18dbcf02cSchristos /*
28dbcf02cSchristos  * WPA Supplicant - command line interface for wpa_supplicant daemon
3*0dddab58Schristos  * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
5da2e293dSchristos  * This software may be distributed under the terms of the BSD license.
6da2e293dSchristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos 
118dbcf02cSchristos #ifdef CONFIG_CTRL_IFACE
128dbcf02cSchristos 
138dbcf02cSchristos #ifdef CONFIG_CTRL_IFACE_UNIX
148dbcf02cSchristos #include <dirent.h>
158dbcf02cSchristos #endif /* CONFIG_CTRL_IFACE_UNIX */
168dbcf02cSchristos 
178d355d6fSchristos #include "common/cli.h"
188dbcf02cSchristos #include "common/wpa_ctrl.h"
1902ec05fbSchristos #include "utils/common.h"
2002ec05fbSchristos #include "utils/eloop.h"
2102ec05fbSchristos #include "utils/edit.h"
2202ec05fbSchristos #include "utils/list.h"
238dbcf02cSchristos #include "common/version.h"
24da2e293dSchristos #include "common/ieee802_11_defs.h"
2502ec05fbSchristos #ifdef ANDROID
2602ec05fbSchristos #include <cutils/properties.h>
2702ec05fbSchristos #endif /* ANDROID */
288dbcf02cSchristos 
298dbcf02cSchristos 
308d355d6fSchristos static const char *const wpa_cli_version =
318dbcf02cSchristos "wpa_cli v" VERSION_STR "\n"
32*0dddab58Schristos "Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors";
338dbcf02cSchristos 
348d355d6fSchristos #define VENDOR_ELEM_FRAME_ID \
358d355d6fSchristos 	"  0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
368d355d6fSchristos 	"3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
378d355d6fSchristos 	"7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \
388d355d6fSchristos 	"11: Assoc Req (P2P), 12: Assoc Resp (P2P)"
398dbcf02cSchristos 
408dbcf02cSchristos static struct wpa_ctrl *ctrl_conn;
418dbcf02cSchristos static struct wpa_ctrl *mon_conn;
428dbcf02cSchristos static int wpa_cli_quit = 0;
438dbcf02cSchristos static int wpa_cli_attached = 0;
44c1f1514dSchristos static int wpa_cli_connected = -1;
458dbcf02cSchristos static int wpa_cli_last_id = 0;
4602ec05fbSchristos #ifndef CONFIG_CTRL_IFACE_DIR
4702ec05fbSchristos #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
4802ec05fbSchristos #endif /* CONFIG_CTRL_IFACE_DIR */
4902ec05fbSchristos static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
508d355d6fSchristos static const char *client_socket_dir = NULL;
518dbcf02cSchristos static char *ctrl_ifname = NULL;
52*0dddab58Schristos static const char *global = NULL;
538dbcf02cSchristos static const char *pid_file = NULL;
548dbcf02cSchristos static const char *action_file = NULL;
558dbcf02cSchristos static int ping_interval = 5;
568dbcf02cSchristos static int interactive = 0;
57c1f1514dSchristos static char *ifname_prefix = NULL;
588dbcf02cSchristos 
5902ec05fbSchristos static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
6002ec05fbSchristos static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
6102ec05fbSchristos static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
62c1f1514dSchristos static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
638d355d6fSchristos static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
64264891a8Schristos static DEFINE_DL_LIST(creds); /* struct cli_txt_entry */
65264891a8Schristos #ifdef CONFIG_AP
66264891a8Schristos static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
67264891a8Schristos #endif /* CONFIG_AP */
6802ec05fbSchristos 
6902ec05fbSchristos 
70da2e293dSchristos static void print_help(const char *cmd);
7102ec05fbSchristos static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
72da2e293dSchristos static void wpa_cli_close_connection(void);
73da2e293dSchristos static char * wpa_cli_get_default_ifname(void);
74da2e293dSchristos static char ** wpa_list_cmd_list(void);
75264891a8Schristos static void update_creds(struct wpa_ctrl *ctrl);
768d355d6fSchristos static void update_networks(struct wpa_ctrl *ctrl);
77264891a8Schristos static void update_stations(struct wpa_ctrl *ctrl);
78*0dddab58Schristos static void update_ifnames(struct wpa_ctrl *ctrl);
798dbcf02cSchristos 
808dbcf02cSchristos 
usage(void)818dbcf02cSchristos static void usage(void)
828dbcf02cSchristos {
838dbcf02cSchristos 	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
848dbcf02cSchristos 	       "[-a<action file>] \\\n"
858dbcf02cSchristos 	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
868d355d6fSchristos 	       "\\\n"
878d355d6fSchristos 	       "        [-s<wpa_client_socket_file_path>] "
888dbcf02cSchristos 	       "[command..]\n"
898dbcf02cSchristos 	       "  -h = help (show this usage text)\n"
908dbcf02cSchristos 	       "  -v = shown version information\n"
918dbcf02cSchristos 	       "  -a = run in daemon mode executing the action file based on "
928dbcf02cSchristos 	       "events from\n"
938dbcf02cSchristos 	       "       wpa_supplicant\n"
948dbcf02cSchristos 	       "  -B = run a daemon in the background\n"
9502ec05fbSchristos 	       "  default path: " CONFIG_CTRL_IFACE_DIR "\n"
968dbcf02cSchristos 	       "  default interface: first interface found in socket path\n");
97da2e293dSchristos 	print_help(NULL);
988dbcf02cSchristos }
998dbcf02cSchristos 
1008dbcf02cSchristos 
wpa_cli_show_event(const char * event)10102ec05fbSchristos static int wpa_cli_show_event(const char *event)
10202ec05fbSchristos {
10302ec05fbSchristos 	const char *start;
10402ec05fbSchristos 
10502ec05fbSchristos 	start = os_strchr(event, '>');
10602ec05fbSchristos 	if (start == NULL)
10702ec05fbSchristos 		return 1;
10802ec05fbSchristos 
10902ec05fbSchristos 	start++;
11002ec05fbSchristos 	/*
11102ec05fbSchristos 	 * Skip BSS added/removed events since they can be relatively frequent
11202ec05fbSchristos 	 * and are likely of not much use for an interactive user.
11302ec05fbSchristos 	 */
11402ec05fbSchristos 	if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
11502ec05fbSchristos 	    str_starts(start, WPA_EVENT_BSS_REMOVED))
11602ec05fbSchristos 		return 0;
11702ec05fbSchristos 
11802ec05fbSchristos 	return 1;
11902ec05fbSchristos }
1208dbcf02cSchristos 
1218dbcf02cSchristos 
wpa_cli_open_connection(const char * ifname,int attach)1228dbcf02cSchristos static int wpa_cli_open_connection(const char *ifname, int attach)
1238dbcf02cSchristos {
1248dbcf02cSchristos #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
1258dbcf02cSchristos 	ctrl_conn = wpa_ctrl_open(ifname);
1268dbcf02cSchristos 	if (ctrl_conn == NULL)
1278dbcf02cSchristos 		return -1;
1288dbcf02cSchristos 
1298dbcf02cSchristos 	if (attach && interactive)
1308dbcf02cSchristos 		mon_conn = wpa_ctrl_open(ifname);
1318dbcf02cSchristos 	else
1328dbcf02cSchristos 		mon_conn = NULL;
1338dbcf02cSchristos #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
13402ec05fbSchristos 	char *cfile = NULL;
1358dbcf02cSchristos 	int flen, res;
1368dbcf02cSchristos 
1378dbcf02cSchristos 	if (ifname == NULL)
1388dbcf02cSchristos 		return -1;
1398dbcf02cSchristos 
14002ec05fbSchristos #ifdef ANDROID
14102ec05fbSchristos 	if (access(ctrl_iface_dir, F_OK) < 0) {
14202ec05fbSchristos 		cfile = os_strdup(ifname);
14302ec05fbSchristos 		if (cfile == NULL)
14402ec05fbSchristos 			return -1;
14502ec05fbSchristos 	}
14602ec05fbSchristos #endif /* ANDROID */
14702ec05fbSchristos 
1488d355d6fSchristos 	if (client_socket_dir && client_socket_dir[0] &&
1498d355d6fSchristos 	    access(client_socket_dir, F_OK) < 0) {
1508d355d6fSchristos 		perror(client_socket_dir);
1518d355d6fSchristos 		os_free(cfile);
1528d355d6fSchristos 		return -1;
1538d355d6fSchristos 	}
1548d355d6fSchristos 
15502ec05fbSchristos 	if (cfile == NULL) {
1568dbcf02cSchristos 		flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
1578dbcf02cSchristos 		cfile = os_malloc(flen);
1588dbcf02cSchristos 		if (cfile == NULL)
15902ec05fbSchristos 			return -1;
16002ec05fbSchristos 		res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
16102ec05fbSchristos 				  ifname);
1629a539354Schristos 		if (os_snprintf_error(flen, res)) {
1638dbcf02cSchristos 			os_free(cfile);
1648dbcf02cSchristos 			return -1;
1658dbcf02cSchristos 		}
16602ec05fbSchristos 	}
1678dbcf02cSchristos 
1688d355d6fSchristos 	ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
1698dbcf02cSchristos 	if (ctrl_conn == NULL) {
1708dbcf02cSchristos 		os_free(cfile);
1718dbcf02cSchristos 		return -1;
1728dbcf02cSchristos 	}
1738dbcf02cSchristos 
1748dbcf02cSchristos 	if (attach && interactive)
1758d355d6fSchristos 		mon_conn = wpa_ctrl_open2(cfile, client_socket_dir);
1768dbcf02cSchristos 	else
1778dbcf02cSchristos 		mon_conn = NULL;
1788dbcf02cSchristos 	os_free(cfile);
1798dbcf02cSchristos #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
1808dbcf02cSchristos 
1818dbcf02cSchristos 	if (mon_conn) {
1828dbcf02cSchristos 		if (wpa_ctrl_attach(mon_conn) == 0) {
1838dbcf02cSchristos 			wpa_cli_attached = 1;
18402ec05fbSchristos 			if (interactive)
18502ec05fbSchristos 				eloop_register_read_sock(
18602ec05fbSchristos 					wpa_ctrl_get_fd(mon_conn),
18702ec05fbSchristos 					wpa_cli_mon_receive, NULL, NULL);
1888dbcf02cSchristos 		} else {
1898dbcf02cSchristos 			printf("Warning: Failed to attach to "
1908dbcf02cSchristos 			       "wpa_supplicant.\n");
191da2e293dSchristos 			wpa_cli_close_connection();
1928dbcf02cSchristos 			return -1;
1938dbcf02cSchristos 		}
1948dbcf02cSchristos 	}
1958dbcf02cSchristos 
1968dbcf02cSchristos 	return 0;
1978dbcf02cSchristos }
1988dbcf02cSchristos 
1998dbcf02cSchristos 
wpa_cli_close_connection(void)2008dbcf02cSchristos static void wpa_cli_close_connection(void)
2018dbcf02cSchristos {
2028dbcf02cSchristos 	if (ctrl_conn == NULL)
2038dbcf02cSchristos 		return;
2048dbcf02cSchristos 
2058dbcf02cSchristos 	if (wpa_cli_attached) {
2068dbcf02cSchristos 		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
2078dbcf02cSchristos 		wpa_cli_attached = 0;
2088dbcf02cSchristos 	}
2098dbcf02cSchristos 	wpa_ctrl_close(ctrl_conn);
2108dbcf02cSchristos 	ctrl_conn = NULL;
2118dbcf02cSchristos 	if (mon_conn) {
21202ec05fbSchristos 		eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
2138dbcf02cSchristos 		wpa_ctrl_close(mon_conn);
2148dbcf02cSchristos 		mon_conn = NULL;
2158dbcf02cSchristos 	}
2168dbcf02cSchristos }
2178dbcf02cSchristos 
skip_priority(const char * msg)218ccfa3bc9Schristos static const char *skip_priority(const char *msg)
219ccfa3bc9Schristos {
220ccfa3bc9Schristos 	const char *pos = msg;
221ccfa3bc9Schristos 
222ccfa3bc9Schristos 	if (*msg != '<')
223ccfa3bc9Schristos 		return msg;
224ccfa3bc9Schristos 
225ccfa3bc9Schristos 	for (pos = msg + 1; isdigit((unsigned char)*pos); pos++)
226ccfa3bc9Schristos 		continue;
227ccfa3bc9Schristos 
228ccfa3bc9Schristos 	if (*pos != '>')
229ccfa3bc9Schristos 		return msg;
230ccfa3bc9Schristos 
231ccfa3bc9Schristos 	return ++pos;
232ccfa3bc9Schristos }
233ccfa3bc9Schristos 
fmttime(char * buf,size_t buflen)234ccfa3bc9Schristos static const char *fmttime(char *buf, size_t buflen)
235ccfa3bc9Schristos {
236ccfa3bc9Schristos 	struct timeval tv;
237ccfa3bc9Schristos 	struct tm tm;
238ccfa3bc9Schristos 	time_t t;
239ccfa3bc9Schristos 
240ccfa3bc9Schristos 	if (buflen <= 8)
241ccfa3bc9Schristos 		return NULL;
242ccfa3bc9Schristos 
243ccfa3bc9Schristos 	(void)gettimeofday(&tv, NULL);
244ccfa3bc9Schristos 	t = (time_t)tv.tv_sec;
245ccfa3bc9Schristos 	(void)localtime_r(&t, &tm);
246ccfa3bc9Schristos 	(void)strftime(buf, buflen, "%H:%M:%S", &tm);
247ccfa3bc9Schristos 	(void)snprintf(buf + 8, buflen - 8, ".%.3d", (int)(tv.tv_usec / 1000));
248ccfa3bc9Schristos 	return buf;
249ccfa3bc9Schristos }
2508dbcf02cSchristos 
wpa_cli_msg_cb(char * msg,size_t len)2518dbcf02cSchristos static void wpa_cli_msg_cb(char *msg, size_t len)
2528dbcf02cSchristos {
253ccfa3bc9Schristos 	char tbuf[32];
254ccfa3bc9Schristos 	printf("%s: %s\n", fmttime(tbuf, sizeof(tbuf)), skip_priority(msg));
2558dbcf02cSchristos }
2568dbcf02cSchristos 
2578dbcf02cSchristos 
_wpa_ctrl_command(struct wpa_ctrl * ctrl,const char * cmd,int print)258264891a8Schristos static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print)
2598dbcf02cSchristos {
260c1f1514dSchristos 	char buf[4096];
2618dbcf02cSchristos 	size_t len;
2628dbcf02cSchristos 	int ret;
2638dbcf02cSchristos 
2648dbcf02cSchristos 	if (ctrl_conn == NULL) {
2658dbcf02cSchristos 		printf("Not connected to wpa_supplicant - command dropped.\n");
2668dbcf02cSchristos 		return -1;
2678dbcf02cSchristos 	}
268c1f1514dSchristos 	if (ifname_prefix) {
269c1f1514dSchristos 		os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
270c1f1514dSchristos 			    ifname_prefix, cmd);
271c1f1514dSchristos 		buf[sizeof(buf) - 1] = '\0';
272c1f1514dSchristos 		cmd = buf;
273c1f1514dSchristos 	}
2748dbcf02cSchristos 	len = sizeof(buf) - 1;
2758dbcf02cSchristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2768dbcf02cSchristos 			       wpa_cli_msg_cb);
2778dbcf02cSchristos 	if (ret == -2) {
2788dbcf02cSchristos 		printf("'%s' command timed out.\n", cmd);
2798dbcf02cSchristos 		return -2;
2808dbcf02cSchristos 	} else if (ret < 0) {
2818dbcf02cSchristos 		printf("'%s' command failed.\n", cmd);
2828dbcf02cSchristos 		return -1;
2838dbcf02cSchristos 	}
2848dbcf02cSchristos 	if (print) {
2858dbcf02cSchristos 		buf[len] = '\0';
286ccfa3bc9Schristos 		wpa_cli_msg_cb(buf, 0);
2878dbcf02cSchristos 	}
2888dbcf02cSchristos 	return 0;
2898dbcf02cSchristos }
2908dbcf02cSchristos 
2918dbcf02cSchristos 
wpa_ctrl_command(struct wpa_ctrl * ctrl,const char * cmd)292264891a8Schristos static int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd)
2938dbcf02cSchristos {
2948dbcf02cSchristos 	return _wpa_ctrl_command(ctrl, cmd, 1);
2958dbcf02cSchristos }
2968dbcf02cSchristos 
2978dbcf02cSchristos 
wpa_cli_cmd(struct wpa_ctrl * ctrl,const char * cmd,int min_args,int argc,char * argv[])298da2e293dSchristos static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
299da2e293dSchristos 		       int argc, char *argv[])
300da2e293dSchristos {
301c1f1514dSchristos 	char buf[4096];
302da2e293dSchristos 	if (argc < min_args) {
303da2e293dSchristos 		printf("Invalid %s command - at least %d argument%s "
304da2e293dSchristos 		       "required.\n", cmd, min_args,
305da2e293dSchristos 		       min_args > 1 ? "s are" : " is");
306da2e293dSchristos 		return -1;
307da2e293dSchristos 	}
308da2e293dSchristos 	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
309da2e293dSchristos 		return -1;
310da2e293dSchristos 	return wpa_ctrl_command(ctrl, buf);
311da2e293dSchristos }
312da2e293dSchristos 
313da2e293dSchristos 
wpa_cli_cmd_ifname(struct wpa_ctrl * ctrl,int argc,char * argv[])314da2e293dSchristos static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
315da2e293dSchristos {
316da2e293dSchristos 	return wpa_ctrl_command(ctrl, "IFNAME");
317da2e293dSchristos }
318da2e293dSchristos 
319da2e293dSchristos 
wpa_cli_cmd_status(struct wpa_ctrl * ctrl,int argc,char * argv[])3208dbcf02cSchristos static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
3218dbcf02cSchristos {
322da2e293dSchristos 	if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
323da2e293dSchristos 		return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
324da2e293dSchristos 	if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
325da2e293dSchristos 		return wpa_ctrl_command(ctrl, "STATUS-WPS");
326c1f1514dSchristos 	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
327c1f1514dSchristos 		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
3288d355d6fSchristos #ifdef ANDROID
3298d355d6fSchristos 	if (argc > 0 && os_strcmp(argv[0], "no_events") == 0)
3308d355d6fSchristos 		return wpa_ctrl_command(ctrl, "STATUS-NO_EVENTS");
3318d355d6fSchristos #endif /* ANDROID */
332da2e293dSchristos 	return wpa_ctrl_command(ctrl, "STATUS");
3338dbcf02cSchristos }
3348dbcf02cSchristos 
3358dbcf02cSchristos 
wpa_cli_cmd_ping(struct wpa_ctrl * ctrl,int argc,char * argv[])3368dbcf02cSchristos static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
3378dbcf02cSchristos {
3388dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "PING");
3398dbcf02cSchristos }
3408dbcf02cSchristos 
3418dbcf02cSchristos 
wpa_cli_cmd_relog(struct wpa_ctrl * ctrl,int argc,char * argv[])34202ec05fbSchristos static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
34302ec05fbSchristos {
34402ec05fbSchristos 	return wpa_ctrl_command(ctrl, "RELOG");
34502ec05fbSchristos }
34602ec05fbSchristos 
34702ec05fbSchristos 
wpa_cli_cmd_note(struct wpa_ctrl * ctrl,int argc,char * argv[])34802ec05fbSchristos static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
34902ec05fbSchristos {
350da2e293dSchristos 	return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
35102ec05fbSchristos }
35202ec05fbSchristos 
35302ec05fbSchristos 
wpa_cli_cmd_mib(struct wpa_ctrl * ctrl,int argc,char * argv[])3548dbcf02cSchristos static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
3558dbcf02cSchristos {
3568dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "MIB");
3578dbcf02cSchristos }
3588dbcf02cSchristos 
3598dbcf02cSchristos 
wpa_cli_cmd_pmksa(struct wpa_ctrl * ctrl,int argc,char * argv[])3608dbcf02cSchristos static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
3618dbcf02cSchristos {
3628dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "PMKSA");
3638dbcf02cSchristos }
3648dbcf02cSchristos 
3658dbcf02cSchristos 
wpa_cli_cmd_pmksa_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])366c1f1514dSchristos static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
367c1f1514dSchristos 				   char *argv[])
368c1f1514dSchristos {
369c1f1514dSchristos 	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
370c1f1514dSchristos }
371c1f1514dSchristos 
372c1f1514dSchristos 
373264891a8Schristos #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
374264891a8Schristos 
wpa_cli_cmd_pmksa_get(struct wpa_ctrl * ctrl,int argc,char * argv[])375264891a8Schristos static int wpa_cli_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
376264891a8Schristos {
377264891a8Schristos 	return wpa_cli_cmd(ctrl, "PMKSA_GET", 1, argc, argv);
378264891a8Schristos }
379264891a8Schristos 
380264891a8Schristos 
wpa_cli_cmd_pmksa_add(struct wpa_ctrl * ctrl,int argc,char * argv[])381264891a8Schristos static int wpa_cli_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, char *argv[])
382264891a8Schristos {
383264891a8Schristos 	return wpa_cli_cmd(ctrl, "PMKSA_ADD", 8, argc, argv);
384264891a8Schristos }
385264891a8Schristos 
386264891a8Schristos 
387264891a8Schristos #ifdef CONFIG_MESH
388264891a8Schristos 
wpa_cli_mesh_cmd_pmksa_get(struct wpa_ctrl * ctrl,int argc,char * argv[])389264891a8Schristos static int wpa_cli_mesh_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc,
390264891a8Schristos 				      char *argv[])
391264891a8Schristos {
392264891a8Schristos 	return wpa_cli_cmd(ctrl, "MESH_PMKSA_GET", 1, argc, argv);
393264891a8Schristos }
394264891a8Schristos 
395264891a8Schristos 
wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl * ctrl,int argc,char * argv[])396264891a8Schristos static int wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc,
397264891a8Schristos 				      char *argv[])
398264891a8Schristos {
399264891a8Schristos 	return wpa_cli_cmd(ctrl, "MESH_PMKSA_ADD", 4, argc, argv);
400264891a8Schristos }
401264891a8Schristos 
402264891a8Schristos #endif /* CONFIG_MESH */
403264891a8Schristos #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
404264891a8Schristos 
405264891a8Schristos 
wpa_cli_cmd_help(struct wpa_ctrl * ctrl,int argc,char * argv[])4068dbcf02cSchristos static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
4078dbcf02cSchristos {
408da2e293dSchristos 	print_help(argc > 0 ? argv[0] : NULL);
4098dbcf02cSchristos 	return 0;
4108dbcf02cSchristos }
4118dbcf02cSchristos 
4128dbcf02cSchristos 
wpa_cli_complete_help(const char * str,int pos)413da2e293dSchristos static char ** wpa_cli_complete_help(const char *str, int pos)
414da2e293dSchristos {
415da2e293dSchristos 	int arg = get_cmd_arg_num(str, pos);
416da2e293dSchristos 	char **res = NULL;
417da2e293dSchristos 
418da2e293dSchristos 	switch (arg) {
419da2e293dSchristos 	case 1:
420da2e293dSchristos 		res = wpa_list_cmd_list();
421da2e293dSchristos 		break;
422da2e293dSchristos 	}
423da2e293dSchristos 
424da2e293dSchristos 	return res;
425da2e293dSchristos }
426da2e293dSchristos 
427da2e293dSchristos 
wpa_cli_cmd_license(struct wpa_ctrl * ctrl,int argc,char * argv[])4288dbcf02cSchristos static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
4298dbcf02cSchristos {
4308d355d6fSchristos 	printf("%s\n\n%s\n", wpa_cli_version, cli_full_license);
4318dbcf02cSchristos 	return 0;
4328dbcf02cSchristos }
4338dbcf02cSchristos 
4348dbcf02cSchristos 
wpa_cli_cmd_quit(struct wpa_ctrl * ctrl,int argc,char * argv[])4358dbcf02cSchristos static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
4368dbcf02cSchristos {
4378dbcf02cSchristos 	wpa_cli_quit = 1;
43802ec05fbSchristos 	if (interactive)
43902ec05fbSchristos 		eloop_terminate();
4408dbcf02cSchristos 	return 0;
4418dbcf02cSchristos }
4428dbcf02cSchristos 
4438dbcf02cSchristos 
wpa_cli_cmd_set(struct wpa_ctrl * ctrl,int argc,char * argv[])4448dbcf02cSchristos static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
4458dbcf02cSchristos {
4468dbcf02cSchristos 	char cmd[256];
4478dbcf02cSchristos 	int res;
4488dbcf02cSchristos 
449c1f1514dSchristos 	if (argc == 1) {
45002ec05fbSchristos 		res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
4519a539354Schristos 		if (os_snprintf_error(sizeof(cmd), res)) {
4528dbcf02cSchristos 			printf("Too long SET command.\n");
4538dbcf02cSchristos 			return -1;
4548dbcf02cSchristos 		}
4558dbcf02cSchristos 		return wpa_ctrl_command(ctrl, cmd);
4568dbcf02cSchristos 	}
4578dbcf02cSchristos 
458c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
459c1f1514dSchristos }
460c1f1514dSchristos 
461c1f1514dSchristos 
wpa_cli_complete_set(const char * str,int pos)462c1f1514dSchristos static char ** wpa_cli_complete_set(const char *str, int pos)
463c1f1514dSchristos {
464c1f1514dSchristos 	int arg = get_cmd_arg_num(str, pos);
465c1f1514dSchristos 	const char *fields[] = {
466c1f1514dSchristos 		/* runtime values */
467c1f1514dSchristos 		"EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
468c1f1514dSchristos 		"EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
469c1f1514dSchristos 		"dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
470c1f1514dSchristos 		"wps_fragment_size", "wps_version_number", "ampdu",
471c1f1514dSchristos 		"tdls_testing", "tdls_disabled", "pno", "radio_disabled",
472c1f1514dSchristos 		"uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
473c1f1514dSchristos 		"no_keep_alive",
474c1f1514dSchristos 		/* global configuration parameters */
4758d355d6fSchristos #ifdef CONFIG_CTRL_IFACE
4768d355d6fSchristos 		"ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
4778d355d6fSchristos #endif /* CONFIG_CTRL_IFACE */
4788d355d6fSchristos 		"eapol_version", "ap_scan", "bgscan",
4798d355d6fSchristos #ifdef CONFIG_MESH
4808d355d6fSchristos 		"user_mpm", "max_peer_links", "mesh_max_inactivity",
4818d355d6fSchristos 		"dot11RSNASAERetransPeriod",
4828d355d6fSchristos #endif /* CONFIG_MESH */
4838d355d6fSchristos 		"disable_scan_offload", "fast_reauth", "opensc_engine_path",
4848d355d6fSchristos 		"pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
4858d355d6fSchristos 		"pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
4868d355d6fSchristos 		"dot11RSNAConfigPMKLifetime",
487c1f1514dSchristos 		"dot11RSNAConfigPMKReauthThreshold",
488c1f1514dSchristos 		"dot11RSNAConfigSATimeout",
4898d355d6fSchristos #ifndef CONFIG_NO_CONFIG_WRITE
4908d355d6fSchristos 		"update_config",
4918d355d6fSchristos #endif /* CONFIG_NO_CONFIG_WRITE */
4928d355d6fSchristos 		"load_dynamic_eap",
4938d355d6fSchristos #ifdef CONFIG_WPS
4948d355d6fSchristos 		"uuid", "device_name", "manufacturer", "model_name",
4958d355d6fSchristos 		"model_number", "serial_number", "device_type", "os_version",
4968d355d6fSchristos 		"config_methods", "wps_cred_processing", "wps_vendor_ext_m1",
4978d355d6fSchristos #endif /* CONFIG_WPS */
4988d355d6fSchristos #ifdef CONFIG_P2P
4998d355d6fSchristos 		"sec_device_type",
500c1f1514dSchristos 		"p2p_listen_reg_class", "p2p_listen_channel",
5018d355d6fSchristos 		"p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
5028d355d6fSchristos 		"p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
5038d355d6fSchristos 		"p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan",
5048d355d6fSchristos 		"p2p_no_go_freq", "p2p_add_cli_chan",
5058d355d6fSchristos 		"p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
5068d355d6fSchristos 		"p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
5078d355d6fSchristos 		"p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
5088d355d6fSchristos 		"ip_addr_start", "ip_addr_end",
5098d355d6fSchristos #endif /* CONFIG_P2P */
5108d355d6fSchristos 		"country", "bss_max_count", "bss_expiration_age",
5118d355d6fSchristos 		"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
512264891a8Schristos 		"max_num_sta", "disassoc_low_ack", "ap_isolate",
5138d355d6fSchristos #ifdef CONFIG_HS20
5148d355d6fSchristos 		"hs20",
5158d355d6fSchristos #endif /* CONFIG_HS20 */
5168d355d6fSchristos 		"interworking", "hessid", "access_network_type", "pbc_in_m1",
517264891a8Schristos 		"go_interworking", "go_access_network_type", "go_internet",
518264891a8Schristos 		"go_venue_group", "go_venue_type",
5198d355d6fSchristos 		"autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
5208d355d6fSchristos 		"wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
521c1f1514dSchristos 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
5228d355d6fSchristos 		"sae_groups", "dtim_period", "beacon_int",
5238d355d6fSchristos 		"ap_vendor_elements", "ignore_old_scan_res", "freq_list",
5248d355d6fSchristos 		"scan_cur_freq", "sched_scan_interval",
5258d355d6fSchristos 		"tdls_external_control", "osu_dir", "wowlan_triggers",
5268d355d6fSchristos 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
5278d355d6fSchristos 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
5288d355d6fSchristos 		"reassoc_same_bss_optim", "wps_priority",
5298d355d6fSchristos #ifdef CONFIG_TESTING_OPTIONS
5308d355d6fSchristos 		"ignore_auth_resp",
5318d355d6fSchristos #endif /* CONFIG_TESTING_OPTIONS */
532264891a8Schristos 		"relative_rssi", "relative_band_adjust",
533c1f1514dSchristos 	};
534c1f1514dSchristos 	int i, num_fields = ARRAY_SIZE(fields);
535c1f1514dSchristos 
536c1f1514dSchristos 	if (arg == 1) {
537c1f1514dSchristos 		char **res = os_calloc(num_fields + 1, sizeof(char *));
538c1f1514dSchristos 		if (res == NULL)
539c1f1514dSchristos 			return NULL;
540c1f1514dSchristos 		for (i = 0; i < num_fields; i++) {
541c1f1514dSchristos 			res[i] = os_strdup(fields[i]);
542c1f1514dSchristos 			if (res[i] == NULL)
543c1f1514dSchristos 				return res;
544c1f1514dSchristos 		}
545c1f1514dSchristos 		return res;
546c1f1514dSchristos 	}
547c1f1514dSchristos 
548c1f1514dSchristos 	if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
549c1f1514dSchristos 		return cli_txt_list_array(&bsses);
550c1f1514dSchristos 
551c1f1514dSchristos 	return NULL;
552c1f1514dSchristos }
553c1f1514dSchristos 
wpa_cli_cmd_dump(struct wpa_ctrl * ctrl,int argc,char * argv[])5549a539354Schristos static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
5559a539354Schristos {
5569a539354Schristos 	return wpa_ctrl_command(ctrl, "DUMP");
5579a539354Schristos }
5589a539354Schristos 
5598dbcf02cSchristos 
wpa_cli_cmd_driver_flags(struct wpa_ctrl * ctrl,int argc,char * argv[])5608d355d6fSchristos static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
5618d355d6fSchristos 				    char *argv[])
5628d355d6fSchristos {
5638d355d6fSchristos 	return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
5648d355d6fSchristos }
5658d355d6fSchristos 
5668d355d6fSchristos 
wpa_cli_cmd_get(struct wpa_ctrl * ctrl,int argc,char * argv[])56702ec05fbSchristos static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
56802ec05fbSchristos {
569da2e293dSchristos 	return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
57002ec05fbSchristos }
57102ec05fbSchristos 
57202ec05fbSchristos 
wpa_cli_complete_get(const char * str,int pos)5738d355d6fSchristos static char ** wpa_cli_complete_get(const char *str, int pos)
5748d355d6fSchristos {
5758d355d6fSchristos 	int arg = get_cmd_arg_num(str, pos);
5768d355d6fSchristos 	const char *fields[] = {
5778d355d6fSchristos #ifdef CONFIG_CTRL_IFACE
5788d355d6fSchristos 		"ctrl_interface", "ctrl_interface_group",
5798d355d6fSchristos #endif /* CONFIG_CTRL_IFACE */
5808d355d6fSchristos 		"eapol_version", "ap_scan",
5818d355d6fSchristos #ifdef CONFIG_MESH
5828d355d6fSchristos 		"user_mpm", "max_peer_links", "mesh_max_inactivity",
5838d355d6fSchristos #endif /* CONFIG_MESH */
5848d355d6fSchristos 		"disable_scan_offload", "fast_reauth", "opensc_engine_path",
5858d355d6fSchristos 		"pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
5868d355d6fSchristos 		"pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
5878d355d6fSchristos 		"dot11RSNAConfigPMKLifetime",
5888d355d6fSchristos 		"dot11RSNAConfigPMKReauthThreshold",
5898d355d6fSchristos 		"dot11RSNAConfigSATimeout",
5908d355d6fSchristos #ifndef CONFIG_NO_CONFIG_WRITE
5918d355d6fSchristos 		"update_config",
5928d355d6fSchristos #endif /* CONFIG_NO_CONFIG_WRITE */
5938d355d6fSchristos #ifdef CONFIG_WPS
5948d355d6fSchristos 		"device_name", "manufacturer", "model_name", "model_number",
5958d355d6fSchristos 		"serial_number", "config_methods", "wps_cred_processing",
5968d355d6fSchristos #endif /* CONFIG_WPS */
5978d355d6fSchristos #ifdef CONFIG_P2P
5988d355d6fSchristos 		"p2p_listen_reg_class", "p2p_listen_channel",
5998d355d6fSchristos 		"p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
6008d355d6fSchristos 		"p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
6018d355d6fSchristos 		"p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
6028d355d6fSchristos 		"p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
6038d355d6fSchristos 		"p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
6048d355d6fSchristos 		"p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
6058d355d6fSchristos 		"ip_addr_start", "ip_addr_end",
6068d355d6fSchristos #endif /* CONFIG_P2P */
6078d355d6fSchristos 		"bss_max_count", "bss_expiration_age",
6088d355d6fSchristos 		"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
609264891a8Schristos 		"max_num_sta", "disassoc_low_ack", "ap_isolate",
6108d355d6fSchristos #ifdef CONFIG_HS20
6118d355d6fSchristos 		"hs20",
6128d355d6fSchristos #endif /* CONFIG_HS20 */
6138d355d6fSchristos 		"interworking", "access_network_type", "pbc_in_m1", "autoscan",
614264891a8Schristos 		"go_interworking", "go_access_network_type", "go_internet",
615264891a8Schristos 		"go_venue_group", "go_venue_type",
6168d355d6fSchristos 		"wps_nfc_dev_pw_id", "ext_password_backend",
6178d355d6fSchristos 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
6188d355d6fSchristos 		"dtim_period", "beacon_int", "ignore_old_scan_res",
6198d355d6fSchristos 		"scan_cur_freq", "sched_scan_interval",
620264891a8Schristos 		"sched_scan_start_delay",
6218d355d6fSchristos 		"tdls_external_control", "osu_dir", "wowlan_triggers",
6228d355d6fSchristos 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
6238d355d6fSchristos 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
6248d355d6fSchristos 		"reassoc_same_bss_optim"
6258d355d6fSchristos 	};
6268d355d6fSchristos 	int i, num_fields = ARRAY_SIZE(fields);
6278d355d6fSchristos 
6288d355d6fSchristos 	if (arg == 1) {
6298d355d6fSchristos 		char **res = os_calloc(num_fields + 1, sizeof(char *));
6308d355d6fSchristos 		if (res == NULL)
6318d355d6fSchristos 			return NULL;
6328d355d6fSchristos 		for (i = 0; i < num_fields; i++) {
6338d355d6fSchristos 			res[i] = os_strdup(fields[i]);
6348d355d6fSchristos 			if (res[i] == NULL)
6358d355d6fSchristos 				return res;
6368d355d6fSchristos 		}
6378d355d6fSchristos 		return res;
6388d355d6fSchristos 	}
6398d355d6fSchristos 
6408d355d6fSchristos 	return NULL;
6418d355d6fSchristos }
6428d355d6fSchristos 
6438d355d6fSchristos 
wpa_cli_cmd_logoff(struct wpa_ctrl * ctrl,int argc,char * argv[])6448dbcf02cSchristos static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
6458dbcf02cSchristos {
6468dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "LOGOFF");
6478dbcf02cSchristos }
6488dbcf02cSchristos 
6498dbcf02cSchristos 
wpa_cli_cmd_logon(struct wpa_ctrl * ctrl,int argc,char * argv[])6508dbcf02cSchristos static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
6518dbcf02cSchristos {
6528dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "LOGON");
6538dbcf02cSchristos }
6548dbcf02cSchristos 
6558dbcf02cSchristos 
wpa_cli_cmd_reassociate(struct wpa_ctrl * ctrl,int argc,char * argv[])6568dbcf02cSchristos static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
6578dbcf02cSchristos 				   char *argv[])
6588dbcf02cSchristos {
6598dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "REASSOCIATE");
6608dbcf02cSchristos }
6618dbcf02cSchristos 
6628dbcf02cSchristos 
wpa_cli_cmd_reattach(struct wpa_ctrl * ctrl,int argc,char * argv[])663c1f1514dSchristos static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
664c1f1514dSchristos {
665c1f1514dSchristos 	return wpa_ctrl_command(ctrl, "REATTACH");
666c1f1514dSchristos }
667c1f1514dSchristos 
668c1f1514dSchristos 
wpa_cli_cmd_preauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])6698dbcf02cSchristos static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
6708dbcf02cSchristos 				       char *argv[])
6718dbcf02cSchristos {
672da2e293dSchristos 	return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
6738dbcf02cSchristos }
6748dbcf02cSchristos 
6758dbcf02cSchristos 
wpa_cli_cmd_ap_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])6768dbcf02cSchristos static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
6778dbcf02cSchristos {
678da2e293dSchristos 	return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
6798dbcf02cSchristos }
6808dbcf02cSchristos 
6818dbcf02cSchristos 
wpa_cli_cmd_scan_interval(struct wpa_ctrl * ctrl,int argc,char * argv[])68202ec05fbSchristos static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
68302ec05fbSchristos 				     char *argv[])
68402ec05fbSchristos {
685da2e293dSchristos 	return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
68602ec05fbSchristos }
68702ec05fbSchristos 
68802ec05fbSchristos 
wpa_cli_cmd_bss_expire_age(struct wpa_ctrl * ctrl,int argc,char * argv[])68902ec05fbSchristos static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
69002ec05fbSchristos 				      char *argv[])
69102ec05fbSchristos {
692da2e293dSchristos 	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
69302ec05fbSchristos }
69402ec05fbSchristos 
69502ec05fbSchristos 
wpa_cli_cmd_bss_expire_count(struct wpa_ctrl * ctrl,int argc,char * argv[])69602ec05fbSchristos static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
69702ec05fbSchristos 				        char *argv[])
69802ec05fbSchristos {
699da2e293dSchristos 	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
700da2e293dSchristos }
701da2e293dSchristos 
702da2e293dSchristos 
wpa_cli_cmd_bss_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])703da2e293dSchristos static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
704da2e293dSchristos {
70502ec05fbSchristos 	char cmd[256];
70602ec05fbSchristos 	int res;
70702ec05fbSchristos 
708da2e293dSchristos 	if (argc < 1)
709da2e293dSchristos 		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
710da2e293dSchristos 	else
711da2e293dSchristos 		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
7129a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res)) {
713da2e293dSchristos 		printf("Too long BSS_FLUSH command.\n");
71402ec05fbSchristos 		return -1;
71502ec05fbSchristos 	}
71602ec05fbSchristos 	return wpa_ctrl_command(ctrl, cmd);
71702ec05fbSchristos }
71802ec05fbSchristos 
71902ec05fbSchristos 
wpa_cli_cmd_ft_ds(struct wpa_ctrl * ctrl,int argc,char * argv[])7208dbcf02cSchristos static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
7218dbcf02cSchristos {
722da2e293dSchristos 	return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
7238dbcf02cSchristos }
7248dbcf02cSchristos 
7258dbcf02cSchristos 
wpa_cli_cmd_wps_pbc(struct wpa_ctrl * ctrl,int argc,char * argv[])7268dbcf02cSchristos static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
7278dbcf02cSchristos {
728da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
7298dbcf02cSchristos }
7308dbcf02cSchristos 
7318dbcf02cSchristos 
wpa_cli_cmd_wps_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])7328dbcf02cSchristos static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
7338dbcf02cSchristos {
7348dbcf02cSchristos 	if (argc == 0) {
7358dbcf02cSchristos 		printf("Invalid WPS_PIN command: need one or two arguments:\n"
7368dbcf02cSchristos 		       "- BSSID: use 'any' to select any\n"
7378dbcf02cSchristos 		       "- PIN: optional, used only with devices that have no "
7388dbcf02cSchristos 		       "display\n");
7398dbcf02cSchristos 		return -1;
7408dbcf02cSchristos 	}
7418dbcf02cSchristos 
742da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
7438dbcf02cSchristos }
7448dbcf02cSchristos 
7458dbcf02cSchristos 
wpa_cli_cmd_wps_check_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])74602ec05fbSchristos static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
74702ec05fbSchristos 				     char *argv[])
74802ec05fbSchristos {
749da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
75002ec05fbSchristos }
75102ec05fbSchristos 
75202ec05fbSchristos 
wpa_cli_cmd_wps_cancel(struct wpa_ctrl * ctrl,int argc,char * argv[])75302ec05fbSchristos static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
75402ec05fbSchristos 				  char *argv[])
75502ec05fbSchristos {
75602ec05fbSchristos 	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
75702ec05fbSchristos }
75802ec05fbSchristos 
75902ec05fbSchristos 
760da2e293dSchristos #ifdef CONFIG_WPS_NFC
761da2e293dSchristos 
wpa_cli_cmd_wps_nfc(struct wpa_ctrl * ctrl,int argc,char * argv[])762da2e293dSchristos static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
7638dbcf02cSchristos {
764da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
765da2e293dSchristos }
7668dbcf02cSchristos 
767da2e293dSchristos 
wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl * ctrl,int argc,char * argv[])768c1f1514dSchristos static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
769c1f1514dSchristos 					    char *argv[])
770c1f1514dSchristos {
771c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
772c1f1514dSchristos }
773c1f1514dSchristos 
774c1f1514dSchristos 
wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl * ctrl,int argc,char * argv[])775da2e293dSchristos static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
776da2e293dSchristos 				     char *argv[])
777da2e293dSchristos {
778da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
779da2e293dSchristos }
780da2e293dSchristos 
781da2e293dSchristos 
wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl * ctrl,int argc,char * argv[])782da2e293dSchristos static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
783da2e293dSchristos 					char *argv[])
784da2e293dSchristos {
785da2e293dSchristos 	int ret;
786da2e293dSchristos 	char *buf;
787da2e293dSchristos 	size_t buflen;
788da2e293dSchristos 
789da2e293dSchristos 	if (argc != 1) {
790da2e293dSchristos 		printf("Invalid 'wps_nfc_tag_read' command - one argument "
791da2e293dSchristos 		       "is required.\n");
7928dbcf02cSchristos 		return -1;
7938dbcf02cSchristos 	}
7948dbcf02cSchristos 
795da2e293dSchristos 	buflen = 18 + os_strlen(argv[0]);
796da2e293dSchristos 	buf = os_malloc(buflen);
797da2e293dSchristos 	if (buf == NULL)
798da2e293dSchristos 		return -1;
799da2e293dSchristos 	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
800da2e293dSchristos 
801da2e293dSchristos 	ret = wpa_ctrl_command(ctrl, buf);
802da2e293dSchristos 	os_free(buf);
803da2e293dSchristos 
804da2e293dSchristos 	return ret;
805da2e293dSchristos }
806da2e293dSchristos 
807da2e293dSchristos 
wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl * ctrl,int argc,char * argv[])808da2e293dSchristos static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
809da2e293dSchristos 					    char *argv[])
810da2e293dSchristos {
811da2e293dSchristos 	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
812da2e293dSchristos }
813da2e293dSchristos 
814da2e293dSchristos 
wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl * ctrl,int argc,char * argv[])815da2e293dSchristos static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
816da2e293dSchristos 					    char *argv[])
817da2e293dSchristos {
818da2e293dSchristos 	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
819da2e293dSchristos }
820da2e293dSchristos 
821da2e293dSchristos 
wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl * ctrl,int argc,char * argv[])822c1f1514dSchristos static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
823da2e293dSchristos 					   char *argv[])
824da2e293dSchristos {
825c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
826da2e293dSchristos }
827da2e293dSchristos 
828da2e293dSchristos #endif /* CONFIG_WPS_NFC */
8298dbcf02cSchristos 
8308dbcf02cSchristos 
wpa_cli_cmd_wps_reg(struct wpa_ctrl * ctrl,int argc,char * argv[])8318dbcf02cSchristos static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
8328dbcf02cSchristos {
8338dbcf02cSchristos 	char cmd[256];
8348dbcf02cSchristos 	int res;
8358dbcf02cSchristos 
8368dbcf02cSchristos 	if (argc == 2)
8378dbcf02cSchristos 		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
8388dbcf02cSchristos 				  argv[0], argv[1]);
83902ec05fbSchristos 	else if (argc == 5 || argc == 6) {
8408d355d6fSchristos 		char ssid_hex[2 * SSID_MAX_LEN + 1];
8418dbcf02cSchristos 		char key_hex[2 * 64 + 1];
8428dbcf02cSchristos 		int i;
8438dbcf02cSchristos 
8448dbcf02cSchristos 		ssid_hex[0] = '\0';
8458d355d6fSchristos 		for (i = 0; i < SSID_MAX_LEN; i++) {
8468dbcf02cSchristos 			if (argv[2][i] == '\0')
8478dbcf02cSchristos 				break;
8488dbcf02cSchristos 			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
8498dbcf02cSchristos 		}
8508dbcf02cSchristos 
8518dbcf02cSchristos 		key_hex[0] = '\0';
85202ec05fbSchristos 		if (argc == 6) {
8538dbcf02cSchristos 			for (i = 0; i < 64; i++) {
8548dbcf02cSchristos 				if (argv[5][i] == '\0')
8558dbcf02cSchristos 					break;
85602ec05fbSchristos 				os_snprintf(&key_hex[i * 2], 3, "%02x",
85702ec05fbSchristos 					    argv[5][i]);
85802ec05fbSchristos 			}
8598dbcf02cSchristos 		}
8608dbcf02cSchristos 
8618dbcf02cSchristos 		res = os_snprintf(cmd, sizeof(cmd),
8628dbcf02cSchristos 				  "WPS_REG %s %s %s %s %s %s",
8638dbcf02cSchristos 				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
8648dbcf02cSchristos 				  key_hex);
8658dbcf02cSchristos 	} else {
8668dbcf02cSchristos 		printf("Invalid WPS_REG command: need two arguments:\n"
86702ec05fbSchristos 		       "- BSSID of the target AP\n"
8688dbcf02cSchristos 		       "- AP PIN\n");
8698dbcf02cSchristos 		printf("Alternatively, six arguments can be used to "
8708dbcf02cSchristos 		       "reconfigure the AP:\n"
87102ec05fbSchristos 		       "- BSSID of the target AP\n"
8728dbcf02cSchristos 		       "- AP PIN\n"
8738dbcf02cSchristos 		       "- new SSID\n"
8748dbcf02cSchristos 		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
8758dbcf02cSchristos 		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
8768dbcf02cSchristos 		       "- new key\n");
8778dbcf02cSchristos 		return -1;
8788dbcf02cSchristos 	}
8798dbcf02cSchristos 
8809a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res)) {
8818dbcf02cSchristos 		printf("Too long WPS_REG command.\n");
8828dbcf02cSchristos 		return -1;
8838dbcf02cSchristos 	}
8848dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
8858dbcf02cSchristos }
8868dbcf02cSchristos 
8878dbcf02cSchristos 
wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])88802ec05fbSchristos static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
88902ec05fbSchristos 				  char *argv[])
89002ec05fbSchristos {
891da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
89202ec05fbSchristos }
89302ec05fbSchristos 
89402ec05fbSchristos 
wpa_cli_cmd_wps_er_start(struct wpa_ctrl * ctrl,int argc,char * argv[])8958dbcf02cSchristos static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
8968dbcf02cSchristos 				    char *argv[])
8978dbcf02cSchristos {
898da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
8998dbcf02cSchristos }
9008dbcf02cSchristos 
9018dbcf02cSchristos 
wpa_cli_cmd_wps_er_stop(struct wpa_ctrl * ctrl,int argc,char * argv[])9028dbcf02cSchristos static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
9038dbcf02cSchristos 				   char *argv[])
9048dbcf02cSchristos {
9058dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
9068dbcf02cSchristos 
9078dbcf02cSchristos }
9088dbcf02cSchristos 
9098dbcf02cSchristos 
wpa_cli_cmd_wps_er_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])9108dbcf02cSchristos static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
9118dbcf02cSchristos 				  char *argv[])
9128dbcf02cSchristos {
91302ec05fbSchristos 	if (argc < 2) {
91402ec05fbSchristos 		printf("Invalid WPS_ER_PIN command: need at least two "
91502ec05fbSchristos 		       "arguments:\n"
9168dbcf02cSchristos 		       "- UUID: use 'any' to select any\n"
91702ec05fbSchristos 		       "- PIN: Enrollee PIN\n"
91802ec05fbSchristos 		       "optional: - Enrollee MAC address\n");
9198dbcf02cSchristos 		return -1;
9208dbcf02cSchristos 	}
9218dbcf02cSchristos 
922da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
9238dbcf02cSchristos }
9248dbcf02cSchristos 
9258dbcf02cSchristos 
wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl * ctrl,int argc,char * argv[])9268dbcf02cSchristos static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
9278dbcf02cSchristos 				  char *argv[])
9288dbcf02cSchristos {
929da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
9308dbcf02cSchristos }
9318dbcf02cSchristos 
9328dbcf02cSchristos 
wpa_cli_cmd_wps_er_learn(struct wpa_ctrl * ctrl,int argc,char * argv[])9338dbcf02cSchristos static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
9348dbcf02cSchristos 				    char *argv[])
9358dbcf02cSchristos {
9368dbcf02cSchristos 	if (argc != 2) {
9378dbcf02cSchristos 		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
9388dbcf02cSchristos 		       "- UUID: specify which AP to use\n"
9398dbcf02cSchristos 		       "- PIN: AP PIN\n");
9408dbcf02cSchristos 		return -1;
9418dbcf02cSchristos 	}
9428dbcf02cSchristos 
943da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
9448dbcf02cSchristos }
9458dbcf02cSchristos 
9468dbcf02cSchristos 
wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl * ctrl,int argc,char * argv[])94702ec05fbSchristos static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
94802ec05fbSchristos 					 char *argv[])
94902ec05fbSchristos {
95002ec05fbSchristos 	if (argc != 2) {
95102ec05fbSchristos 		printf("Invalid WPS_ER_SET_CONFIG command: need two "
95202ec05fbSchristos 		       "arguments:\n"
95302ec05fbSchristos 		       "- UUID: specify which AP to use\n"
95402ec05fbSchristos 		       "- Network configuration id\n");
95502ec05fbSchristos 		return -1;
95602ec05fbSchristos 	}
95702ec05fbSchristos 
958da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
95902ec05fbSchristos }
96002ec05fbSchristos 
96102ec05fbSchristos 
wpa_cli_cmd_wps_er_config(struct wpa_ctrl * ctrl,int argc,char * argv[])96202ec05fbSchristos static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
96302ec05fbSchristos 				     char *argv[])
96402ec05fbSchristos {
96502ec05fbSchristos 	char cmd[256];
96602ec05fbSchristos 	int res;
96702ec05fbSchristos 
96802ec05fbSchristos 	if (argc == 5 || argc == 6) {
9698d355d6fSchristos 		char ssid_hex[2 * SSID_MAX_LEN + 1];
97002ec05fbSchristos 		char key_hex[2 * 64 + 1];
97102ec05fbSchristos 		int i;
97202ec05fbSchristos 
97302ec05fbSchristos 		ssid_hex[0] = '\0';
9748d355d6fSchristos 		for (i = 0; i < SSID_MAX_LEN; i++) {
97502ec05fbSchristos 			if (argv[2][i] == '\0')
97602ec05fbSchristos 				break;
97702ec05fbSchristos 			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
97802ec05fbSchristos 		}
97902ec05fbSchristos 
98002ec05fbSchristos 		key_hex[0] = '\0';
98102ec05fbSchristos 		if (argc == 6) {
98202ec05fbSchristos 			for (i = 0; i < 64; i++) {
98302ec05fbSchristos 				if (argv[5][i] == '\0')
98402ec05fbSchristos 					break;
98502ec05fbSchristos 				os_snprintf(&key_hex[i * 2], 3, "%02x",
98602ec05fbSchristos 					    argv[5][i]);
98702ec05fbSchristos 			}
98802ec05fbSchristos 		}
98902ec05fbSchristos 
99002ec05fbSchristos 		res = os_snprintf(cmd, sizeof(cmd),
99102ec05fbSchristos 				  "WPS_ER_CONFIG %s %s %s %s %s %s",
99202ec05fbSchristos 				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
99302ec05fbSchristos 				  key_hex);
99402ec05fbSchristos 	} else {
99502ec05fbSchristos 		printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
99602ec05fbSchristos 		       "- AP UUID\n"
99702ec05fbSchristos 		       "- AP PIN\n"
99802ec05fbSchristos 		       "- new SSID\n"
99902ec05fbSchristos 		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
100002ec05fbSchristos 		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
100102ec05fbSchristos 		       "- new key\n");
100202ec05fbSchristos 		return -1;
100302ec05fbSchristos 	}
100402ec05fbSchristos 
10059a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res)) {
100602ec05fbSchristos 		printf("Too long WPS_ER_CONFIG command.\n");
100702ec05fbSchristos 		return -1;
100802ec05fbSchristos 	}
100902ec05fbSchristos 	return wpa_ctrl_command(ctrl, cmd);
101002ec05fbSchristos }
101102ec05fbSchristos 
101202ec05fbSchristos 
1013da2e293dSchristos #ifdef CONFIG_WPS_NFC
wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl * ctrl,int argc,char * argv[])1014da2e293dSchristos static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1015da2e293dSchristos 					       char *argv[])
1016da2e293dSchristos {
1017da2e293dSchristos 	if (argc != 2) {
1018da2e293dSchristos 		printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1019da2e293dSchristos 		       "arguments:\n"
1020da2e293dSchristos 		       "- WPS/NDEF: token format\n"
1021da2e293dSchristos 		       "- UUID: specify which AP to use\n");
1022da2e293dSchristos 		return -1;
1023da2e293dSchristos 	}
1024da2e293dSchristos 
1025da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1026da2e293dSchristos }
1027da2e293dSchristos #endif /* CONFIG_WPS_NFC */
1028da2e293dSchristos 
1029da2e293dSchristos 
wpa_cli_cmd_ibss_rsn(struct wpa_ctrl * ctrl,int argc,char * argv[])10308dbcf02cSchristos static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
10318dbcf02cSchristos {
1032da2e293dSchristos 	return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
10338dbcf02cSchristos }
10348dbcf02cSchristos 
10358dbcf02cSchristos 
wpa_cli_cmd_level(struct wpa_ctrl * ctrl,int argc,char * argv[])10368dbcf02cSchristos static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
10378dbcf02cSchristos {
1038da2e293dSchristos 	return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
10398dbcf02cSchristos }
10408dbcf02cSchristos 
10418dbcf02cSchristos 
wpa_cli_cmd_identity(struct wpa_ctrl * ctrl,int argc,char * argv[])10428dbcf02cSchristos static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
10438dbcf02cSchristos {
10448dbcf02cSchristos 	char cmd[256], *pos, *end;
10458dbcf02cSchristos 	int i, ret;
10468dbcf02cSchristos 
10478dbcf02cSchristos 	if (argc < 2) {
10488dbcf02cSchristos 		printf("Invalid IDENTITY command: needs two arguments "
10498dbcf02cSchristos 		       "(network id and identity)\n");
10508dbcf02cSchristos 		return -1;
10518dbcf02cSchristos 	}
10528dbcf02cSchristos 
10538dbcf02cSchristos 	end = cmd + sizeof(cmd);
10548dbcf02cSchristos 	pos = cmd;
10558dbcf02cSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
10568dbcf02cSchristos 			  argv[0], argv[1]);
10579a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
10588dbcf02cSchristos 		printf("Too long IDENTITY command.\n");
10598dbcf02cSchristos 		return -1;
10608dbcf02cSchristos 	}
10618dbcf02cSchristos 	pos += ret;
10628dbcf02cSchristos 	for (i = 2; i < argc; i++) {
10638dbcf02cSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
10649a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
10658dbcf02cSchristos 			printf("Too long IDENTITY command.\n");
10668dbcf02cSchristos 			return -1;
10678dbcf02cSchristos 		}
10688dbcf02cSchristos 		pos += ret;
10698dbcf02cSchristos 	}
10708dbcf02cSchristos 
10718dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
10728dbcf02cSchristos }
10738dbcf02cSchristos 
10748dbcf02cSchristos 
wpa_cli_cmd_password(struct wpa_ctrl * ctrl,int argc,char * argv[])10758dbcf02cSchristos static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
10768dbcf02cSchristos {
10778dbcf02cSchristos 	char cmd[256], *pos, *end;
10788dbcf02cSchristos 	int i, ret;
10798dbcf02cSchristos 
10808dbcf02cSchristos 	if (argc < 2) {
10818dbcf02cSchristos 		printf("Invalid PASSWORD command: needs two arguments "
10828dbcf02cSchristos 		       "(network id and password)\n");
10838dbcf02cSchristos 		return -1;
10848dbcf02cSchristos 	}
10858dbcf02cSchristos 
10868dbcf02cSchristos 	end = cmd + sizeof(cmd);
10878dbcf02cSchristos 	pos = cmd;
10888dbcf02cSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
10898dbcf02cSchristos 			  argv[0], argv[1]);
10909a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
10918dbcf02cSchristos 		printf("Too long PASSWORD command.\n");
10928dbcf02cSchristos 		return -1;
10938dbcf02cSchristos 	}
10948dbcf02cSchristos 	pos += ret;
10958dbcf02cSchristos 	for (i = 2; i < argc; i++) {
10968dbcf02cSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
10979a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
10988dbcf02cSchristos 			printf("Too long PASSWORD command.\n");
10998dbcf02cSchristos 			return -1;
11008dbcf02cSchristos 		}
11018dbcf02cSchristos 		pos += ret;
11028dbcf02cSchristos 	}
11038dbcf02cSchristos 
11048dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
11058dbcf02cSchristos }
11068dbcf02cSchristos 
11078dbcf02cSchristos 
wpa_cli_cmd_new_password(struct wpa_ctrl * ctrl,int argc,char * argv[])11088dbcf02cSchristos static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
11098dbcf02cSchristos 				    char *argv[])
11108dbcf02cSchristos {
11118dbcf02cSchristos 	char cmd[256], *pos, *end;
11128dbcf02cSchristos 	int i, ret;
11138dbcf02cSchristos 
11148dbcf02cSchristos 	if (argc < 2) {
11158dbcf02cSchristos 		printf("Invalid NEW_PASSWORD command: needs two arguments "
11168dbcf02cSchristos 		       "(network id and password)\n");
11178dbcf02cSchristos 		return -1;
11188dbcf02cSchristos 	}
11198dbcf02cSchristos 
11208dbcf02cSchristos 	end = cmd + sizeof(cmd);
11218dbcf02cSchristos 	pos = cmd;
11228dbcf02cSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
11238dbcf02cSchristos 			  argv[0], argv[1]);
11249a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
11258dbcf02cSchristos 		printf("Too long NEW_PASSWORD command.\n");
11268dbcf02cSchristos 		return -1;
11278dbcf02cSchristos 	}
11288dbcf02cSchristos 	pos += ret;
11298dbcf02cSchristos 	for (i = 2; i < argc; i++) {
11308dbcf02cSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
11319a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
11328dbcf02cSchristos 			printf("Too long NEW_PASSWORD command.\n");
11338dbcf02cSchristos 			return -1;
11348dbcf02cSchristos 		}
11358dbcf02cSchristos 		pos += ret;
11368dbcf02cSchristos 	}
11378dbcf02cSchristos 
11388dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
11398dbcf02cSchristos }
11408dbcf02cSchristos 
11418dbcf02cSchristos 
wpa_cli_cmd_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])11428dbcf02cSchristos static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
11438dbcf02cSchristos {
11448dbcf02cSchristos 	char cmd[256], *pos, *end;
11458dbcf02cSchristos 	int i, ret;
11468dbcf02cSchristos 
11478dbcf02cSchristos 	if (argc < 2) {
11488dbcf02cSchristos 		printf("Invalid PIN command: needs two arguments "
11498dbcf02cSchristos 		       "(network id and pin)\n");
11508dbcf02cSchristos 		return -1;
11518dbcf02cSchristos 	}
11528dbcf02cSchristos 
11538dbcf02cSchristos 	end = cmd + sizeof(cmd);
11548dbcf02cSchristos 	pos = cmd;
11558dbcf02cSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
11568dbcf02cSchristos 			  argv[0], argv[1]);
11579a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
11588dbcf02cSchristos 		printf("Too long PIN command.\n");
11598dbcf02cSchristos 		return -1;
11608dbcf02cSchristos 	}
11618dbcf02cSchristos 	pos += ret;
11628dbcf02cSchristos 	for (i = 2; i < argc; i++) {
11638dbcf02cSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
11649a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
11658dbcf02cSchristos 			printf("Too long PIN command.\n");
11668dbcf02cSchristos 			return -1;
11678dbcf02cSchristos 		}
11688dbcf02cSchristos 		pos += ret;
11698dbcf02cSchristos 	}
11708dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
11718dbcf02cSchristos }
11728dbcf02cSchristos 
11738dbcf02cSchristos 
wpa_cli_cmd_otp(struct wpa_ctrl * ctrl,int argc,char * argv[])11748dbcf02cSchristos static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
11758dbcf02cSchristos {
11768dbcf02cSchristos 	char cmd[256], *pos, *end;
11778dbcf02cSchristos 	int i, ret;
11788dbcf02cSchristos 
11798dbcf02cSchristos 	if (argc < 2) {
11808dbcf02cSchristos 		printf("Invalid OTP command: needs two arguments (network "
11818dbcf02cSchristos 		       "id and password)\n");
11828dbcf02cSchristos 		return -1;
11838dbcf02cSchristos 	}
11848dbcf02cSchristos 
11858dbcf02cSchristos 	end = cmd + sizeof(cmd);
11868dbcf02cSchristos 	pos = cmd;
11878dbcf02cSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
11888dbcf02cSchristos 			  argv[0], argv[1]);
11899a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
11908dbcf02cSchristos 		printf("Too long OTP command.\n");
11918dbcf02cSchristos 		return -1;
11928dbcf02cSchristos 	}
11938dbcf02cSchristos 	pos += ret;
11948dbcf02cSchristos 	for (i = 2; i < argc; i++) {
11958dbcf02cSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
11969a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
11978dbcf02cSchristos 			printf("Too long OTP command.\n");
11988dbcf02cSchristos 			return -1;
11998dbcf02cSchristos 		}
12008dbcf02cSchristos 		pos += ret;
12018dbcf02cSchristos 	}
12028dbcf02cSchristos 
12038dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
12048dbcf02cSchristos }
12058dbcf02cSchristos 
12068dbcf02cSchristos 
wpa_cli_cmd_sim(struct wpa_ctrl * ctrl,int argc,char * argv[])1207c1f1514dSchristos static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1208c1f1514dSchristos {
1209c1f1514dSchristos 	char cmd[256], *pos, *end;
1210c1f1514dSchristos 	int i, ret;
1211c1f1514dSchristos 
1212c1f1514dSchristos 	if (argc < 2) {
1213c1f1514dSchristos 		printf("Invalid SIM command: needs two arguments "
1214c1f1514dSchristos 		       "(network id and SIM operation response)\n");
1215c1f1514dSchristos 		return -1;
1216c1f1514dSchristos 	}
1217c1f1514dSchristos 
1218c1f1514dSchristos 	end = cmd + sizeof(cmd);
1219c1f1514dSchristos 	pos = cmd;
1220c1f1514dSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1221c1f1514dSchristos 			  argv[0], argv[1]);
12229a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
1223c1f1514dSchristos 		printf("Too long SIM command.\n");
1224c1f1514dSchristos 		return -1;
1225c1f1514dSchristos 	}
1226c1f1514dSchristos 	pos += ret;
1227c1f1514dSchristos 	for (i = 2; i < argc; i++) {
1228c1f1514dSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
12299a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
1230c1f1514dSchristos 			printf("Too long SIM command.\n");
1231c1f1514dSchristos 			return -1;
1232c1f1514dSchristos 		}
1233c1f1514dSchristos 		pos += ret;
1234c1f1514dSchristos 	}
1235c1f1514dSchristos 	return wpa_ctrl_command(ctrl, cmd);
1236c1f1514dSchristos }
1237c1f1514dSchristos 
1238c1f1514dSchristos 
wpa_cli_cmd_psk_passphrase(struct wpa_ctrl * ctrl,int argc,char * argv[])1239*0dddab58Schristos static int wpa_cli_cmd_psk_passphrase(struct wpa_ctrl *ctrl, int argc,
1240*0dddab58Schristos 				      char *argv[])
1241*0dddab58Schristos {
1242*0dddab58Schristos 	char cmd[256], *pos, *end;
1243*0dddab58Schristos 	int i, ret;
1244*0dddab58Schristos 
1245*0dddab58Schristos 	if (argc < 2) {
1246*0dddab58Schristos 		printf("Invalid PSK_PASSPHRASE command: needs two arguments (network id and PSK/passphrase)\n");
1247*0dddab58Schristos 		return -1;
1248*0dddab58Schristos 	}
1249*0dddab58Schristos 
1250*0dddab58Schristos 	end = cmd + sizeof(cmd);
1251*0dddab58Schristos 	pos = cmd;
1252*0dddab58Schristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PSK_PASSPHRASE-%s:%s",
1253*0dddab58Schristos 			  argv[0], argv[1]);
1254*0dddab58Schristos 	if (os_snprintf_error(end - pos, ret)) {
1255*0dddab58Schristos 		printf("Too long PSK_PASSPHRASE command.\n");
1256*0dddab58Schristos 		return -1;
1257*0dddab58Schristos 	}
1258*0dddab58Schristos 	pos += ret;
1259*0dddab58Schristos 	for (i = 2; i < argc; i++) {
1260*0dddab58Schristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1261*0dddab58Schristos 		if (os_snprintf_error(end - pos, ret)) {
1262*0dddab58Schristos 			printf("Too long PSK_PASSPHRASE command.\n");
1263*0dddab58Schristos 			return -1;
1264*0dddab58Schristos 		}
1265*0dddab58Schristos 		pos += ret;
1266*0dddab58Schristos 	}
1267*0dddab58Schristos 
1268*0dddab58Schristos 	return wpa_ctrl_command(ctrl, cmd);
1269*0dddab58Schristos }
1270*0dddab58Schristos 
1271*0dddab58Schristos 
wpa_cli_cmd_passphrase(struct wpa_ctrl * ctrl,int argc,char * argv[])12728dbcf02cSchristos static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
12738dbcf02cSchristos 				  char *argv[])
12748dbcf02cSchristos {
12758dbcf02cSchristos 	char cmd[256], *pos, *end;
12768dbcf02cSchristos 	int i, ret;
12778dbcf02cSchristos 
12788dbcf02cSchristos 	if (argc < 2) {
12798dbcf02cSchristos 		printf("Invalid PASSPHRASE command: needs two arguments "
12808dbcf02cSchristos 		       "(network id and passphrase)\n");
12818dbcf02cSchristos 		return -1;
12828dbcf02cSchristos 	}
12838dbcf02cSchristos 
12848dbcf02cSchristos 	end = cmd + sizeof(cmd);
12858dbcf02cSchristos 	pos = cmd;
12868dbcf02cSchristos 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
12878dbcf02cSchristos 			  argv[0], argv[1]);
12889a539354Schristos 	if (os_snprintf_error(end - pos, ret)) {
12898dbcf02cSchristos 		printf("Too long PASSPHRASE command.\n");
12908dbcf02cSchristos 		return -1;
12918dbcf02cSchristos 	}
12928dbcf02cSchristos 	pos += ret;
12938dbcf02cSchristos 	for (i = 2; i < argc; i++) {
12948dbcf02cSchristos 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
12959a539354Schristos 		if (os_snprintf_error(end - pos, ret)) {
12968dbcf02cSchristos 			printf("Too long PASSPHRASE command.\n");
12978dbcf02cSchristos 			return -1;
12988dbcf02cSchristos 		}
12998dbcf02cSchristos 		pos += ret;
13008dbcf02cSchristos 	}
13018dbcf02cSchristos 
13028dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
13038dbcf02cSchristos }
13048dbcf02cSchristos 
13058dbcf02cSchristos 
wpa_cli_cmd_bssid(struct wpa_ctrl * ctrl,int argc,char * argv[])13068dbcf02cSchristos static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
13078dbcf02cSchristos {
13088dbcf02cSchristos 	if (argc < 2) {
13098dbcf02cSchristos 		printf("Invalid BSSID command: needs two arguments (network "
13108dbcf02cSchristos 		       "id and BSSID)\n");
13118dbcf02cSchristos 		return -1;
13128dbcf02cSchristos 	}
13138dbcf02cSchristos 
1314da2e293dSchristos 	return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
13158dbcf02cSchristos }
13168dbcf02cSchristos 
13178dbcf02cSchristos 
wpa_cli_cmd_blacklist(struct wpa_ctrl * ctrl,int argc,char * argv[])131802ec05fbSchristos static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
131902ec05fbSchristos {
1320da2e293dSchristos 	return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
132102ec05fbSchristos }
132202ec05fbSchristos 
132302ec05fbSchristos 
wpa_cli_cmd_log_level(struct wpa_ctrl * ctrl,int argc,char * argv[])132402ec05fbSchristos static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
132502ec05fbSchristos {
1326da2e293dSchristos 	return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
132702ec05fbSchristos }
132802ec05fbSchristos 
132902ec05fbSchristos 
wpa_cli_cmd_list_networks(struct wpa_ctrl * ctrl,int argc,char * argv[])13308dbcf02cSchristos static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
13318dbcf02cSchristos 				     char *argv[])
13328dbcf02cSchristos {
13338dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
13348dbcf02cSchristos }
13358dbcf02cSchristos 
13368dbcf02cSchristos 
wpa_cli_cmd_select_network(struct wpa_ctrl * ctrl,int argc,char * argv[])13378dbcf02cSchristos static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
13388dbcf02cSchristos 				      char *argv[])
13398dbcf02cSchristos {
1340da2e293dSchristos 	return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
13418dbcf02cSchristos }
13428dbcf02cSchristos 
13438dbcf02cSchristos 
wpa_cli_cmd_enable_network(struct wpa_ctrl * ctrl,int argc,char * argv[])13448dbcf02cSchristos static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
13458dbcf02cSchristos 				      char *argv[])
13468dbcf02cSchristos {
1347da2e293dSchristos 	return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
13488dbcf02cSchristos }
13498dbcf02cSchristos 
13508dbcf02cSchristos 
wpa_cli_cmd_disable_network(struct wpa_ctrl * ctrl,int argc,char * argv[])13518dbcf02cSchristos static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
13528dbcf02cSchristos 				       char *argv[])
13538dbcf02cSchristos {
1354da2e293dSchristos 	return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
13558dbcf02cSchristos }
13568dbcf02cSchristos 
13578dbcf02cSchristos 
wpa_cli_cmd_add_network(struct wpa_ctrl * ctrl,int argc,char * argv[])13588dbcf02cSchristos static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
13598dbcf02cSchristos 				   char *argv[])
13608dbcf02cSchristos {
13618d355d6fSchristos 	int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
13628d355d6fSchristos 	if (interactive)
13638d355d6fSchristos 		update_networks(ctrl);
13648d355d6fSchristos 	return res;
13658dbcf02cSchristos }
13668dbcf02cSchristos 
13678dbcf02cSchristos 
wpa_cli_cmd_remove_network(struct wpa_ctrl * ctrl,int argc,char * argv[])13688dbcf02cSchristos static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
13698dbcf02cSchristos 				      char *argv[])
13708dbcf02cSchristos {
13718d355d6fSchristos 	int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
13728d355d6fSchristos 	if (interactive)
13738d355d6fSchristos 		update_networks(ctrl);
13748d355d6fSchristos 	return res;
13758dbcf02cSchristos }
13768dbcf02cSchristos 
13778dbcf02cSchristos 
wpa_cli_show_network_variables(void)13788dbcf02cSchristos static void wpa_cli_show_network_variables(void)
13798dbcf02cSchristos {
13808dbcf02cSchristos 	printf("set_network variables:\n"
13818dbcf02cSchristos 	       "  ssid (network name, SSID)\n"
13828dbcf02cSchristos 	       "  psk (WPA passphrase or pre-shared key)\n"
13838dbcf02cSchristos 	       "  key_mgmt (key management protocol)\n"
13848dbcf02cSchristos 	       "  identity (EAP identity)\n"
13858dbcf02cSchristos 	       "  password (EAP password)\n"
13868dbcf02cSchristos 	       "  ...\n"
13878dbcf02cSchristos 	       "\n"
13888dbcf02cSchristos 	       "Note: Values are entered in the same format as the "
13898dbcf02cSchristos 	       "configuration file is using,\n"
13908dbcf02cSchristos 	       "i.e., strings values need to be inside double quotation "
13918dbcf02cSchristos 	       "marks.\n"
13928dbcf02cSchristos 	       "For example: set_network 1 ssid \"network name\"\n"
13938dbcf02cSchristos 	       "\n"
13948dbcf02cSchristos 	       "Please see wpa_supplicant.conf documentation for full list "
13958dbcf02cSchristos 	       "of\navailable variables.\n");
13968dbcf02cSchristos }
13978dbcf02cSchristos 
13988dbcf02cSchristos 
wpa_cli_cmd_set_network(struct wpa_ctrl * ctrl,int argc,char * argv[])13998dbcf02cSchristos static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
14008dbcf02cSchristos 				   char *argv[])
14018dbcf02cSchristos {
14028dbcf02cSchristos 	if (argc == 0) {
14038dbcf02cSchristos 		wpa_cli_show_network_variables();
14048dbcf02cSchristos 		return 0;
14058dbcf02cSchristos 	}
14068dbcf02cSchristos 
1407da2e293dSchristos 	if (argc < 3) {
14088dbcf02cSchristos 		printf("Invalid SET_NETWORK command: needs three arguments\n"
14098dbcf02cSchristos 		       "(network id, variable name, and value)\n");
14108dbcf02cSchristos 		return -1;
14118dbcf02cSchristos 	}
14128dbcf02cSchristos 
1413da2e293dSchristos 	return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
14148dbcf02cSchristos }
14158dbcf02cSchristos 
14168dbcf02cSchristos 
wpa_cli_cmd_get_network(struct wpa_ctrl * ctrl,int argc,char * argv[])14178dbcf02cSchristos static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
14188dbcf02cSchristos 				   char *argv[])
14198dbcf02cSchristos {
14208dbcf02cSchristos 	if (argc == 0) {
14218dbcf02cSchristos 		wpa_cli_show_network_variables();
14228dbcf02cSchristos 		return 0;
14238dbcf02cSchristos 	}
14248dbcf02cSchristos 
14258dbcf02cSchristos 	if (argc != 2) {
14268dbcf02cSchristos 		printf("Invalid GET_NETWORK command: needs two arguments\n"
14278dbcf02cSchristos 		       "(network id and variable name)\n");
14288dbcf02cSchristos 		return -1;
14298dbcf02cSchristos 	}
14308dbcf02cSchristos 
1431da2e293dSchristos 	return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1432da2e293dSchristos }
1433da2e293dSchristos 
1434da2e293dSchristos 
14358d355d6fSchristos static const char *network_fields[] = {
14368d355d6fSchristos 	"ssid", "scan_ssid", "bssid", "bssid_blacklist",
14378d355d6fSchristos 	"bssid_whitelist", "psk", "proto", "key_mgmt",
14388d355d6fSchristos 	"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
1439264891a8Schristos 	"freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1",
1440264891a8Schristos 	"vht_center_freq2", "ht",
14418d355d6fSchristos #ifdef IEEE8021X_EAPOL
14428d355d6fSchristos 	"eap", "identity", "anonymous_identity", "password", "ca_cert",
14438d355d6fSchristos 	"ca_path", "client_cert", "private_key", "private_key_passwd",
14448d355d6fSchristos 	"dh_file", "subject_match", "altsubject_match",
1445*0dddab58Schristos 	"check_cert_subject",
14468d355d6fSchristos 	"domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
14478d355d6fSchristos 	"client_cert2", "private_key2", "private_key2_passwd",
14488d355d6fSchristos 	"dh_file2", "subject_match2", "altsubject_match2",
1449*0dddab58Schristos 	"check_cert_subject2",
14508d355d6fSchristos 	"domain_suffix_match2", "domain_match2", "phase1", "phase2",
14518d355d6fSchristos 	"pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
14528d355d6fSchristos 	"pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
14538d355d6fSchristos 	"engine", "engine2", "eapol_flags", "sim_num",
14548d355d6fSchristos 	"openssl_ciphers", "erp",
14558d355d6fSchristos #endif /* IEEE8021X_EAPOL */
14568d355d6fSchristos 	"wep_key0", "wep_key1", "wep_key2", "wep_key3",
14578d355d6fSchristos 	"wep_tx_keyidx", "priority",
14588d355d6fSchristos #ifdef IEEE8021X_EAPOL
14598d355d6fSchristos 	"eap_workaround", "pac_file", "fragment_size", "ocsp",
14608d355d6fSchristos #endif /* IEEE8021X_EAPOL */
14618d355d6fSchristos #ifdef CONFIG_MESH
1462264891a8Schristos 	"mode", "no_auto_peer", "mesh_rssi_threshold",
14638d355d6fSchristos #else /* CONFIG_MESH */
14648d355d6fSchristos 	"mode",
14658d355d6fSchristos #endif /* CONFIG_MESH */
14668d355d6fSchristos 	"proactive_key_caching", "disabled", "id_str",
14678d355d6fSchristos #ifdef CONFIG_IEEE80211W
14688d355d6fSchristos 	"ieee80211w",
14698d355d6fSchristos #endif /* CONFIG_IEEE80211W */
1470264891a8Schristos 	"mixed_cell", "frequency", "fixed_freq",
14718d355d6fSchristos #ifdef CONFIG_MESH
14728d355d6fSchristos 	"mesh_basic_rates", "dot11MeshMaxRetries",
14738d355d6fSchristos 	"dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
14748d355d6fSchristos 	"dot11MeshHoldingTimeout",
14758d355d6fSchristos #endif /* CONFIG_MESH */
14768d355d6fSchristos 	"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
14778d355d6fSchristos #ifdef CONFIG_P2P
14788d355d6fSchristos 	"go_p2p_dev_addr", "p2p_client_list", "psk_list",
14798d355d6fSchristos #endif /* CONFIG_P2P */
14808d355d6fSchristos #ifdef CONFIG_HT_OVERRIDES
14818d355d6fSchristos 	"disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
14828d355d6fSchristos 	"ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
1483*0dddab58Schristos 	"ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc",
14848d355d6fSchristos #endif /* CONFIG_HT_OVERRIDES */
14858d355d6fSchristos #ifdef CONFIG_VHT_OVERRIDES
14868d355d6fSchristos 	"disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
14878d355d6fSchristos 	"vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
14888d355d6fSchristos 	"vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
14898d355d6fSchristos 	"vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
14908d355d6fSchristos 	"vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
14918d355d6fSchristos 	"vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
14928d355d6fSchristos #endif /* CONFIG_VHT_OVERRIDES */
14938d355d6fSchristos 	"ap_max_inactivity", "dtim_period", "beacon_int",
14948d355d6fSchristos #ifdef CONFIG_MACSEC
14958d355d6fSchristos 	"macsec_policy",
1496264891a8Schristos 	"macsec_integ_only",
1497*0dddab58Schristos 	"macsec_replay_protect",
1498*0dddab58Schristos 	"macsec_replay_window",
1499264891a8Schristos 	"macsec_port",
1500264891a8Schristos 	"mka_priority",
15018d355d6fSchristos #endif /* CONFIG_MACSEC */
15028d355d6fSchristos #ifdef CONFIG_HS20
15038d355d6fSchristos 	"update_identifier",
15048d355d6fSchristos #endif /* CONFIG_HS20 */
15058d355d6fSchristos 	"mac_addr", "pbss", "wps_disabled"
15068d355d6fSchristos };
15078d355d6fSchristos 
15088d355d6fSchristos 
wpa_cli_complete_network(const char * str,int pos)15098d355d6fSchristos static char ** wpa_cli_complete_network(const char *str, int pos)
15108d355d6fSchristos {
15118d355d6fSchristos 	int arg = get_cmd_arg_num(str, pos);
15128d355d6fSchristos 	int i, num_fields = ARRAY_SIZE(network_fields);
15138d355d6fSchristos 	char **res = NULL;
15148d355d6fSchristos 
15158d355d6fSchristos 	switch (arg) {
15168d355d6fSchristos 	case 1:
15178d355d6fSchristos 		res = cli_txt_list_array(&networks);
15188d355d6fSchristos 		break;
15198d355d6fSchristos 	case 2:
15208d355d6fSchristos 		res = os_calloc(num_fields + 1, sizeof(char *));
15218d355d6fSchristos 		if (res == NULL)
15228d355d6fSchristos 			return NULL;
15238d355d6fSchristos 		for (i = 0; i < num_fields; i++) {
15248d355d6fSchristos 			res[i] = os_strdup(network_fields[i]);
15258d355d6fSchristos 			if (res[i] == NULL)
15268d355d6fSchristos 				break;
15278d355d6fSchristos 		}
15288d355d6fSchristos 	}
15298d355d6fSchristos 	return res;
15308d355d6fSchristos }
15318d355d6fSchristos 
15328d355d6fSchristos 
wpa_cli_complete_network_id(const char * str,int pos)15338d355d6fSchristos static char ** wpa_cli_complete_network_id(const char *str, int pos)
15348d355d6fSchristos {
15358d355d6fSchristos 	int arg = get_cmd_arg_num(str, pos);
15368d355d6fSchristos 	if (arg == 1)
15378d355d6fSchristos 		return cli_txt_list_array(&networks);
15388d355d6fSchristos 	return NULL;
15398d355d6fSchristos }
15408d355d6fSchristos 
15418d355d6fSchristos 
wpa_cli_cmd_dup_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1542c1f1514dSchristos static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1543c1f1514dSchristos 				   char *argv[])
1544c1f1514dSchristos {
1545c1f1514dSchristos 	if (argc == 0) {
1546c1f1514dSchristos 		wpa_cli_show_network_variables();
1547c1f1514dSchristos 		return 0;
1548c1f1514dSchristos 	}
1549c1f1514dSchristos 
1550c1f1514dSchristos 	if (argc < 3) {
1551c1f1514dSchristos 		printf("Invalid DUP_NETWORK command: needs three arguments\n"
1552c1f1514dSchristos 		       "(src netid, dest netid, and variable name)\n");
1553c1f1514dSchristos 		return -1;
1554c1f1514dSchristos 	}
1555c1f1514dSchristos 
1556c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1557c1f1514dSchristos }
1558c1f1514dSchristos 
1559c1f1514dSchristos 
wpa_cli_complete_dup_network(const char * str,int pos)15608d355d6fSchristos static char ** wpa_cli_complete_dup_network(const char *str, int pos)
15618d355d6fSchristos {
15628d355d6fSchristos 	int arg = get_cmd_arg_num(str, pos);
15638d355d6fSchristos 	int i, num_fields = ARRAY_SIZE(network_fields);
15648d355d6fSchristos 	char **res = NULL;
15658d355d6fSchristos 
15668d355d6fSchristos 	switch (arg) {
15678d355d6fSchristos 	case 1:
15688d355d6fSchristos 	case 2:
15698d355d6fSchristos 		res = cli_txt_list_array(&networks);
15708d355d6fSchristos 		break;
15718d355d6fSchristos 	case 3:
15728d355d6fSchristos 		res = os_calloc(num_fields + 1, sizeof(char *));
15738d355d6fSchristos 		if (res == NULL)
15748d355d6fSchristos 			return NULL;
15758d355d6fSchristos 		for (i = 0; i < num_fields; i++) {
15768d355d6fSchristos 			res[i] = os_strdup(network_fields[i]);
15778d355d6fSchristos 			if (res[i] == NULL)
15788d355d6fSchristos 				break;
15798d355d6fSchristos 		}
15808d355d6fSchristos 	}
15818d355d6fSchristos 	return res;
15828d355d6fSchristos }
15838d355d6fSchristos 
15848d355d6fSchristos 
wpa_cli_cmd_list_creds(struct wpa_ctrl * ctrl,int argc,char * argv[])1585da2e293dSchristos static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1586da2e293dSchristos 				  char *argv[])
1587da2e293dSchristos {
1588da2e293dSchristos 	return wpa_ctrl_command(ctrl, "LIST_CREDS");
1589da2e293dSchristos }
1590da2e293dSchristos 
1591da2e293dSchristos 
wpa_cli_cmd_add_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1592da2e293dSchristos static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1593da2e293dSchristos {
1594264891a8Schristos 	int res = wpa_ctrl_command(ctrl, "ADD_CRED");
1595264891a8Schristos 	if (interactive)
1596264891a8Schristos 		update_creds(ctrl);
1597264891a8Schristos 	return res;
1598da2e293dSchristos }
1599da2e293dSchristos 
1600da2e293dSchristos 
wpa_cli_cmd_remove_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1601da2e293dSchristos static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1602da2e293dSchristos 				   char *argv[])
1603da2e293dSchristos {
1604264891a8Schristos 	int res = wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1605264891a8Schristos 	if (interactive)
1606264891a8Schristos 		update_creds(ctrl);
1607264891a8Schristos 	return res;
1608264891a8Schristos }
1609264891a8Schristos 
1610264891a8Schristos 
1611264891a8Schristos static const char * const cred_fields[] = {
1612264891a8Schristos 	"temporary", "priority", "sp_priority", "pcsc", "eap",
1613264891a8Schristos 	"update_identifier", "min_dl_bandwidth_home", "min_ul_bandwidth_home",
1614264891a8Schristos 	"min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
1615264891a8Schristos 	"req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
1616264891a8Schristos 	"ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
1617264891a8Schristos 	"milenage", "domain_suffix_match", "domain", "phase1", "phase2",
1618264891a8Schristos 	"roaming_consortium", "required_roaming_consortium", "excluded_ssid",
1619264891a8Schristos 	"roaming_partner", "provisioning_sp"
1620264891a8Schristos };
1621264891a8Schristos 
1622264891a8Schristos 
wpa_cli_complete_cred(const char * str,int pos)1623264891a8Schristos static char ** wpa_cli_complete_cred(const char *str, int pos)
1624264891a8Schristos {
1625264891a8Schristos 	int arg = get_cmd_arg_num(str, pos);
1626264891a8Schristos 	int i, num_fields = ARRAY_SIZE(cred_fields);
1627264891a8Schristos 	char **res = NULL;
1628264891a8Schristos 
1629264891a8Schristos 	switch (arg) {
1630264891a8Schristos 	case 1:
1631264891a8Schristos 		res = cli_txt_list_array(&creds);
1632264891a8Schristos 		break;
1633264891a8Schristos 	case 2:
1634264891a8Schristos 		res = os_calloc(num_fields + 1, sizeof(char *));
1635264891a8Schristos 		if (res == NULL)
1636264891a8Schristos 			return NULL;
1637264891a8Schristos 		for (i = 0; i < num_fields; i++) {
1638264891a8Schristos 			res[i] = os_strdup(cred_fields[i]);
1639264891a8Schristos 			if (res[i] == NULL)
1640264891a8Schristos 				break;
1641264891a8Schristos 		}
1642264891a8Schristos 	}
1643264891a8Schristos 	return res;
1644da2e293dSchristos }
1645da2e293dSchristos 
1646da2e293dSchristos 
wpa_cli_cmd_set_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1647da2e293dSchristos static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1648da2e293dSchristos {
1649da2e293dSchristos 	if (argc != 3) {
1650da2e293dSchristos 		printf("Invalid SET_CRED command: needs three arguments\n"
1651da2e293dSchristos 		       "(cred id, variable name, and value)\n");
16528dbcf02cSchristos 		return -1;
16538dbcf02cSchristos 	}
1654da2e293dSchristos 
1655da2e293dSchristos 	return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
16568dbcf02cSchristos }
16578dbcf02cSchristos 
16588dbcf02cSchristos 
wpa_cli_cmd_get_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1659c1f1514dSchristos static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1660c1f1514dSchristos {
1661c1f1514dSchristos 	if (argc != 2) {
1662c1f1514dSchristos 		printf("Invalid GET_CRED command: needs two arguments\n"
1663c1f1514dSchristos 		       "(cred id, variable name)\n");
1664c1f1514dSchristos 		return -1;
1665c1f1514dSchristos 	}
1666c1f1514dSchristos 
1667c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1668c1f1514dSchristos }
1669c1f1514dSchristos 
1670c1f1514dSchristos 
wpa_cli_cmd_disconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])16718dbcf02cSchristos static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
16728dbcf02cSchristos 				  char *argv[])
16738dbcf02cSchristos {
16748dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "DISCONNECT");
16758dbcf02cSchristos }
16768dbcf02cSchristos 
16778dbcf02cSchristos 
wpa_cli_cmd_reconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])16788dbcf02cSchristos static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
16798dbcf02cSchristos 				  char *argv[])
16808dbcf02cSchristos {
16818dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "RECONNECT");
16828dbcf02cSchristos }
16838dbcf02cSchristos 
16848dbcf02cSchristos 
wpa_cli_cmd_save_config(struct wpa_ctrl * ctrl,int argc,char * argv[])16858dbcf02cSchristos static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
16868dbcf02cSchristos 				   char *argv[])
16878dbcf02cSchristos {
16888dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
16898dbcf02cSchristos }
16908dbcf02cSchristos 
16918dbcf02cSchristos 
wpa_cli_cmd_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])16928dbcf02cSchristos static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
16938dbcf02cSchristos {
1694c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
16958dbcf02cSchristos }
16968dbcf02cSchristos 
16978dbcf02cSchristos 
wpa_cli_cmd_scan_results(struct wpa_ctrl * ctrl,int argc,char * argv[])16988dbcf02cSchristos static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
16998dbcf02cSchristos 				    char *argv[])
17008dbcf02cSchristos {
17018dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
17028dbcf02cSchristos }
17038dbcf02cSchristos 
17048dbcf02cSchristos 
wpa_cli_cmd_abort_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])17058d355d6fSchristos static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc,
17068d355d6fSchristos 				  char *argv[])
17078d355d6fSchristos {
17088d355d6fSchristos 	return wpa_ctrl_command(ctrl, "ABORT_SCAN");
17098d355d6fSchristos }
17108d355d6fSchristos 
17118d355d6fSchristos 
wpa_cli_cmd_bss(struct wpa_ctrl * ctrl,int argc,char * argv[])17128dbcf02cSchristos static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
17138dbcf02cSchristos {
1714da2e293dSchristos 	return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
17158dbcf02cSchristos }
17168dbcf02cSchristos 
17178dbcf02cSchristos 
wpa_cli_complete_bss(const char * str,int pos)171802ec05fbSchristos static char ** wpa_cli_complete_bss(const char *str, int pos)
171902ec05fbSchristos {
172002ec05fbSchristos 	int arg = get_cmd_arg_num(str, pos);
172102ec05fbSchristos 	char **res = NULL;
172202ec05fbSchristos 
172302ec05fbSchristos 	switch (arg) {
172402ec05fbSchristos 	case 1:
172502ec05fbSchristos 		res = cli_txt_list_array(&bsses);
172602ec05fbSchristos 		break;
172702ec05fbSchristos 	}
172802ec05fbSchristos 
172902ec05fbSchristos 	return res;
173002ec05fbSchristos }
173102ec05fbSchristos 
173202ec05fbSchristos 
wpa_cli_cmd_get_capability(struct wpa_ctrl * ctrl,int argc,char * argv[])17338dbcf02cSchristos static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
17348dbcf02cSchristos 				      char *argv[])
17358dbcf02cSchristos {
17368dbcf02cSchristos 	if (argc < 1 || argc > 2) {
17378dbcf02cSchristos 		printf("Invalid GET_CAPABILITY command: need either one or "
17388dbcf02cSchristos 		       "two arguments\n");
17398dbcf02cSchristos 		return -1;
17408dbcf02cSchristos 	}
17418dbcf02cSchristos 
17428dbcf02cSchristos 	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
17438dbcf02cSchristos 		printf("Invalid GET_CAPABILITY command: second argument, "
17448dbcf02cSchristos 		       "if any, must be 'strict'\n");
17458dbcf02cSchristos 		return -1;
17468dbcf02cSchristos 	}
17478dbcf02cSchristos 
1748da2e293dSchristos 	return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
17498dbcf02cSchristos }
17508dbcf02cSchristos 
17518dbcf02cSchristos 
wpa_cli_complete_get_capability(const char * str,int pos)17528d355d6fSchristos static char ** wpa_cli_complete_get_capability(const char *str, int pos)
17538d355d6fSchristos {
17548d355d6fSchristos 	int arg = get_cmd_arg_num(str, pos);
17558d355d6fSchristos 	const char *fields[] = {
17568d355d6fSchristos 		"eap", "pairwise", "group", "group_mgmt", "key_mgmt",
17578d355d6fSchristos 		"proto", "auth_alg", "modes", "channels", "freq",
17588d355d6fSchristos #ifdef CONFIG_TDLS
17598d355d6fSchristos 		"tdls",
17608d355d6fSchristos #endif /* CONFIG_TDLS */
17618d355d6fSchristos #ifdef CONFIG_ERP
17628d355d6fSchristos 		"erp",
17638d355d6fSchristos #endif /* CONFIG_ERP */
17648d355d6fSchristos #ifdef CONFIG_FIPS
17658d355d6fSchristos 		"fips",
17668d355d6fSchristos #endif /* CONFIG_FIPS */
17678d355d6fSchristos #ifdef CONFIG_ACS
17688d355d6fSchristos 		"acs",
17698d355d6fSchristos #endif /* CONFIG_ACS */
17708d355d6fSchristos 	};
17718d355d6fSchristos 	int i, num_fields = ARRAY_SIZE(fields);
17728d355d6fSchristos 	char **res = NULL;
17738d355d6fSchristos 
17748d355d6fSchristos 	if (arg == 1) {
17758d355d6fSchristos 		res = os_calloc(num_fields + 1, sizeof(char *));
17768d355d6fSchristos 		if (res == NULL)
17778d355d6fSchristos 			return NULL;
17788d355d6fSchristos 		for (i = 0; i < num_fields; i++) {
17798d355d6fSchristos 			res[i] = os_strdup(fields[i]);
17808d355d6fSchristos 			if (res[i] == NULL)
17818d355d6fSchristos 				return res;
17828d355d6fSchristos 		}
17838d355d6fSchristos 	}
17848d355d6fSchristos 	if (arg == 2) {
17858d355d6fSchristos 		res = os_calloc(1 + 1, sizeof(char *));
17868d355d6fSchristos 		if (res == NULL)
17878d355d6fSchristos 			return NULL;
17888d355d6fSchristos 		res[0] = os_strdup("strict");
17898d355d6fSchristos 	}
17908d355d6fSchristos 	return res;
17918d355d6fSchristos }
17928d355d6fSchristos 
17938d355d6fSchristos 
wpa_cli_list_interfaces(struct wpa_ctrl * ctrl)17948dbcf02cSchristos static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
17958dbcf02cSchristos {
17968dbcf02cSchristos 	printf("Available interfaces:\n");
17978dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "INTERFACES");
17988dbcf02cSchristos }
17998dbcf02cSchristos 
18008dbcf02cSchristos 
wpa_cli_cmd_interface(struct wpa_ctrl * ctrl,int argc,char * argv[])18018dbcf02cSchristos static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
18028dbcf02cSchristos {
18038dbcf02cSchristos 	if (argc < 1) {
18048dbcf02cSchristos 		wpa_cli_list_interfaces(ctrl);
18058dbcf02cSchristos 		return 0;
18068dbcf02cSchristos 	}
18078dbcf02cSchristos 
18088dbcf02cSchristos 	wpa_cli_close_connection();
18098dbcf02cSchristos 	os_free(ctrl_ifname);
18108dbcf02cSchristos 	ctrl_ifname = os_strdup(argv[0]);
18119a539354Schristos 	if (!ctrl_ifname) {
18129a539354Schristos 		printf("Failed to allocate memory\n");
18139a539354Schristos 		return 0;
18149a539354Schristos 	}
18158dbcf02cSchristos 
1816c1f1514dSchristos 	if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
18178dbcf02cSchristos 		printf("Connected to interface '%s.\n", ctrl_ifname);
18188dbcf02cSchristos 	} else {
18198dbcf02cSchristos 		printf("Could not connect to interface '%s' - re-trying\n",
18208dbcf02cSchristos 		       ctrl_ifname);
18218dbcf02cSchristos 	}
18228dbcf02cSchristos 	return 0;
18238dbcf02cSchristos }
18248dbcf02cSchristos 
18258dbcf02cSchristos 
wpa_cli_cmd_reconfigure(struct wpa_ctrl * ctrl,int argc,char * argv[])18268dbcf02cSchristos static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
18278dbcf02cSchristos 				   char *argv[])
18288dbcf02cSchristos {
18298dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "RECONFIGURE");
18308dbcf02cSchristos }
18318dbcf02cSchristos 
18328dbcf02cSchristos 
wpa_cli_cmd_terminate(struct wpa_ctrl * ctrl,int argc,char * argv[])18338dbcf02cSchristos static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
18348dbcf02cSchristos 				 char *argv[])
18358dbcf02cSchristos {
18368dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "TERMINATE");
18378dbcf02cSchristos }
18388dbcf02cSchristos 
18398dbcf02cSchristos 
wpa_cli_cmd_interface_add(struct wpa_ctrl * ctrl,int argc,char * argv[])18408dbcf02cSchristos static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
18418dbcf02cSchristos 				     char *argv[])
18428dbcf02cSchristos {
18438dbcf02cSchristos 	char cmd[256];
18448dbcf02cSchristos 	int res;
18458dbcf02cSchristos 
18468dbcf02cSchristos 	if (argc < 1) {
18478dbcf02cSchristos 		printf("Invalid INTERFACE_ADD command: needs at least one "
18488dbcf02cSchristos 		       "argument (interface name)\n"
18498dbcf02cSchristos 		       "All arguments: ifname confname driver ctrl_interface "
18508d355d6fSchristos 		       "driver_param bridge_name [create]\n");
18518dbcf02cSchristos 		return -1;
18528dbcf02cSchristos 	}
18538dbcf02cSchristos 
18548dbcf02cSchristos 	/*
18558dbcf02cSchristos 	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
18568d355d6fSchristos 	 * <driver_param>TAB<bridge_name>[TAB<create>[TAB<type>]]
18578dbcf02cSchristos 	 */
18588dbcf02cSchristos 	res = os_snprintf(cmd, sizeof(cmd),
18598d355d6fSchristos 			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
18608dbcf02cSchristos 			  argv[0],
18618dbcf02cSchristos 			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
18628dbcf02cSchristos 			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
18638d355d6fSchristos 			  argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "",
18648d355d6fSchristos 			  argc > 7 ? argv[7] : "");
18659a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res))
18668dbcf02cSchristos 		return -1;
18678dbcf02cSchristos 	cmd[sizeof(cmd) - 1] = '\0';
18688dbcf02cSchristos 	return wpa_ctrl_command(ctrl, cmd);
18698dbcf02cSchristos }
18708dbcf02cSchristos 
18718dbcf02cSchristos 
wpa_cli_cmd_interface_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])18728dbcf02cSchristos static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
18738dbcf02cSchristos 					char *argv[])
18748dbcf02cSchristos {
1875da2e293dSchristos 	return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
18768dbcf02cSchristos }
18778dbcf02cSchristos 
18788dbcf02cSchristos 
wpa_cli_cmd_interface_list(struct wpa_ctrl * ctrl,int argc,char * argv[])18798dbcf02cSchristos static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
18808dbcf02cSchristos 				      char *argv[])
18818dbcf02cSchristos {
18828dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
18838dbcf02cSchristos }
18848dbcf02cSchristos 
18858dbcf02cSchristos 
18868dbcf02cSchristos #ifdef CONFIG_AP
wpa_cli_cmd_sta(struct wpa_ctrl * ctrl,int argc,char * argv[])18878dbcf02cSchristos static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
18888dbcf02cSchristos {
1889da2e293dSchristos 	return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
18908dbcf02cSchristos }
18918dbcf02cSchristos 
18928dbcf02cSchristos 
wpa_cli_complete_sta(const char * str,int pos)1893264891a8Schristos static char ** wpa_cli_complete_sta(const char *str, int pos)
1894264891a8Schristos {
1895264891a8Schristos 	int arg = get_cmd_arg_num(str, pos);
1896264891a8Schristos 	char **res = NULL;
1897264891a8Schristos 
1898264891a8Schristos 	switch (arg) {
1899264891a8Schristos 	case 1:
1900264891a8Schristos 		res = cli_txt_list_array(&stations);
1901264891a8Schristos 		break;
1902264891a8Schristos 	}
1903264891a8Schristos 
1904264891a8Schristos 	return res;
1905264891a8Schristos }
1906264891a8Schristos 
1907264891a8Schristos 
wpa_ctrl_command_sta(struct wpa_ctrl * ctrl,const char * cmd,char * addr,size_t addr_len,int print)1908264891a8Schristos static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd,
1909264891a8Schristos 				char *addr, size_t addr_len, int print)
19108dbcf02cSchristos {
19118dbcf02cSchristos 	char buf[4096], *pos;
19128dbcf02cSchristos 	size_t len;
19138dbcf02cSchristos 	int ret;
19148dbcf02cSchristos 
19158dbcf02cSchristos 	if (ctrl_conn == NULL) {
19168dbcf02cSchristos 		printf("Not connected to hostapd - command dropped.\n");
19178dbcf02cSchristos 		return -1;
19188dbcf02cSchristos 	}
19198d355d6fSchristos 	if (ifname_prefix) {
19208d355d6fSchristos 		os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
19218d355d6fSchristos 			    ifname_prefix, cmd);
19228d355d6fSchristos 		buf[sizeof(buf) - 1] = '\0';
19238d355d6fSchristos 		cmd = buf;
19248d355d6fSchristos 	}
19258dbcf02cSchristos 	len = sizeof(buf) - 1;
1926da2e293dSchristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
19278dbcf02cSchristos 			       wpa_cli_msg_cb);
19288dbcf02cSchristos 	if (ret == -2) {
19298dbcf02cSchristos 		printf("'%s' command timed out.\n", cmd);
19308dbcf02cSchristos 		return -2;
19318dbcf02cSchristos 	} else if (ret < 0) {
19328dbcf02cSchristos 		printf("'%s' command failed.\n", cmd);
19338dbcf02cSchristos 		return -1;
19348dbcf02cSchristos 	}
19358dbcf02cSchristos 
19368dbcf02cSchristos 	buf[len] = '\0';
1937264891a8Schristos 	if (os_memcmp(buf, "FAIL", 4) == 0 ||
1938264891a8Schristos 	    os_memcmp(buf, "UNKNOWN COMMAND", 15) == 0)
19398dbcf02cSchristos 		return -1;
1940264891a8Schristos 	if (print)
19418dbcf02cSchristos 		printf("%s", buf);
19428dbcf02cSchristos 
19438dbcf02cSchristos 	pos = buf;
19448dbcf02cSchristos 	while (*pos != '\0' && *pos != '\n')
19458dbcf02cSchristos 		pos++;
19468dbcf02cSchristos 	*pos = '\0';
19478dbcf02cSchristos 	os_strlcpy(addr, buf, addr_len);
19488dbcf02cSchristos 	return 0;
19498dbcf02cSchristos }
19508dbcf02cSchristos 
19518dbcf02cSchristos 
wpa_cli_cmd_all_sta(struct wpa_ctrl * ctrl,int argc,char * argv[])19528dbcf02cSchristos static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
19538dbcf02cSchristos {
19548dbcf02cSchristos 	char addr[32], cmd[64];
19558dbcf02cSchristos 
1956264891a8Schristos 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1))
19578dbcf02cSchristos 		return 0;
19588dbcf02cSchristos 	do {
19598dbcf02cSchristos 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1960264891a8Schristos 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0);
19618dbcf02cSchristos 
19628dbcf02cSchristos 	return -1;
19638dbcf02cSchristos }
1964da2e293dSchristos 
1965da2e293dSchristos 
wpa_cli_cmd_list_sta(struct wpa_ctrl * ctrl,int argc,char * argv[])1966264891a8Schristos static int wpa_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc,
1967264891a8Schristos 				char *argv[])
1968264891a8Schristos {
1969264891a8Schristos 	char addr[32], cmd[64];
1970264891a8Schristos 
1971264891a8Schristos 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0))
1972264891a8Schristos 		return 0;
1973264891a8Schristos 	do {
1974264891a8Schristos 		if (os_strcmp(addr, "") != 0)
1975264891a8Schristos 			printf("%s\n", addr);
1976264891a8Schristos 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1977264891a8Schristos 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0);
1978264891a8Schristos 
1979264891a8Schristos 	return 0;
1980264891a8Schristos }
1981264891a8Schristos 
1982264891a8Schristos 
wpa_cli_cmd_deauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])1983da2e293dSchristos static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1984da2e293dSchristos 				      char *argv[])
1985da2e293dSchristos {
1986da2e293dSchristos 	return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1987da2e293dSchristos }
1988da2e293dSchristos 
1989da2e293dSchristos 
wpa_cli_complete_deauthenticate(const char * str,int pos)1990264891a8Schristos static char ** wpa_cli_complete_deauthenticate(const char *str, int pos)
1991264891a8Schristos {
1992264891a8Schristos 	int arg = get_cmd_arg_num(str, pos);
1993264891a8Schristos 	char **res = NULL;
1994264891a8Schristos 
1995264891a8Schristos 	switch (arg) {
1996264891a8Schristos 	case 1:
1997264891a8Schristos 		res = cli_txt_list_array(&stations);
1998264891a8Schristos 		break;
1999264891a8Schristos 	}
2000264891a8Schristos 
2001264891a8Schristos 	return res;
2002264891a8Schristos }
2003264891a8Schristos 
2004264891a8Schristos 
wpa_cli_cmd_disassociate(struct wpa_ctrl * ctrl,int argc,char * argv[])2005da2e293dSchristos static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
2006da2e293dSchristos 				    char *argv[])
2007da2e293dSchristos {
2008da2e293dSchristos 	return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
2009da2e293dSchristos }
2010c1f1514dSchristos 
2011264891a8Schristos 
wpa_cli_complete_disassociate(const char * str,int pos)2012264891a8Schristos static char ** wpa_cli_complete_disassociate(const char *str, int pos)
2013264891a8Schristos {
2014264891a8Schristos 	int arg = get_cmd_arg_num(str, pos);
2015264891a8Schristos 	char **res = NULL;
2016264891a8Schristos 
2017264891a8Schristos 	switch (arg) {
2018264891a8Schristos 	case 1:
2019264891a8Schristos 		res = cli_txt_list_array(&stations);
2020264891a8Schristos 		break;
2021264891a8Schristos 	}
2022264891a8Schristos 
2023264891a8Schristos 	return res;
2024264891a8Schristos }
2025264891a8Schristos 
2026264891a8Schristos 
wpa_cli_cmd_chanswitch(struct wpa_ctrl * ctrl,int argc,char * argv[])2027c1f1514dSchristos static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
2028c1f1514dSchristos 				    char *argv[])
2029c1f1514dSchristos {
2030c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
2031c1f1514dSchristos }
2032c1f1514dSchristos 
20338dbcf02cSchristos #endif /* CONFIG_AP */
20348dbcf02cSchristos 
20358dbcf02cSchristos 
wpa_cli_cmd_suspend(struct wpa_ctrl * ctrl,int argc,char * argv[])20368dbcf02cSchristos static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
20378dbcf02cSchristos {
20388dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "SUSPEND");
20398dbcf02cSchristos }
20408dbcf02cSchristos 
20418dbcf02cSchristos 
wpa_cli_cmd_resume(struct wpa_ctrl * ctrl,int argc,char * argv[])20428dbcf02cSchristos static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
20438dbcf02cSchristos {
20448dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "RESUME");
20458dbcf02cSchristos }
20468dbcf02cSchristos 
20478dbcf02cSchristos 
2048c1f1514dSchristos #ifdef CONFIG_TESTING_OPTIONS
wpa_cli_cmd_drop_sa(struct wpa_ctrl * ctrl,int argc,char * argv[])20498dbcf02cSchristos static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
20508dbcf02cSchristos {
20518dbcf02cSchristos 	return wpa_ctrl_command(ctrl, "DROP_SA");
20528dbcf02cSchristos }
2053c1f1514dSchristos #endif /* CONFIG_TESTING_OPTIONS */
20548dbcf02cSchristos 
20558dbcf02cSchristos 
wpa_cli_cmd_roam(struct wpa_ctrl * ctrl,int argc,char * argv[])20568dbcf02cSchristos static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
20578dbcf02cSchristos {
2058da2e293dSchristos 	return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
20598dbcf02cSchristos }
20608dbcf02cSchristos 
20618dbcf02cSchristos 
20629a539354Schristos #ifdef CONFIG_MESH
20639a539354Schristos 
wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl * ctrl,int argc,char * argv[])20649a539354Schristos static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
20659a539354Schristos 					  char *argv[])
20669a539354Schristos {
20679a539354Schristos 	return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
20689a539354Schristos }
20699a539354Schristos 
20709a539354Schristos 
wpa_cli_cmd_mesh_group_add(struct wpa_ctrl * ctrl,int argc,char * argv[])20719a539354Schristos static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
20729a539354Schristos 				      char *argv[])
20739a539354Schristos {
20749a539354Schristos 	return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
20759a539354Schristos }
20769a539354Schristos 
20779a539354Schristos 
wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])20789a539354Schristos static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
20799a539354Schristos 					 char *argv[])
20809a539354Schristos {
20819a539354Schristos 	return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
20829a539354Schristos }
20839a539354Schristos 
20848d355d6fSchristos 
wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])20858d355d6fSchristos static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
20868d355d6fSchristos 					char *argv[])
20878d355d6fSchristos {
20888d355d6fSchristos 	return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
20898d355d6fSchristos }
20908d355d6fSchristos 
20918d355d6fSchristos 
wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl * ctrl,int argc,char * argv[])20928d355d6fSchristos static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
20938d355d6fSchristos 				     char *argv[])
20948d355d6fSchristos {
20958d355d6fSchristos 	return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
20968d355d6fSchristos }
20978d355d6fSchristos 
2098*0dddab58Schristos 
wpa_cli_cmd_mesh_link_probe(struct wpa_ctrl * ctrl,int argc,char * argv[])2099*0dddab58Schristos static int wpa_cli_cmd_mesh_link_probe(struct wpa_ctrl *ctrl, int argc,
2100*0dddab58Schristos 				       char *argv[])
2101*0dddab58Schristos {
2102*0dddab58Schristos 	return wpa_cli_cmd(ctrl, "MESH_LINK_PROBE", 1, argc, argv);
2103*0dddab58Schristos }
2104*0dddab58Schristos 
21059a539354Schristos #endif /* CONFIG_MESH */
21069a539354Schristos 
21079a539354Schristos 
210802ec05fbSchristos #ifdef CONFIG_P2P
210902ec05fbSchristos 
wpa_cli_cmd_p2p_find(struct wpa_ctrl * ctrl,int argc,char * argv[])211002ec05fbSchristos static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
211102ec05fbSchristos {
2112da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
2113da2e293dSchristos }
211402ec05fbSchristos 
211502ec05fbSchristos 
wpa_cli_complete_p2p_find(const char * str,int pos)2116da2e293dSchristos static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
2117da2e293dSchristos {
2118da2e293dSchristos 	char **res = NULL;
2119da2e293dSchristos 	int arg = get_cmd_arg_num(str, pos);
2120da2e293dSchristos 
2121da2e293dSchristos 	res = os_calloc(6, sizeof(char *));
2122da2e293dSchristos 	if (res == NULL)
2123da2e293dSchristos 		return NULL;
2124da2e293dSchristos 	res[0] = os_strdup("type=social");
2125da2e293dSchristos 	if (res[0] == NULL) {
2126da2e293dSchristos 		os_free(res);
2127da2e293dSchristos 		return NULL;
2128da2e293dSchristos 	}
2129da2e293dSchristos 	res[1] = os_strdup("type=progressive");
2130da2e293dSchristos 	if (res[1] == NULL)
2131da2e293dSchristos 		return res;
2132da2e293dSchristos 	res[2] = os_strdup("delay=");
2133da2e293dSchristos 	if (res[2] == NULL)
2134da2e293dSchristos 		return res;
2135da2e293dSchristos 	res[3] = os_strdup("dev_id=");
2136da2e293dSchristos 	if (res[3] == NULL)
2137da2e293dSchristos 		return res;
2138da2e293dSchristos 	if (arg == 1)
2139da2e293dSchristos 		res[4] = os_strdup("[timeout]");
2140da2e293dSchristos 
2141da2e293dSchristos 	return res;
214202ec05fbSchristos }
214302ec05fbSchristos 
214402ec05fbSchristos 
wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl * ctrl,int argc,char * argv[])214502ec05fbSchristos static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
214602ec05fbSchristos 				     char *argv[])
214702ec05fbSchristos {
214802ec05fbSchristos 	return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
214902ec05fbSchristos }
215002ec05fbSchristos 
215102ec05fbSchristos 
wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl * ctrl,int argc,char * argv[])21529a539354Schristos static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
21539a539354Schristos 					 char *argv[])
21549a539354Schristos {
21559a539354Schristos 	return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
21569a539354Schristos }
21579a539354Schristos 
21589a539354Schristos 
wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl * ctrl,int argc,char * argv[])21599a539354Schristos static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
21609a539354Schristos 					      char *argv[])
21619a539354Schristos {
21629a539354Schristos 	return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
21639a539354Schristos }
21649a539354Schristos 
21659a539354Schristos 
wpa_cli_cmd_p2p_connect(struct wpa_ctrl * ctrl,int argc,char * argv[])216602ec05fbSchristos static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
216702ec05fbSchristos 				   char *argv[])
216802ec05fbSchristos {
2169da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
217002ec05fbSchristos }
217102ec05fbSchristos 
217202ec05fbSchristos 
wpa_cli_complete_p2p_connect(const char * str,int pos)217302ec05fbSchristos static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
217402ec05fbSchristos {
217502ec05fbSchristos 	int arg = get_cmd_arg_num(str, pos);
217602ec05fbSchristos 	char **res = NULL;
217702ec05fbSchristos 
217802ec05fbSchristos 	switch (arg) {
217902ec05fbSchristos 	case 1:
218002ec05fbSchristos 		res = cli_txt_list_array(&p2p_peers);
218102ec05fbSchristos 		break;
218202ec05fbSchristos 	}
218302ec05fbSchristos 
218402ec05fbSchristos 	return res;
218502ec05fbSchristos }
218602ec05fbSchristos 
218702ec05fbSchristos 
wpa_cli_cmd_p2p_listen(struct wpa_ctrl * ctrl,int argc,char * argv[])218802ec05fbSchristos static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
218902ec05fbSchristos 				  char *argv[])
219002ec05fbSchristos {
2191da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
219202ec05fbSchristos }
219302ec05fbSchristos 
219402ec05fbSchristos 
wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])219502ec05fbSchristos static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
219602ec05fbSchristos 					char *argv[])
219702ec05fbSchristos {
2198da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
219902ec05fbSchristos }
220002ec05fbSchristos 
220102ec05fbSchristos 
wpa_cli_complete_p2p_group_remove(const char * str,int pos)220202ec05fbSchristos static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
220302ec05fbSchristos {
220402ec05fbSchristos 	int arg = get_cmd_arg_num(str, pos);
220502ec05fbSchristos 	char **res = NULL;
220602ec05fbSchristos 
220702ec05fbSchristos 	switch (arg) {
220802ec05fbSchristos 	case 1:
220902ec05fbSchristos 		res = cli_txt_list_array(&p2p_groups);
221002ec05fbSchristos 		break;
221102ec05fbSchristos 	}
221202ec05fbSchristos 
221302ec05fbSchristos 	return res;
221402ec05fbSchristos }
221502ec05fbSchristos 
221602ec05fbSchristos 
wpa_cli_cmd_p2p_group_add(struct wpa_ctrl * ctrl,int argc,char * argv[])221702ec05fbSchristos static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
221802ec05fbSchristos 					char *argv[])
221902ec05fbSchristos {
2220da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
222102ec05fbSchristos }
222202ec05fbSchristos 
222302ec05fbSchristos 
wpa_cli_cmd_p2p_group_member(struct wpa_ctrl * ctrl,int argc,char * argv[])22248d355d6fSchristos static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc,
22258d355d6fSchristos 					char *argv[])
22268d355d6fSchristos {
22278d355d6fSchristos 	return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv);
22288d355d6fSchristos }
22298d355d6fSchristos 
22308d355d6fSchristos 
wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl * ctrl,int argc,char * argv[])223102ec05fbSchristos static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
223202ec05fbSchristos 				     char *argv[])
223302ec05fbSchristos {
223402ec05fbSchristos 	if (argc != 2 && argc != 3) {
223502ec05fbSchristos 		printf("Invalid P2P_PROV_DISC command: needs at least "
223602ec05fbSchristos 		       "two arguments, address and config method\n"
223702ec05fbSchristos 		       "(display, keypad, or pbc) and an optional join\n");
223802ec05fbSchristos 		return -1;
223902ec05fbSchristos 	}
224002ec05fbSchristos 
2241da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
224202ec05fbSchristos }
224302ec05fbSchristos 
224402ec05fbSchristos 
wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl * ctrl,int argc,char * argv[])224502ec05fbSchristos static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
224602ec05fbSchristos 					  char *argv[])
224702ec05fbSchristos {
224802ec05fbSchristos 	return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
224902ec05fbSchristos }
225002ec05fbSchristos 
225102ec05fbSchristos 
wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl * ctrl,int argc,char * argv[])225202ec05fbSchristos static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
225302ec05fbSchristos 					 char *argv[])
225402ec05fbSchristos {
225502ec05fbSchristos 	char cmd[4096];
225602ec05fbSchristos 
22579a539354Schristos 	if (argc < 2) {
225802ec05fbSchristos 		printf("Invalid P2P_SERV_DISC_REQ command: needs two "
22599a539354Schristos 		       "or more arguments (address and TLVs)\n");
226002ec05fbSchristos 		return -1;
226102ec05fbSchristos 	}
226202ec05fbSchristos 
2263da2e293dSchristos 	if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
226402ec05fbSchristos 		return -1;
226502ec05fbSchristos 	return wpa_ctrl_command(ctrl, cmd);
226602ec05fbSchristos }
226702ec05fbSchristos 
226802ec05fbSchristos 
wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl * ctrl,int argc,char * argv[])226902ec05fbSchristos static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
227002ec05fbSchristos 						int argc, char *argv[])
227102ec05fbSchristos {
2272da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
227302ec05fbSchristos }
227402ec05fbSchristos 
227502ec05fbSchristos 
wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl * ctrl,int argc,char * argv[])227602ec05fbSchristos static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
227702ec05fbSchristos 					  char *argv[])
227802ec05fbSchristos {
227902ec05fbSchristos 	char cmd[4096];
228002ec05fbSchristos 	int res;
228102ec05fbSchristos 
228202ec05fbSchristos 	if (argc != 4) {
228302ec05fbSchristos 		printf("Invalid P2P_SERV_DISC_RESP command: needs four "
228402ec05fbSchristos 		       "arguments (freq, address, dialog token, and TLVs)\n");
228502ec05fbSchristos 		return -1;
228602ec05fbSchristos 	}
228702ec05fbSchristos 
228802ec05fbSchristos 	res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
228902ec05fbSchristos 			  argv[0], argv[1], argv[2], argv[3]);
22909a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res))
229102ec05fbSchristos 		return -1;
229202ec05fbSchristos 	cmd[sizeof(cmd) - 1] = '\0';
229302ec05fbSchristos 	return wpa_ctrl_command(ctrl, cmd);
229402ec05fbSchristos }
229502ec05fbSchristos 
229602ec05fbSchristos 
wpa_cli_cmd_p2p_service_update(struct wpa_ctrl * ctrl,int argc,char * argv[])229702ec05fbSchristos static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
229802ec05fbSchristos 					  char *argv[])
229902ec05fbSchristos {
230002ec05fbSchristos 	return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
230102ec05fbSchristos }
230202ec05fbSchristos 
230302ec05fbSchristos 
wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl * ctrl,int argc,char * argv[])230402ec05fbSchristos static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
230502ec05fbSchristos 					      int argc, char *argv[])
230602ec05fbSchristos {
2307da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
230802ec05fbSchristos }
230902ec05fbSchristos 
231002ec05fbSchristos 
wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])231102ec05fbSchristos static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
231202ec05fbSchristos 					 char *argv[])
231302ec05fbSchristos {
231402ec05fbSchristos 	return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
231502ec05fbSchristos }
231602ec05fbSchristos 
231702ec05fbSchristos 
wpa_cli_cmd_p2p_service_add(struct wpa_ctrl * ctrl,int argc,char * argv[])231802ec05fbSchristos static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
231902ec05fbSchristos 				       char *argv[])
232002ec05fbSchristos {
23219a539354Schristos 	if (argc < 3) {
23229a539354Schristos 		printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
23239a539354Schristos 		return -1;
23249a539354Schristos 	}
232502ec05fbSchristos 
23269a539354Schristos 	return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
23279a539354Schristos }
23289a539354Schristos 
23299a539354Schristos 
wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl * ctrl,int argc,char * argv[])23309a539354Schristos static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
23319a539354Schristos 				       char *argv[])
23329a539354Schristos {
23339a539354Schristos 	if (argc < 5 || argc > 6) {
23349a539354Schristos 		printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
233502ec05fbSchristos 		       "arguments\n");
233602ec05fbSchristos 		return -1;
233702ec05fbSchristos 	}
233802ec05fbSchristos 
23399a539354Schristos 	return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
234002ec05fbSchristos }
234102ec05fbSchristos 
234202ec05fbSchristos 
wpa_cli_cmd_p2p_service_del(struct wpa_ctrl * ctrl,int argc,char * argv[])234302ec05fbSchristos static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
234402ec05fbSchristos 				       char *argv[])
234502ec05fbSchristos {
234602ec05fbSchristos 	char cmd[4096];
234702ec05fbSchristos 	int res;
234802ec05fbSchristos 
234902ec05fbSchristos 	if (argc != 2 && argc != 3) {
235002ec05fbSchristos 		printf("Invalid P2P_SERVICE_DEL command: needs two or three "
235102ec05fbSchristos 		       "arguments\n");
235202ec05fbSchristos 		return -1;
235302ec05fbSchristos 	}
235402ec05fbSchristos 
235502ec05fbSchristos 	if (argc == 3)
235602ec05fbSchristos 		res = os_snprintf(cmd, sizeof(cmd),
235702ec05fbSchristos 				  "P2P_SERVICE_DEL %s %s %s",
235802ec05fbSchristos 				  argv[0], argv[1], argv[2]);
235902ec05fbSchristos 	else
236002ec05fbSchristos 		res = os_snprintf(cmd, sizeof(cmd),
236102ec05fbSchristos 				  "P2P_SERVICE_DEL %s %s",
236202ec05fbSchristos 				  argv[0], argv[1]);
23639a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res))
236402ec05fbSchristos 		return -1;
236502ec05fbSchristos 	cmd[sizeof(cmd) - 1] = '\0';
236602ec05fbSchristos 	return wpa_ctrl_command(ctrl, cmd);
236702ec05fbSchristos }
236802ec05fbSchristos 
236902ec05fbSchristos 
wpa_cli_cmd_p2p_reject(struct wpa_ctrl * ctrl,int argc,char * argv[])237002ec05fbSchristos static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
237102ec05fbSchristos 				  int argc, char *argv[])
237202ec05fbSchristos {
2373da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
237402ec05fbSchristos }
237502ec05fbSchristos 
237602ec05fbSchristos 
wpa_cli_cmd_p2p_invite(struct wpa_ctrl * ctrl,int argc,char * argv[])237702ec05fbSchristos static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
237802ec05fbSchristos 				  int argc, char *argv[])
237902ec05fbSchristos {
2380da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
238102ec05fbSchristos }
238202ec05fbSchristos 
238302ec05fbSchristos 
wpa_cli_cmd_p2p_peer(struct wpa_ctrl * ctrl,int argc,char * argv[])238402ec05fbSchristos static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
238502ec05fbSchristos {
2386da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
238702ec05fbSchristos }
238802ec05fbSchristos 
238902ec05fbSchristos 
wpa_cli_complete_p2p_peer(const char * str,int pos)239002ec05fbSchristos static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
239102ec05fbSchristos {
239202ec05fbSchristos 	int arg = get_cmd_arg_num(str, pos);
239302ec05fbSchristos 	char **res = NULL;
239402ec05fbSchristos 
239502ec05fbSchristos 	switch (arg) {
239602ec05fbSchristos 	case 1:
239702ec05fbSchristos 		res = cli_txt_list_array(&p2p_peers);
239802ec05fbSchristos 		break;
239902ec05fbSchristos 	}
240002ec05fbSchristos 
240102ec05fbSchristos 	return res;
240202ec05fbSchristos }
240302ec05fbSchristos 
240402ec05fbSchristos 
wpa_ctrl_command_p2p_peer(struct wpa_ctrl * ctrl,const char * cmd,char * addr,size_t addr_len,int discovered)2405264891a8Schristos static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, const char *cmd,
240602ec05fbSchristos 				     char *addr, size_t addr_len,
240702ec05fbSchristos 				     int discovered)
240802ec05fbSchristos {
240902ec05fbSchristos 	char buf[4096], *pos;
241002ec05fbSchristos 	size_t len;
241102ec05fbSchristos 	int ret;
241202ec05fbSchristos 
241302ec05fbSchristos 	if (ctrl_conn == NULL)
241402ec05fbSchristos 		return -1;
241502ec05fbSchristos 	len = sizeof(buf) - 1;
2416da2e293dSchristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
241702ec05fbSchristos 			       wpa_cli_msg_cb);
241802ec05fbSchristos 	if (ret == -2) {
241902ec05fbSchristos 		printf("'%s' command timed out.\n", cmd);
242002ec05fbSchristos 		return -2;
242102ec05fbSchristos 	} else if (ret < 0) {
242202ec05fbSchristos 		printf("'%s' command failed.\n", cmd);
242302ec05fbSchristos 		return -1;
242402ec05fbSchristos 	}
242502ec05fbSchristos 
242602ec05fbSchristos 	buf[len] = '\0';
2427da2e293dSchristos 	if (os_memcmp(buf, "FAIL", 4) == 0)
242802ec05fbSchristos 		return -1;
242902ec05fbSchristos 
243002ec05fbSchristos 	pos = buf;
243102ec05fbSchristos 	while (*pos != '\0' && *pos != '\n')
243202ec05fbSchristos 		pos++;
243302ec05fbSchristos 	*pos++ = '\0';
243402ec05fbSchristos 	os_strlcpy(addr, buf, addr_len);
243502ec05fbSchristos 	if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
243602ec05fbSchristos 		printf("%s\n", addr);
243702ec05fbSchristos 	return 0;
243802ec05fbSchristos }
243902ec05fbSchristos 
244002ec05fbSchristos 
wpa_cli_cmd_p2p_peers(struct wpa_ctrl * ctrl,int argc,char * argv[])244102ec05fbSchristos static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
244202ec05fbSchristos {
244302ec05fbSchristos 	char addr[32], cmd[64];
244402ec05fbSchristos 	int discovered;
244502ec05fbSchristos 
244602ec05fbSchristos 	discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
244702ec05fbSchristos 
244802ec05fbSchristos 	if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
244902ec05fbSchristos 				      addr, sizeof(addr), discovered))
245002ec05fbSchristos 		return -1;
245102ec05fbSchristos 	do {
245202ec05fbSchristos 		os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
245302ec05fbSchristos 	} while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
245402ec05fbSchristos 			 discovered) == 0);
245502ec05fbSchristos 
245602ec05fbSchristos 	return 0;
245702ec05fbSchristos }
245802ec05fbSchristos 
245902ec05fbSchristos 
wpa_cli_cmd_p2p_set(struct wpa_ctrl * ctrl,int argc,char * argv[])246002ec05fbSchristos static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
246102ec05fbSchristos {
2462da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
246302ec05fbSchristos }
246402ec05fbSchristos 
246502ec05fbSchristos 
wpa_cli_complete_p2p_set(const char * str,int pos)2466c1f1514dSchristos static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2467c1f1514dSchristos {
2468c1f1514dSchristos 	int arg = get_cmd_arg_num(str, pos);
2469c1f1514dSchristos 	const char *fields[] = {
2470c1f1514dSchristos 		"discoverability",
2471c1f1514dSchristos 		"managed",
2472c1f1514dSchristos 		"listen_channel",
2473c1f1514dSchristos 		"ssid_postfix",
2474c1f1514dSchristos 		"noa",
2475c1f1514dSchristos 		"ps",
2476c1f1514dSchristos 		"oppps",
2477c1f1514dSchristos 		"ctwindow",
2478c1f1514dSchristos 		"disabled",
2479c1f1514dSchristos 		"conc_pref",
2480c1f1514dSchristos 		"force_long_sd",
2481c1f1514dSchristos 		"peer_filter",
2482c1f1514dSchristos 		"cross_connect",
2483c1f1514dSchristos 		"go_apsd",
2484c1f1514dSchristos 		"client_apsd",
2485c1f1514dSchristos 		"disallow_freq",
2486c1f1514dSchristos 		"disc_int",
2487c1f1514dSchristos 		"per_sta_psk",
2488c1f1514dSchristos 	};
2489c1f1514dSchristos 	int i, num_fields = ARRAY_SIZE(fields);
2490c1f1514dSchristos 
2491c1f1514dSchristos 	if (arg == 1) {
2492c1f1514dSchristos 		char **res = os_calloc(num_fields + 1, sizeof(char *));
2493c1f1514dSchristos 		if (res == NULL)
2494c1f1514dSchristos 			return NULL;
2495c1f1514dSchristos 		for (i = 0; i < num_fields; i++) {
2496c1f1514dSchristos 			res[i] = os_strdup(fields[i]);
2497c1f1514dSchristos 			if (res[i] == NULL)
2498c1f1514dSchristos 				return res;
2499c1f1514dSchristos 		}
2500c1f1514dSchristos 		return res;
2501c1f1514dSchristos 	}
2502c1f1514dSchristos 
2503c1f1514dSchristos 	if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2504c1f1514dSchristos 		return cli_txt_list_array(&p2p_peers);
2505c1f1514dSchristos 
2506c1f1514dSchristos 	return NULL;
2507c1f1514dSchristos }
2508c1f1514dSchristos 
2509c1f1514dSchristos 
wpa_cli_cmd_p2p_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])251002ec05fbSchristos static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
251102ec05fbSchristos {
251202ec05fbSchristos 	return wpa_ctrl_command(ctrl, "P2P_FLUSH");
251302ec05fbSchristos }
251402ec05fbSchristos 
251502ec05fbSchristos 
wpa_cli_cmd_p2p_cancel(struct wpa_ctrl * ctrl,int argc,char * argv[])251602ec05fbSchristos static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
251702ec05fbSchristos 				  char *argv[])
251802ec05fbSchristos {
251902ec05fbSchristos 	return wpa_ctrl_command(ctrl, "P2P_CANCEL");
252002ec05fbSchristos }
252102ec05fbSchristos 
252202ec05fbSchristos 
wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl * ctrl,int argc,char * argv[])252302ec05fbSchristos static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
252402ec05fbSchristos 				       char *argv[])
252502ec05fbSchristos {
2526da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
252702ec05fbSchristos }
252802ec05fbSchristos 
252902ec05fbSchristos 
wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl * ctrl,int argc,char * argv[])253002ec05fbSchristos static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
253102ec05fbSchristos 					char *argv[])
253202ec05fbSchristos {
253302ec05fbSchristos 	if (argc != 0 && argc != 2 && argc != 4) {
253402ec05fbSchristos 		printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
253502ec05fbSchristos 		       "(preferred duration, interval; in microsecods).\n"
253602ec05fbSchristos 		       "Optional second pair can be used to provide "
253702ec05fbSchristos 		       "acceptable values.\n");
253802ec05fbSchristos 		return -1;
253902ec05fbSchristos 	}
254002ec05fbSchristos 
2541da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
254202ec05fbSchristos }
254302ec05fbSchristos 
254402ec05fbSchristos 
wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl * ctrl,int argc,char * argv[])254502ec05fbSchristos static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
254602ec05fbSchristos 				      char *argv[])
254702ec05fbSchristos {
254802ec05fbSchristos 	if (argc != 0 && argc != 2) {
254902ec05fbSchristos 		printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
255002ec05fbSchristos 		       "(availability period, availability interval; in "
255102ec05fbSchristos 		       "millisecods).\n"
255202ec05fbSchristos 		       "Extended Listen Timing can be cancelled with this "
255302ec05fbSchristos 		       "command when used without parameters.\n");
255402ec05fbSchristos 		return -1;
255502ec05fbSchristos 	}
255602ec05fbSchristos 
2557da2e293dSchristos 	return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2558da2e293dSchristos }
2559da2e293dSchristos 
2560c1f1514dSchristos 
wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl * ctrl,int argc,char * argv[])2561c1f1514dSchristos static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2562c1f1514dSchristos 					 char *argv[])
2563c1f1514dSchristos {
2564c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2565c1f1514dSchristos }
2566c1f1514dSchristos 
2567264891a8Schristos #endif /* CONFIG_P2P */
2568264891a8Schristos 
25698d355d6fSchristos 
wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl * ctrl,int argc,char * argv[])25708d355d6fSchristos static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
25718d355d6fSchristos 				       char *argv[])
25728d355d6fSchristos {
25738d355d6fSchristos 	return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
25748d355d6fSchristos }
25758d355d6fSchristos 
25768d355d6fSchristos 
wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl * ctrl,int argc,char * argv[])25778d355d6fSchristos static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
25788d355d6fSchristos 				       char *argv[])
25798d355d6fSchristos {
25808d355d6fSchristos 	return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
25818d355d6fSchristos }
25828d355d6fSchristos 
25838d355d6fSchristos 
wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])25848d355d6fSchristos static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
25858d355d6fSchristos 					  char *argv[])
25868d355d6fSchristos {
25878d355d6fSchristos 	return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
25888d355d6fSchristos }
25898d355d6fSchristos 
2590da2e293dSchristos 
2591da2e293dSchristos #ifdef CONFIG_WIFI_DISPLAY
2592da2e293dSchristos 
wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl * ctrl,int argc,char * argv[])2593da2e293dSchristos static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2594da2e293dSchristos 				       char *argv[])
2595da2e293dSchristos {
2596da2e293dSchristos 	char cmd[100];
2597da2e293dSchristos 	int res;
2598da2e293dSchristos 
2599da2e293dSchristos 	if (argc != 1 && argc != 2) {
2600da2e293dSchristos 		printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2601da2e293dSchristos 		       "arguments (subelem, hexdump)\n");
2602da2e293dSchristos 		return -1;
2603da2e293dSchristos 	}
2604da2e293dSchristos 
2605da2e293dSchristos 	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2606da2e293dSchristos 			  argv[0], argc > 1 ? argv[1] : "");
26079a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res))
260802ec05fbSchristos 		return -1;
260902ec05fbSchristos 	cmd[sizeof(cmd) - 1] = '\0';
261002ec05fbSchristos 	return wpa_ctrl_command(ctrl, cmd);
261102ec05fbSchristos }
261202ec05fbSchristos 
2613da2e293dSchristos 
wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2614da2e293dSchristos static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2615da2e293dSchristos 				       char *argv[])
2616da2e293dSchristos {
2617da2e293dSchristos 	char cmd[100];
2618da2e293dSchristos 	int res;
2619da2e293dSchristos 
2620da2e293dSchristos 	if (argc != 1) {
2621da2e293dSchristos 		printf("Invalid WFD_SUBELEM_GET command: needs one "
2622da2e293dSchristos 		       "argument (subelem)\n");
2623da2e293dSchristos 		return -1;
2624da2e293dSchristos 	}
2625da2e293dSchristos 
2626da2e293dSchristos 	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2627da2e293dSchristos 			  argv[0]);
26289a539354Schristos 	if (os_snprintf_error(sizeof(cmd), res))
2629da2e293dSchristos 		return -1;
2630da2e293dSchristos 	cmd[sizeof(cmd) - 1] = '\0';
2631da2e293dSchristos 	return wpa_ctrl_command(ctrl, cmd);
2632da2e293dSchristos }
2633da2e293dSchristos #endif /* CONFIG_WIFI_DISPLAY */
263402ec05fbSchristos 
263502ec05fbSchristos 
263602ec05fbSchristos #ifdef CONFIG_INTERWORKING
wpa_cli_cmd_fetch_anqp(struct wpa_ctrl * ctrl,int argc,char * argv[])263702ec05fbSchristos static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
263802ec05fbSchristos 				  char *argv[])
263902ec05fbSchristos {
264002ec05fbSchristos 	return wpa_ctrl_command(ctrl, "FETCH_ANQP");
264102ec05fbSchristos }
264202ec05fbSchristos 
264302ec05fbSchristos 
wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl * ctrl,int argc,char * argv[])264402ec05fbSchristos static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
264502ec05fbSchristos 				       char *argv[])
264602ec05fbSchristos {
264702ec05fbSchristos 	return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
264802ec05fbSchristos }
264902ec05fbSchristos 
265002ec05fbSchristos 
wpa_cli_cmd_interworking_select(struct wpa_ctrl * ctrl,int argc,char * argv[])265102ec05fbSchristos static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
265202ec05fbSchristos 					   char *argv[])
265302ec05fbSchristos {
2654da2e293dSchristos 	return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
265502ec05fbSchristos }
265602ec05fbSchristos 
265702ec05fbSchristos 
wpa_cli_cmd_interworking_connect(struct wpa_ctrl * ctrl,int argc,char * argv[])265802ec05fbSchristos static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
265902ec05fbSchristos 					    char *argv[])
266002ec05fbSchristos {
2661da2e293dSchristos 	return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
266202ec05fbSchristos }
266302ec05fbSchristos 
266402ec05fbSchristos 
wpa_cli_cmd_interworking_add_network(struct wpa_ctrl * ctrl,int argc,char * argv[])26659a539354Schristos static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
26669a539354Schristos 						char *argv[])
26679a539354Schristos {
26689a539354Schristos 	return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
26699a539354Schristos }
26709a539354Schristos 
26719a539354Schristos 
wpa_cli_cmd_anqp_get(struct wpa_ctrl * ctrl,int argc,char * argv[])267202ec05fbSchristos static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
267302ec05fbSchristos {
2674da2e293dSchristos 	return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
267502ec05fbSchristos }
267602ec05fbSchristos 
2677da2e293dSchristos 
wpa_cli_cmd_gas_request(struct wpa_ctrl * ctrl,int argc,char * argv[])2678da2e293dSchristos static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2679da2e293dSchristos 				   char *argv[])
2680da2e293dSchristos {
2681da2e293dSchristos 	return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2682da2e293dSchristos }
2683da2e293dSchristos 
2684da2e293dSchristos 
wpa_cli_cmd_gas_response_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2685da2e293dSchristos static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2686da2e293dSchristos 					char *argv[])
2687da2e293dSchristos {
2688da2e293dSchristos 	return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
268902ec05fbSchristos }
269002ec05fbSchristos #endif /* CONFIG_INTERWORKING */
269102ec05fbSchristos 
269202ec05fbSchristos 
2693da2e293dSchristos #ifdef CONFIG_HS20
2694da2e293dSchristos 
wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2695da2e293dSchristos static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2696da2e293dSchristos 				     char *argv[])
2697da2e293dSchristos {
2698da2e293dSchristos 	return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2699da2e293dSchristos }
2700da2e293dSchristos 
2701da2e293dSchristos 
wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl * ctrl,int argc,char * argv[])2702da2e293dSchristos static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2703da2e293dSchristos 					       char *argv[])
2704da2e293dSchristos {
2705da2e293dSchristos 	char cmd[512];
2706da2e293dSchristos 
2707da2e293dSchristos 	if (argc == 0) {
2708da2e293dSchristos 		printf("Command needs one or two arguments (dst mac addr and "
2709da2e293dSchristos 		       "optional home realm)\n");
2710da2e293dSchristos 		return -1;
2711da2e293dSchristos 	}
2712da2e293dSchristos 
2713da2e293dSchristos 	if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2714da2e293dSchristos 		      argc, argv) < 0)
2715da2e293dSchristos 		return -1;
2716da2e293dSchristos 
2717da2e293dSchristos 	return wpa_ctrl_command(ctrl, cmd);
2718da2e293dSchristos }
2719da2e293dSchristos 
2720c1f1514dSchristos 
wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl * ctrl,int argc,char * argv[])2721c1f1514dSchristos static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2722c1f1514dSchristos 					 char *argv[])
2723c1f1514dSchristos {
2724c1f1514dSchristos 	char cmd[512];
2725c1f1514dSchristos 
2726c1f1514dSchristos 	if (argc < 2) {
2727c1f1514dSchristos 		printf("Command needs two arguments (dst mac addr and "
2728c1f1514dSchristos 		       "icon name)\n");
2729c1f1514dSchristos 		return -1;
2730c1f1514dSchristos 	}
2731c1f1514dSchristos 
2732c1f1514dSchristos 	if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2733c1f1514dSchristos 		return -1;
2734c1f1514dSchristos 
2735c1f1514dSchristos 	return wpa_ctrl_command(ctrl, cmd);
2736c1f1514dSchristos }
2737c1f1514dSchristos 
2738c1f1514dSchristos 
wpa_cli_cmd_fetch_osu(struct wpa_ctrl * ctrl,int argc,char * argv[])2739c1f1514dSchristos static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2740c1f1514dSchristos {
2741c1f1514dSchristos 	return wpa_ctrl_command(ctrl, "FETCH_OSU");
2742c1f1514dSchristos }
2743c1f1514dSchristos 
2744c1f1514dSchristos 
wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl * ctrl,int argc,char * argv[])2745c1f1514dSchristos static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2746c1f1514dSchristos 					char *argv[])
2747c1f1514dSchristos {
2748c1f1514dSchristos 	return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2749c1f1514dSchristos }
2750c1f1514dSchristos 
2751da2e293dSchristos #endif /* CONFIG_HS20 */
2752da2e293dSchristos 
2753da2e293dSchristos 
wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])275402ec05fbSchristos static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
275502ec05fbSchristos 				       char *argv[])
275602ec05fbSchristos {
2757da2e293dSchristos 	return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
275802ec05fbSchristos }
275902ec05fbSchristos 
276002ec05fbSchristos 
wpa_cli_cmd_tdls_discover(struct wpa_ctrl * ctrl,int argc,char * argv[])276102ec05fbSchristos static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
276202ec05fbSchristos 				     char *argv[])
276302ec05fbSchristos {
2764da2e293dSchristos 	return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
276502ec05fbSchristos }
276602ec05fbSchristos 
276702ec05fbSchristos 
wpa_cli_cmd_tdls_setup(struct wpa_ctrl * ctrl,int argc,char * argv[])276802ec05fbSchristos static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
276902ec05fbSchristos 				  char *argv[])
277002ec05fbSchristos {
2771da2e293dSchristos 	return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
277202ec05fbSchristos }
277302ec05fbSchristos 
277402ec05fbSchristos 
wpa_cli_cmd_tdls_teardown(struct wpa_ctrl * ctrl,int argc,char * argv[])277502ec05fbSchristos static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
277602ec05fbSchristos 				     char *argv[])
277702ec05fbSchristos {
2778da2e293dSchristos 	return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
277902ec05fbSchristos }
278002ec05fbSchristos 
278102ec05fbSchristos 
wpa_cli_cmd_tdls_link_status(struct wpa_ctrl * ctrl,int argc,char * argv[])27828d355d6fSchristos static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
27838d355d6fSchristos 					char *argv[])
27848d355d6fSchristos {
27858d355d6fSchristos 	return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
27868d355d6fSchristos }
27878d355d6fSchristos 
27888d355d6fSchristos 
wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl * ctrl,int argc,char * argv[])27899a539354Schristos static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
27909a539354Schristos 				    char *argv[])
27919a539354Schristos {
27929a539354Schristos 	return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
27939a539354Schristos }
27949a539354Schristos 
27959a539354Schristos 
wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl * ctrl,int argc,char * argv[])27969a539354Schristos static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
27979a539354Schristos 				    char *argv[])
27989a539354Schristos {
27999a539354Schristos 	return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
28009a539354Schristos }
28019a539354Schristos 
28029a539354Schristos 
wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl * ctrl,int argc,char * argv[])28039a539354Schristos static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
28049a539354Schristos 				    char *argv[])
28059a539354Schristos {
28069a539354Schristos 	return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
28079a539354Schristos }
28089a539354Schristos 
28099a539354Schristos 
wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl * ctrl,int argc,char * argv[])28109a539354Schristos static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
28119a539354Schristos 					char *argv[])
28129a539354Schristos {
28139a539354Schristos 	return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
28149a539354Schristos }
28159a539354Schristos 
28169a539354Schristos 
wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl * ctrl,int argc,char * argv[])28179a539354Schristos static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
28189a539354Schristos 					       char *argv[])
28199a539354Schristos {
28209a539354Schristos 	return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
28219a539354Schristos }
28229a539354Schristos 
28239a539354Schristos 
wpa_cli_cmd_signal_poll(struct wpa_ctrl * ctrl,int argc,char * argv[])282402ec05fbSchristos static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
282502ec05fbSchristos 				   char *argv[])
282602ec05fbSchristos {
282702ec05fbSchristos 	return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
282802ec05fbSchristos }
282902ec05fbSchristos 
283002ec05fbSchristos 
wpa_cli_cmd_signal_monitor(struct wpa_ctrl * ctrl,int argc,char * argv[])28318d355d6fSchristos static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc,
28328d355d6fSchristos 				   char *argv[])
28338d355d6fSchristos {
28348d355d6fSchristos 	return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv);
28358d355d6fSchristos }
28368d355d6fSchristos 
28378d355d6fSchristos 
wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl * ctrl,int argc,char * argv[])2838da2e293dSchristos static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2839da2e293dSchristos 				   char *argv[])
2840da2e293dSchristos {
2841da2e293dSchristos 	return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2842da2e293dSchristos }
2843da2e293dSchristos 
2844da2e293dSchristos 
wpa_cli_cmd_reauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])2845da2e293dSchristos static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2846da2e293dSchristos 				      char *argv[])
2847da2e293dSchristos {
2848da2e293dSchristos 	return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2849da2e293dSchristos }
2850da2e293dSchristos 
2851da2e293dSchristos 
2852da2e293dSchristos #ifdef CONFIG_AUTOSCAN
2853da2e293dSchristos 
wpa_cli_cmd_autoscan(struct wpa_ctrl * ctrl,int argc,char * argv[])2854da2e293dSchristos static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2855da2e293dSchristos {
2856da2e293dSchristos 	if (argc == 0)
2857da2e293dSchristos 		return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2858da2e293dSchristos 
2859da2e293dSchristos 	return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2860da2e293dSchristos }
2861da2e293dSchristos 
2862da2e293dSchristos #endif /* CONFIG_AUTOSCAN */
2863da2e293dSchristos 
2864da2e293dSchristos 
2865da2e293dSchristos #ifdef CONFIG_WNM
2866da2e293dSchristos 
wpa_cli_cmd_wnm_sleep(struct wpa_ctrl * ctrl,int argc,char * argv[])2867da2e293dSchristos static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2868da2e293dSchristos {
2869da2e293dSchristos 	return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2870da2e293dSchristos }
2871da2e293dSchristos 
2872c1f1514dSchristos 
wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl * ctrl,int argc,char * argv[])2873c1f1514dSchristos static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2874c1f1514dSchristos {
2875c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2876c1f1514dSchristos }
2877c1f1514dSchristos 
2878da2e293dSchristos #endif /* CONFIG_WNM */
2879da2e293dSchristos 
2880da2e293dSchristos 
wpa_cli_cmd_raw(struct wpa_ctrl * ctrl,int argc,char * argv[])2881da2e293dSchristos static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2882da2e293dSchristos {
2883da2e293dSchristos 	if (argc == 0)
2884da2e293dSchristos 		return -1;
2885da2e293dSchristos 	return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2886da2e293dSchristos }
2887da2e293dSchristos 
2888da2e293dSchristos 
2889c1f1514dSchristos #ifdef ANDROID
wpa_cli_cmd_driver(struct wpa_ctrl * ctrl,int argc,char * argv[])2890c1f1514dSchristos static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2891c1f1514dSchristos {
2892c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2893c1f1514dSchristos }
2894c1f1514dSchristos #endif /* ANDROID */
2895c1f1514dSchristos 
2896c1f1514dSchristos 
wpa_cli_cmd_vendor(struct wpa_ctrl * ctrl,int argc,char * argv[])2897c1f1514dSchristos static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2898c1f1514dSchristos {
2899c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2900c1f1514dSchristos }
2901c1f1514dSchristos 
2902c1f1514dSchristos 
wpa_cli_cmd_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])2903c1f1514dSchristos static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2904c1f1514dSchristos {
2905c1f1514dSchristos 	return wpa_ctrl_command(ctrl, "FLUSH");
2906c1f1514dSchristos }
2907c1f1514dSchristos 
2908c1f1514dSchristos 
wpa_cli_cmd_radio_work(struct wpa_ctrl * ctrl,int argc,char * argv[])2909c1f1514dSchristos static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2910c1f1514dSchristos {
2911c1f1514dSchristos 	return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2912c1f1514dSchristos }
2913c1f1514dSchristos 
2914c1f1514dSchristos 
wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl * ctrl,int argc,char * argv[])29159a539354Schristos static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
29169a539354Schristos 					    char *argv[])
29179a539354Schristos {
29189a539354Schristos 	return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
29199a539354Schristos }
29209a539354Schristos 
29219a539354Schristos 
wpa_cli_cmd_erp_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])29229a539354Schristos static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
29239a539354Schristos {
29249a539354Schristos 	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
29259a539354Schristos }
29269a539354Schristos 
29279a539354Schristos 
wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])29289a539354Schristos static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
29299a539354Schristos 				     char *argv[])
29309a539354Schristos {
29319a539354Schristos 	return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
29329a539354Schristos }
29339a539354Schristos 
29349a539354Schristos 
wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl * ctrl,int argc,char * argv[])29358d355d6fSchristos static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
29368d355d6fSchristos 					  char *argv[])
29378d355d6fSchristos {
29388d355d6fSchristos 	return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
29398d355d6fSchristos }
29408d355d6fSchristos 
29418d355d6fSchristos 
wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl * ctrl,int argc,char * argv[])29428d355d6fSchristos static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc,
29438d355d6fSchristos 				    char *argv[])
29448d355d6fSchristos {
29458d355d6fSchristos 	return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv);
29468d355d6fSchristos }
29478d355d6fSchristos 
29488d355d6fSchristos 
wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl * ctrl,int argc,char * argv[])29498d355d6fSchristos static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
29508d355d6fSchristos 				   char *argv[])
29518d355d6fSchristos {
29528d355d6fSchristos 	return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv);
29538d355d6fSchristos }
29548d355d6fSchristos 
29558d355d6fSchristos 
2956264891a8Schristos #ifdef CONFIG_DPP
2957264891a8Schristos 
wpa_cli_cmd_dpp_qr_code(struct wpa_ctrl * ctrl,int argc,char * argv[])2958264891a8Schristos static int wpa_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc,
2959264891a8Schristos 				   char *argv[])
2960264891a8Schristos {
2961264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv);
2962264891a8Schristos }
2963264891a8Schristos 
2964264891a8Schristos 
wpa_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl * ctrl,int argc,char * argv[])2965264891a8Schristos static int wpa_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc,
2966264891a8Schristos 					 char *argv[])
2967264891a8Schristos {
2968264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv);
2969264891a8Schristos }
2970264891a8Schristos 
2971264891a8Schristos 
wpa_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])2972264891a8Schristos static int wpa_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc,
2973264891a8Schristos 					    char *argv[])
2974264891a8Schristos {
2975264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv);
2976264891a8Schristos }
2977264891a8Schristos 
2978264891a8Schristos 
wpa_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl * ctrl,int argc,char * argv[])2979264891a8Schristos static int wpa_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl, int argc,
2980264891a8Schristos 					     char *argv[])
2981264891a8Schristos {
2982264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv);
2983264891a8Schristos }
2984264891a8Schristos 
2985264891a8Schristos 
wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl * ctrl,int argc,char * argv[])2986264891a8Schristos static int wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc,
2987264891a8Schristos 					  char *argv[])
2988264891a8Schristos {
2989264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv);
2990264891a8Schristos }
2991264891a8Schristos 
2992264891a8Schristos 
wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl * ctrl,int argc,char * argv[])2993264891a8Schristos static int wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
2994264891a8Schristos 				     char *argv[])
2995264891a8Schristos {
2996264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv);
2997264891a8Schristos }
2998264891a8Schristos 
2999264891a8Schristos 
wpa_cli_cmd_dpp_listen(struct wpa_ctrl * ctrl,int argc,char * argv[])3000264891a8Schristos static int wpa_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc,
3001264891a8Schristos 				  char *argv[])
3002264891a8Schristos {
3003264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv);
3004264891a8Schristos }
3005264891a8Schristos 
3006264891a8Schristos 
wpa_cli_cmd_dpp_stop_listen(struct wpa_ctrl * ctrl,int argc,char * argv[])3007264891a8Schristos static int wpa_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc,
3008264891a8Schristos 				       char *argv[])
3009264891a8Schristos {
3010264891a8Schristos 	return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN");
3011264891a8Schristos }
3012264891a8Schristos 
3013264891a8Schristos 
wpa_cli_cmd_dpp_configurator_add(struct wpa_ctrl * ctrl,int argc,char * argv[])3014264891a8Schristos static int wpa_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc,
3015264891a8Schristos 					    char *argv[])
3016264891a8Schristos {
3017264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv);
3018264891a8Schristos }
3019264891a8Schristos 
3020264891a8Schristos 
wpa_cli_cmd_dpp_configurator_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])3021264891a8Schristos static int wpa_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl, int argc,
3022264891a8Schristos 					       char *argv[])
3023264891a8Schristos {
3024264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv);
3025264891a8Schristos }
3026264891a8Schristos 
3027264891a8Schristos 
wpa_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl * ctrl,int argc,char * argv[])3028264891a8Schristos static int wpa_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl, int argc,
3029264891a8Schristos 						char *argv[])
3030264891a8Schristos {
3031264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv);
3032264891a8Schristos }
3033264891a8Schristos 
3034264891a8Schristos 
wpa_cli_cmd_dpp_configurator_sign(struct wpa_ctrl * ctrl,int argc,char * argv[])3035*0dddab58Schristos static int wpa_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, int argc,
3036*0dddab58Schristos 					     char *argv[])
3037*0dddab58Schristos {
3038*0dddab58Schristos 	return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv);
3039*0dddab58Schristos }
3040*0dddab58Schristos 
3041*0dddab58Schristos 
wpa_cli_cmd_dpp_pkex_add(struct wpa_ctrl * ctrl,int argc,char * argv[])3042264891a8Schristos static int wpa_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc,
3043264891a8Schristos 				    char *argv[])
3044264891a8Schristos {
3045264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv);
3046264891a8Schristos }
3047264891a8Schristos 
3048264891a8Schristos 
wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])3049264891a8Schristos static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
3050264891a8Schristos 				       char *argv[])
3051264891a8Schristos {
3052264891a8Schristos 	return wpa_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv);
3053264891a8Schristos }
3054264891a8Schristos 
3055264891a8Schristos #endif /* CONFIG_DPP */
3056264891a8Schristos 
3057264891a8Schristos 
30588dbcf02cSchristos enum wpa_cli_cmd_flags {
30598dbcf02cSchristos 	cli_cmd_flag_none		= 0x00,
30608dbcf02cSchristos 	cli_cmd_flag_sensitive		= 0x01
30618dbcf02cSchristos };
30628dbcf02cSchristos 
30638dbcf02cSchristos struct wpa_cli_cmd {
30648dbcf02cSchristos 	const char *cmd;
30658dbcf02cSchristos 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
3066da2e293dSchristos 	char ** (*completion)(const char *str, int pos);
30678dbcf02cSchristos 	enum wpa_cli_cmd_flags flags;
30688dbcf02cSchristos 	const char *usage;
30698dbcf02cSchristos };
30708dbcf02cSchristos 
30718d355d6fSchristos static const struct wpa_cli_cmd wpa_cli_commands[] = {
3072da2e293dSchristos 	{ "status", wpa_cli_cmd_status, NULL,
30738dbcf02cSchristos 	  cli_cmd_flag_none,
30748dbcf02cSchristos 	  "[verbose] = get current WPA/EAPOL/EAP status" },
3075da2e293dSchristos 	{ "ifname", wpa_cli_cmd_ifname, NULL,
3076da2e293dSchristos 	  cli_cmd_flag_none,
3077da2e293dSchristos 	  "= get current interface name" },
3078da2e293dSchristos 	{ "ping", wpa_cli_cmd_ping, NULL,
30798dbcf02cSchristos 	  cli_cmd_flag_none,
30808dbcf02cSchristos 	  "= pings wpa_supplicant" },
3081da2e293dSchristos 	{ "relog", wpa_cli_cmd_relog, NULL,
308202ec05fbSchristos 	  cli_cmd_flag_none,
308302ec05fbSchristos 	  "= re-open log-file (allow rolling logs)" },
3084da2e293dSchristos 	{ "note", wpa_cli_cmd_note, NULL,
308502ec05fbSchristos 	  cli_cmd_flag_none,
308602ec05fbSchristos 	  "<text> = add a note to wpa_supplicant debug log" },
3087da2e293dSchristos 	{ "mib", wpa_cli_cmd_mib, NULL,
30888dbcf02cSchristos 	  cli_cmd_flag_none,
30898dbcf02cSchristos 	  "= get MIB variables (dot1x, dot11)" },
3090da2e293dSchristos 	{ "help", wpa_cli_cmd_help, wpa_cli_complete_help,
30918dbcf02cSchristos 	  cli_cmd_flag_none,
3092da2e293dSchristos 	  "[command] = show usage help" },
3093da2e293dSchristos 	{ "interface", wpa_cli_cmd_interface, NULL,
30948dbcf02cSchristos 	  cli_cmd_flag_none,
30958dbcf02cSchristos 	  "[ifname] = show interfaces/select interface" },
3096da2e293dSchristos 	{ "level", wpa_cli_cmd_level, NULL,
30978dbcf02cSchristos 	  cli_cmd_flag_none,
30988dbcf02cSchristos 	  "<debug level> = change debug level" },
3099da2e293dSchristos 	{ "license", wpa_cli_cmd_license, NULL,
31008dbcf02cSchristos 	  cli_cmd_flag_none,
31018dbcf02cSchristos 	  "= show full wpa_cli license" },
3102da2e293dSchristos 	{ "quit", wpa_cli_cmd_quit, NULL,
31038dbcf02cSchristos 	  cli_cmd_flag_none,
31048dbcf02cSchristos 	  "= exit wpa_cli" },
3105c1f1514dSchristos 	{ "set", wpa_cli_cmd_set, wpa_cli_complete_set,
31068dbcf02cSchristos 	  cli_cmd_flag_none,
31078dbcf02cSchristos 	  "= set variables (shows list of variables when run without "
31088dbcf02cSchristos 	  "arguments)" },
31099a539354Schristos 	{ "dump", wpa_cli_cmd_dump, NULL,
31109a539354Schristos 	  cli_cmd_flag_none,
31119a539354Schristos 	  "= dump config variables" },
31128d355d6fSchristos 	{ "get", wpa_cli_cmd_get, wpa_cli_complete_get,
311302ec05fbSchristos 	  cli_cmd_flag_none,
311402ec05fbSchristos 	  "<name> = get information" },
31158d355d6fSchristos 	{ "driver_flags", wpa_cli_cmd_driver_flags, NULL,
31168d355d6fSchristos 	  cli_cmd_flag_none,
31178d355d6fSchristos 	  "= list driver flags" },
3118da2e293dSchristos 	{ "logon", wpa_cli_cmd_logon, NULL,
31198dbcf02cSchristos 	  cli_cmd_flag_none,
31208dbcf02cSchristos 	  "= IEEE 802.1X EAPOL state machine logon" },
3121da2e293dSchristos 	{ "logoff", wpa_cli_cmd_logoff, NULL,
31228dbcf02cSchristos 	  cli_cmd_flag_none,
31238dbcf02cSchristos 	  "= IEEE 802.1X EAPOL state machine logoff" },
3124da2e293dSchristos 	{ "pmksa", wpa_cli_cmd_pmksa, NULL,
31258dbcf02cSchristos 	  cli_cmd_flag_none,
31268dbcf02cSchristos 	  "= show PMKSA cache" },
3127c1f1514dSchristos 	{ "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
3128c1f1514dSchristos 	  cli_cmd_flag_none,
3129c1f1514dSchristos 	  "= flush PMKSA cache entries" },
3130264891a8Schristos #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
3131264891a8Schristos 	{ "pmksa_get", wpa_cli_cmd_pmksa_get, NULL,
3132264891a8Schristos 	  cli_cmd_flag_none,
3133264891a8Schristos 	  "<network_id> = fetch all stored PMKSA cache entries" },
3134264891a8Schristos 	{ "pmksa_add", wpa_cli_cmd_pmksa_add, NULL,
3135264891a8Schristos 	  cli_cmd_flag_sensitive,
3136264891a8Schristos 	  "<network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> <expiration in seconds> <akmp> <opportunistic> = store PMKSA cache entry from external storage" },
3137264891a8Schristos #ifdef CONFIG_MESH
3138264891a8Schristos 	{ "mesh_pmksa_get", wpa_cli_mesh_cmd_pmksa_get, NULL,
3139264891a8Schristos 	  cli_cmd_flag_none,
3140264891a8Schristos 	  "<peer MAC address | any> = fetch all stored mesh PMKSA cache entries" },
3141264891a8Schristos 	{ "mesh_pmksa_add", wpa_cli_mesh_cmd_pmksa_add, NULL,
3142264891a8Schristos 	  cli_cmd_flag_sensitive,
3143264891a8Schristos 	  "<BSSID> <PMKID> <PMK> <expiration in seconds> = store mesh PMKSA cache entry from external storage" },
3144264891a8Schristos #endif /* CONFIG_MESH */
3145264891a8Schristos #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
3146da2e293dSchristos 	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
31478dbcf02cSchristos 	  cli_cmd_flag_none,
31488dbcf02cSchristos 	  "= force reassociation" },
3149c1f1514dSchristos 	{ "reattach", wpa_cli_cmd_reattach, NULL,
3150c1f1514dSchristos 	  cli_cmd_flag_none,
3151c1f1514dSchristos 	  "= force reassociation back to the same BSS" },
3152da2e293dSchristos 	{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
31538dbcf02cSchristos 	  cli_cmd_flag_none,
31548dbcf02cSchristos 	  "<BSSID> = force preauthentication" },
3155264891a8Schristos 	{ "identity", wpa_cli_cmd_identity, wpa_cli_complete_network_id,
31568dbcf02cSchristos 	  cli_cmd_flag_none,
31578dbcf02cSchristos 	  "<network id> <identity> = configure identity for an SSID" },
3158264891a8Schristos 	{ "password", wpa_cli_cmd_password, wpa_cli_complete_network_id,
31598dbcf02cSchristos 	  cli_cmd_flag_sensitive,
31608dbcf02cSchristos 	  "<network id> <password> = configure password for an SSID" },
3161264891a8Schristos 	{ "new_password", wpa_cli_cmd_new_password,
3162264891a8Schristos 	  wpa_cli_complete_network_id, cli_cmd_flag_sensitive,
31638dbcf02cSchristos 	  "<network id> <password> = change password for an SSID" },
3164264891a8Schristos 	{ "pin", wpa_cli_cmd_pin, wpa_cli_complete_network_id,
31658dbcf02cSchristos 	  cli_cmd_flag_sensitive,
31668dbcf02cSchristos 	  "<network id> <pin> = configure pin for an SSID" },
3167264891a8Schristos 	{ "otp", wpa_cli_cmd_otp, wpa_cli_complete_network_id,
31688dbcf02cSchristos 	  cli_cmd_flag_sensitive,
31698dbcf02cSchristos 	  "<network id> <password> = configure one-time-password for an SSID"
31708dbcf02cSchristos 	},
3171*0dddab58Schristos 	{ "psk_passphrase", wpa_cli_cmd_psk_passphrase,
3172*0dddab58Schristos 	  wpa_cli_complete_network_id, cli_cmd_flag_sensitive,
3173*0dddab58Schristos 	  "<network id> <PSK/passphrase> = configure PSK/passphrase for an SSID" },
3174264891a8Schristos 	{ "passphrase", wpa_cli_cmd_passphrase, wpa_cli_complete_network_id,
31758dbcf02cSchristos 	  cli_cmd_flag_sensitive,
31768dbcf02cSchristos 	  "<network id> <passphrase> = configure private key passphrase\n"
31778dbcf02cSchristos 	  "  for an SSID" },
3178264891a8Schristos 	{ "sim", wpa_cli_cmd_sim, wpa_cli_complete_network_id,
3179c1f1514dSchristos 	  cli_cmd_flag_sensitive,
3180c1f1514dSchristos 	  "<network id> <pin> = report SIM operation result" },
3181264891a8Schristos 	{ "bssid", wpa_cli_cmd_bssid, wpa_cli_complete_network_id,
31828dbcf02cSchristos 	  cli_cmd_flag_none,
31838dbcf02cSchristos 	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
3184da2e293dSchristos 	{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
318502ec05fbSchristos 	  cli_cmd_flag_none,
318602ec05fbSchristos 	  "<BSSID> = add a BSSID to the blacklist\n"
318702ec05fbSchristos 	  "blacklist clear = clear the blacklist\n"
318802ec05fbSchristos 	  "blacklist = display the blacklist" },
3189da2e293dSchristos 	{ "log_level", wpa_cli_cmd_log_level, NULL,
319002ec05fbSchristos 	  cli_cmd_flag_none,
319102ec05fbSchristos 	  "<level> [<timestamp>] = update the log level/timestamp\n"
319202ec05fbSchristos 	  "log_level = display the current log level and log options" },
3193da2e293dSchristos 	{ "list_networks", wpa_cli_cmd_list_networks, NULL,
31948dbcf02cSchristos 	  cli_cmd_flag_none,
31958dbcf02cSchristos 	  "= list configured networks" },
31968d355d6fSchristos 	{ "select_network", wpa_cli_cmd_select_network,
31978d355d6fSchristos 	  wpa_cli_complete_network_id,
31988dbcf02cSchristos 	  cli_cmd_flag_none,
31998dbcf02cSchristos 	  "<network id> = select a network (disable others)" },
32008d355d6fSchristos 	{ "enable_network", wpa_cli_cmd_enable_network,
32018d355d6fSchristos 	  wpa_cli_complete_network_id,
32028dbcf02cSchristos 	  cli_cmd_flag_none,
32038dbcf02cSchristos 	  "<network id> = enable a network" },
32048d355d6fSchristos 	{ "disable_network", wpa_cli_cmd_disable_network,
32058d355d6fSchristos 	  wpa_cli_complete_network_id,
32068dbcf02cSchristos 	  cli_cmd_flag_none,
32078dbcf02cSchristos 	  "<network id> = disable a network" },
3208da2e293dSchristos 	{ "add_network", wpa_cli_cmd_add_network, NULL,
32098dbcf02cSchristos 	  cli_cmd_flag_none,
32108dbcf02cSchristos 	  "= add a network" },
32118d355d6fSchristos 	{ "remove_network", wpa_cli_cmd_remove_network,
32128d355d6fSchristos 	  wpa_cli_complete_network_id,
32138dbcf02cSchristos 	  cli_cmd_flag_none,
32148dbcf02cSchristos 	  "<network id> = remove a network" },
32158d355d6fSchristos 	{ "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
32168dbcf02cSchristos 	  cli_cmd_flag_sensitive,
32178dbcf02cSchristos 	  "<network id> <variable> <value> = set network variables (shows\n"
32188dbcf02cSchristos 	  "  list of variables when run without arguments)" },
32198d355d6fSchristos 	{ "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
32208dbcf02cSchristos 	  cli_cmd_flag_none,
32218dbcf02cSchristos 	  "<network id> <variable> = get network variables" },
32228d355d6fSchristos 	{ "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
3223c1f1514dSchristos 	  cli_cmd_flag_none,
3224c1f1514dSchristos 	  "<src network id> <dst network id> <variable> = duplicate network variables"
3225c1f1514dSchristos 	},
3226da2e293dSchristos 	{ "list_creds", wpa_cli_cmd_list_creds, NULL,
3227da2e293dSchristos 	  cli_cmd_flag_none,
3228da2e293dSchristos 	  "= list configured credentials" },
3229da2e293dSchristos 	{ "add_cred", wpa_cli_cmd_add_cred, NULL,
3230da2e293dSchristos 	  cli_cmd_flag_none,
3231da2e293dSchristos 	  "= add a credential" },
3232da2e293dSchristos 	{ "remove_cred", wpa_cli_cmd_remove_cred, NULL,
3233da2e293dSchristos 	  cli_cmd_flag_none,
3234da2e293dSchristos 	  "<cred id> = remove a credential" },
3235264891a8Schristos 	{ "set_cred", wpa_cli_cmd_set_cred, wpa_cli_complete_cred,
3236da2e293dSchristos 	  cli_cmd_flag_sensitive,
3237da2e293dSchristos 	  "<cred id> <variable> <value> = set credential variables" },
3238264891a8Schristos 	{ "get_cred", wpa_cli_cmd_get_cred, wpa_cli_complete_cred,
3239c1f1514dSchristos 	  cli_cmd_flag_none,
3240c1f1514dSchristos 	  "<cred id> <variable> = get credential variables" },
3241da2e293dSchristos 	{ "save_config", wpa_cli_cmd_save_config, NULL,
32428dbcf02cSchristos 	  cli_cmd_flag_none,
32438dbcf02cSchristos 	  "= save the current configuration" },
3244da2e293dSchristos 	{ "disconnect", wpa_cli_cmd_disconnect, NULL,
32458dbcf02cSchristos 	  cli_cmd_flag_none,
32468dbcf02cSchristos 	  "= disconnect and wait for reassociate/reconnect command before\n"
32478dbcf02cSchristos 	  "  connecting" },
3248da2e293dSchristos 	{ "reconnect", wpa_cli_cmd_reconnect, NULL,
32498dbcf02cSchristos 	  cli_cmd_flag_none,
32508dbcf02cSchristos 	  "= like reassociate, but only takes effect if already disconnected"
32518dbcf02cSchristos 	},
3252da2e293dSchristos 	{ "scan", wpa_cli_cmd_scan, NULL,
32538dbcf02cSchristos 	  cli_cmd_flag_none,
32548dbcf02cSchristos 	  "= request new BSS scan" },
3255da2e293dSchristos 	{ "scan_results", wpa_cli_cmd_scan_results, NULL,
32568dbcf02cSchristos 	  cli_cmd_flag_none,
32578dbcf02cSchristos 	  "= get latest scan results" },
32588d355d6fSchristos 	{ "abort_scan", wpa_cli_cmd_abort_scan, NULL,
32598d355d6fSchristos 	  cli_cmd_flag_none,
32608d355d6fSchristos 	  "= request ongoing scan to be aborted" },
3261da2e293dSchristos 	{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
32628dbcf02cSchristos 	  cli_cmd_flag_none,
32638dbcf02cSchristos 	  "<<idx> | <bssid>> = get detailed scan result info" },
32648d355d6fSchristos 	{ "get_capability", wpa_cli_cmd_get_capability,
32658d355d6fSchristos 	  wpa_cli_complete_get_capability, cli_cmd_flag_none,
3266c1f1514dSchristos 	  "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
32678d355d6fSchristos 	  "= get capabilities" },
3268da2e293dSchristos 	{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
32698dbcf02cSchristos 	  cli_cmd_flag_none,
32708dbcf02cSchristos 	  "= force wpa_supplicant to re-read its configuration file" },
3271da2e293dSchristos 	{ "terminate", wpa_cli_cmd_terminate, NULL,
32728dbcf02cSchristos 	  cli_cmd_flag_none,
32738dbcf02cSchristos 	  "= terminate wpa_supplicant" },
3274da2e293dSchristos 	{ "interface_add", wpa_cli_cmd_interface_add, NULL,
32758dbcf02cSchristos 	  cli_cmd_flag_none,
32768dbcf02cSchristos 	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
32778d355d6fSchristos 	  "  <bridge_name> <create> <type> = adds new interface, all "
32788d355d6fSchristos 	  "parameters but\n"
32798d355d6fSchristos 	  "  <ifname> are optional. Supported types are station ('sta') and "
32808d355d6fSchristos 	  "AP ('ap')" },
3281da2e293dSchristos 	{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
32828dbcf02cSchristos 	  cli_cmd_flag_none,
32838dbcf02cSchristos 	  "<ifname> = removes the interface" },
3284da2e293dSchristos 	{ "interface_list", wpa_cli_cmd_interface_list, NULL,
32858dbcf02cSchristos 	  cli_cmd_flag_none,
32868dbcf02cSchristos 	  "= list available interfaces" },
3287da2e293dSchristos 	{ "ap_scan", wpa_cli_cmd_ap_scan, NULL,
32888dbcf02cSchristos 	  cli_cmd_flag_none,
32898dbcf02cSchristos 	  "<value> = set ap_scan parameter" },
3290da2e293dSchristos 	{ "scan_interval", wpa_cli_cmd_scan_interval, NULL,
329102ec05fbSchristos 	  cli_cmd_flag_none,
329202ec05fbSchristos 	  "<value> = set scan_interval parameter (in seconds)" },
3293da2e293dSchristos 	{ "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
329402ec05fbSchristos 	  cli_cmd_flag_none,
329502ec05fbSchristos 	  "<value> = set BSS expiration age parameter" },
3296da2e293dSchristos 	{ "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
329702ec05fbSchristos 	  cli_cmd_flag_none,
329802ec05fbSchristos 	  "<value> = set BSS expiration scan count parameter" },
3299da2e293dSchristos 	{ "bss_flush", wpa_cli_cmd_bss_flush, NULL,
3300da2e293dSchristos 	  cli_cmd_flag_none,
3301da2e293dSchristos 	  "<value> = set BSS flush age (0 by default)" },
3302da2e293dSchristos 	{ "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
33038dbcf02cSchristos 	  cli_cmd_flag_none,
33048dbcf02cSchristos 	  "<addr> = request over-the-DS FT with <addr>" },
3305da2e293dSchristos 	{ "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
33068dbcf02cSchristos 	  cli_cmd_flag_none,
33078dbcf02cSchristos 	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
3308da2e293dSchristos 	{ "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
33098dbcf02cSchristos 	  cli_cmd_flag_sensitive,
33108dbcf02cSchristos 	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
33118dbcf02cSchristos 	  "hardcoded)" },
3312da2e293dSchristos 	{ "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
331302ec05fbSchristos 	  cli_cmd_flag_sensitive,
331402ec05fbSchristos 	  "<PIN> = verify PIN checksum" },
3315da2e293dSchristos 	{ "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
331602ec05fbSchristos 	  "Cancels the pending WPS operation" },
3317da2e293dSchristos #ifdef CONFIG_WPS_NFC
3318da2e293dSchristos 	{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
3319da2e293dSchristos 	  cli_cmd_flag_none,
3320da2e293dSchristos 	  "[BSSID] = start Wi-Fi Protected Setup: NFC" },
3321c1f1514dSchristos 	{ "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3322c1f1514dSchristos 	  cli_cmd_flag_none,
3323c1f1514dSchristos 	  "<WPS|NDEF> = build configuration token" },
3324da2e293dSchristos 	{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
3325da2e293dSchristos 	  cli_cmd_flag_none,
3326da2e293dSchristos 	  "<WPS|NDEF> = create password token" },
3327da2e293dSchristos 	{ "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
33288dbcf02cSchristos 	  cli_cmd_flag_sensitive,
3329da2e293dSchristos 	  "<hexdump of payload> = report read NFC tag with WPS data" },
3330da2e293dSchristos 	{ "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3331da2e293dSchristos 	  cli_cmd_flag_none,
3332da2e293dSchristos 	  "<NDEF> <WPS> = create NFC handover request" },
3333da2e293dSchristos 	{ "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3334da2e293dSchristos 	  cli_cmd_flag_none,
3335da2e293dSchristos 	  "<NDEF> <WPS> = create NFC handover select" },
3336c1f1514dSchristos 	{ "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3337da2e293dSchristos 	  cli_cmd_flag_none,
3338c1f1514dSchristos 	  "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3339c1f1514dSchristos 	  "NFC handover" },
3340da2e293dSchristos #endif /* CONFIG_WPS_NFC */
3341da2e293dSchristos 	{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
33428dbcf02cSchristos 	  cli_cmd_flag_sensitive,
33438dbcf02cSchristos 	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
3344da2e293dSchristos 	{ "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
334502ec05fbSchristos 	  cli_cmd_flag_sensitive,
334602ec05fbSchristos 	  "[params..] = enable/disable AP PIN" },
3347da2e293dSchristos 	{ "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
33488dbcf02cSchristos 	  cli_cmd_flag_none,
334902ec05fbSchristos 	  "[IP address] = start Wi-Fi Protected Setup External Registrar" },
3350da2e293dSchristos 	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
33518dbcf02cSchristos 	  cli_cmd_flag_none,
33528dbcf02cSchristos 	  "= stop Wi-Fi Protected Setup External Registrar" },
3353da2e293dSchristos 	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
33548dbcf02cSchristos 	  cli_cmd_flag_sensitive,
33558dbcf02cSchristos 	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
3356da2e293dSchristos 	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
33578dbcf02cSchristos 	  cli_cmd_flag_none,
33588dbcf02cSchristos 	  "<UUID> = accept an Enrollee PBC using External Registrar" },
3359da2e293dSchristos 	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
33608dbcf02cSchristos 	  cli_cmd_flag_sensitive,
33618dbcf02cSchristos 	  "<UUID> <PIN> = learn AP configuration" },
3362da2e293dSchristos 	{ "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
336302ec05fbSchristos 	  cli_cmd_flag_none,
336402ec05fbSchristos 	  "<UUID> <network id> = set AP configuration for enrolling" },
3365da2e293dSchristos 	{ "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
336602ec05fbSchristos 	  cli_cmd_flag_sensitive,
336702ec05fbSchristos 	  "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
3368da2e293dSchristos #ifdef CONFIG_WPS_NFC
3369da2e293dSchristos 	{ "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
3370da2e293dSchristos 	  cli_cmd_flag_none,
3371da2e293dSchristos 	  "<WPS/NDEF> <UUID> = build NFC configuration token" },
3372da2e293dSchristos #endif /* CONFIG_WPS_NFC */
3373da2e293dSchristos 	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
33748dbcf02cSchristos 	  cli_cmd_flag_none,
33758dbcf02cSchristos 	  "<addr> = request RSN authentication with <addr> in IBSS" },
33768dbcf02cSchristos #ifdef CONFIG_AP
3377264891a8Schristos 	{ "sta", wpa_cli_cmd_sta, wpa_cli_complete_sta,
33788dbcf02cSchristos 	  cli_cmd_flag_none,
33798dbcf02cSchristos 	  "<addr> = get information about an associated station (AP)" },
3380da2e293dSchristos 	{ "all_sta", wpa_cli_cmd_all_sta, NULL,
33818dbcf02cSchristos 	  cli_cmd_flag_none,
33828dbcf02cSchristos 	  "= get information about all associated stations (AP)" },
3383264891a8Schristos 	{ "list_sta", wpa_cli_cmd_list_sta, NULL,
3384da2e293dSchristos 	  cli_cmd_flag_none,
3385264891a8Schristos 	  "= list all stations (AP)" },
3386264891a8Schristos 	{ "deauthenticate", wpa_cli_cmd_deauthenticate,
3387264891a8Schristos 	  wpa_cli_complete_deauthenticate, cli_cmd_flag_none,
3388da2e293dSchristos 	  "<addr> = deauthenticate a station" },
3389264891a8Schristos 	{ "disassociate", wpa_cli_cmd_disassociate,
3390264891a8Schristos 	  wpa_cli_complete_disassociate, cli_cmd_flag_none,
3391da2e293dSchristos 	  "<addr> = disassociate a station" },
3392c1f1514dSchristos 	{ "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3393c1f1514dSchristos 	  cli_cmd_flag_none,
3394c1f1514dSchristos 	  "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3395c1f1514dSchristos 	  " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3396c1f1514dSchristos 	  " = CSA parameters" },
33978dbcf02cSchristos #endif /* CONFIG_AP */
3398da2e293dSchristos 	{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
33998dbcf02cSchristos 	  "= notification of suspend/hibernate" },
3400da2e293dSchristos 	{ "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
34018dbcf02cSchristos 	  "= notification of resume/thaw" },
3402c1f1514dSchristos #ifdef CONFIG_TESTING_OPTIONS
3403da2e293dSchristos 	{ "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
34048dbcf02cSchristos 	  "= drop SA without deauth/disassoc (test command)" },
3405c1f1514dSchristos #endif /* CONFIG_TESTING_OPTIONS */
3406da2e293dSchristos 	{ "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
34078dbcf02cSchristos 	  cli_cmd_flag_none,
34088dbcf02cSchristos 	  "<addr> = roam to the specified BSS" },
34099a539354Schristos #ifdef CONFIG_MESH
34109a539354Schristos 	{ "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
34119a539354Schristos 	  cli_cmd_flag_none,
34129a539354Schristos 	  "[ifname] = Create a new mesh interface" },
34139a539354Schristos 	{ "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
34149a539354Schristos 	  cli_cmd_flag_none,
34159a539354Schristos 	  "<network id> = join a mesh network (disable others)" },
34169a539354Schristos 	{ "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
34179a539354Schristos 	  cli_cmd_flag_none,
34189a539354Schristos 	  "<ifname> = Remove mesh group interface" },
34198d355d6fSchristos 	{ "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
34208d355d6fSchristos 	  cli_cmd_flag_none,
34218d355d6fSchristos 	  "<addr> = Remove a mesh peer" },
34228d355d6fSchristos 	{ "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
34238d355d6fSchristos 	  cli_cmd_flag_none,
34248d355d6fSchristos 	  "<addr> [duration=<seconds>] = Add a mesh peer" },
3425*0dddab58Schristos 	{ "mesh_link_probe", wpa_cli_cmd_mesh_link_probe, NULL,
3426*0dddab58Schristos 	  cli_cmd_flag_none,
3427*0dddab58Schristos 	  "<addr> [payload=<hex dump of payload>] = Probe a mesh link for a given peer by injecting a frame." },
34289a539354Schristos #endif /* CONFIG_MESH */
342902ec05fbSchristos #ifdef CONFIG_P2P
3430da2e293dSchristos 	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3431da2e293dSchristos 	  cli_cmd_flag_none,
343202ec05fbSchristos 	  "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3433da2e293dSchristos 	{ "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
343402ec05fbSchristos 	  "= stop P2P Devices search" },
34359a539354Schristos 	{ "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
34369a539354Schristos 	  cli_cmd_flag_none,
34379a539354Schristos 	  "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
34389a539354Schristos 	{ "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
34399a539354Schristos 	  cli_cmd_flag_none,
34409a539354Schristos 	  "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
3441da2e293dSchristos 	{ "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3442da2e293dSchristos 	  cli_cmd_flag_none,
3443da2e293dSchristos 	  "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3444da2e293dSchristos 	{ "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
344502ec05fbSchristos 	  "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3446da2e293dSchristos 	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3447da2e293dSchristos 	  wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
344802ec05fbSchristos 	  "<ifname> = remove P2P group interface (terminate group if GO)" },
3449da2e293dSchristos 	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3450da2e293dSchristos 	  "[ht40] = add a new P2P group (local end as GO)" },
34518d355d6fSchristos 	{ "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL,
34528d355d6fSchristos 	  cli_cmd_flag_none,
34538d355d6fSchristos 	  "<dev_addr> = Get peer interface address on local GO using peer Device Address" },
3454da2e293dSchristos 	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3455da2e293dSchristos 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
345602ec05fbSchristos 	  "<addr> <method> = request provisioning discovery" },
3457da2e293dSchristos 	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
345802ec05fbSchristos 	  cli_cmd_flag_none,
345902ec05fbSchristos 	  "= get the passphrase for a group (GO only)" },
346002ec05fbSchristos 	{ "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3461da2e293dSchristos 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
346202ec05fbSchristos 	  "<addr> <TLVs> = schedule service discovery request" },
346302ec05fbSchristos 	{ "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3464da2e293dSchristos 	  NULL, cli_cmd_flag_none,
346502ec05fbSchristos 	  "<id> = cancel pending service discovery request" },
3466da2e293dSchristos 	{ "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
346702ec05fbSchristos 	  cli_cmd_flag_none,
346802ec05fbSchristos 	  "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3469da2e293dSchristos 	{ "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
347002ec05fbSchristos 	  cli_cmd_flag_none,
347102ec05fbSchristos 	  "= indicate change in local services" },
3472da2e293dSchristos 	{ "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
347302ec05fbSchristos 	  cli_cmd_flag_none,
347402ec05fbSchristos 	  "<external> = set external processing of service discovery" },
3475da2e293dSchristos 	{ "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
347602ec05fbSchristos 	  cli_cmd_flag_none,
347702ec05fbSchristos 	  "= remove all stored service entries" },
3478da2e293dSchristos 	{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
347902ec05fbSchristos 	  cli_cmd_flag_none,
34809a539354Schristos 	  "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
348102ec05fbSchristos 	  "service" },
34829a539354Schristos 	{ "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
34839a539354Schristos 	  cli_cmd_flag_none,
34849a539354Schristos 	  "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
34859a539354Schristos 	  "local ASP service" },
3486da2e293dSchristos 	{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
348702ec05fbSchristos 	  cli_cmd_flag_none,
348802ec05fbSchristos 	  "<bonjour|upnp> <query|version> [|service] = remove a local "
348902ec05fbSchristos 	  "service" },
3490da2e293dSchristos 	{ "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
349102ec05fbSchristos 	  cli_cmd_flag_none,
349202ec05fbSchristos 	  "<addr> = reject connection attempts from a specific peer" },
3493da2e293dSchristos 	{ "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
349402ec05fbSchristos 	  cli_cmd_flag_none,
349502ec05fbSchristos 	  "<cmd> [peer=addr] = invite peer" },
3496da2e293dSchristos 	{ "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
349702ec05fbSchristos 	  "[discovered] = list known (optionally, only fully discovered) P2P "
349802ec05fbSchristos 	  "peers" },
3499da2e293dSchristos 	{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3500da2e293dSchristos 	  cli_cmd_flag_none,
350102ec05fbSchristos 	  "<address> = show information about known P2P peer" },
3502c1f1514dSchristos 	{ "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3503c1f1514dSchristos 	  cli_cmd_flag_none,
350402ec05fbSchristos 	  "<field> <value> = set a P2P parameter" },
3505da2e293dSchristos 	{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
350602ec05fbSchristos 	  "= flush P2P state" },
3507da2e293dSchristos 	{ "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
350802ec05fbSchristos 	  "= cancel P2P group formation" },
3509da2e293dSchristos 	{ "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3510da2e293dSchristos 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
351102ec05fbSchristos 	  "<address> = unauthorize a peer" },
3512da2e293dSchristos 	{ "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3513da2e293dSchristos 	  cli_cmd_flag_none,
351402ec05fbSchristos 	  "[<duration> <interval>] [<duration> <interval>] = request GO "
351502ec05fbSchristos 	  "presence" },
3516da2e293dSchristos 	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3517da2e293dSchristos 	  cli_cmd_flag_none,
351802ec05fbSchristos 	  "[<period> <interval>] = set extended listen timing" },
3519c1f1514dSchristos 	{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3520c1f1514dSchristos 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3521c1f1514dSchristos 	  "<address|iface=address> = remove a peer from all groups" },
3522264891a8Schristos #endif /* CONFIG_P2P */
35238d355d6fSchristos 	{ "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
35248d355d6fSchristos 	  cli_cmd_flag_none,
35258d355d6fSchristos 	  "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
35268d355d6fSchristos 	  VENDOR_ELEM_FRAME_ID },
35278d355d6fSchristos 	{ "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
35288d355d6fSchristos 	  cli_cmd_flag_none,
35298d355d6fSchristos 	  "<frame id> = get vendor specific IE(s) to frame(s)\n"
35308d355d6fSchristos 	  VENDOR_ELEM_FRAME_ID },
35318d355d6fSchristos 	{ "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
35328d355d6fSchristos 	  cli_cmd_flag_none,
35338d355d6fSchristos 	  "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
35348d355d6fSchristos 	  VENDOR_ELEM_FRAME_ID },
3535da2e293dSchristos #ifdef CONFIG_WIFI_DISPLAY
3536da2e293dSchristos 	{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3537da2e293dSchristos 	  cli_cmd_flag_none,
3538da2e293dSchristos 	  "<subelem> [contents] = set Wi-Fi Display subelement" },
3539da2e293dSchristos 	{ "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3540da2e293dSchristos 	  cli_cmd_flag_none,
3541da2e293dSchristos 	  "<subelem> = get Wi-Fi Display subelement" },
3542da2e293dSchristos #endif /* CONFIG_WIFI_DISPLAY */
354302ec05fbSchristos #ifdef CONFIG_INTERWORKING
3544da2e293dSchristos 	{ "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
354502ec05fbSchristos 	  "= fetch ANQP information for all APs" },
3546da2e293dSchristos 	{ "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3547da2e293dSchristos 	  cli_cmd_flag_none,
354802ec05fbSchristos 	  "= stop fetch_anqp operation" },
3549da2e293dSchristos 	{ "interworking_select", wpa_cli_cmd_interworking_select, NULL,
355002ec05fbSchristos 	  cli_cmd_flag_none,
355102ec05fbSchristos 	  "[auto] = perform Interworking network selection" },
355202ec05fbSchristos 	{ "interworking_connect", wpa_cli_cmd_interworking_connect,
3553da2e293dSchristos 	  wpa_cli_complete_bss, cli_cmd_flag_none,
355402ec05fbSchristos 	  "<BSSID> = connect using Interworking credentials" },
35559a539354Schristos 	{ "interworking_add_network", wpa_cli_cmd_interworking_add_network,
35569a539354Schristos 	  wpa_cli_complete_bss, cli_cmd_flag_none,
35579a539354Schristos 	  "<BSSID> = connect using Interworking credentials" },
3558da2e293dSchristos 	{ "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3559da2e293dSchristos 	  cli_cmd_flag_none,
356002ec05fbSchristos 	  "<addr> <info id>[,<info id>]... = request ANQP information" },
3561da2e293dSchristos 	{ "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3562da2e293dSchristos 	  cli_cmd_flag_none,
3563da2e293dSchristos 	  "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3564da2e293dSchristos 	{ "gas_response_get", wpa_cli_cmd_gas_response_get,
3565da2e293dSchristos 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3566da2e293dSchristos 	  "<addr> <dialog token> [start,len] = Fetch last GAS response" },
356702ec05fbSchristos #endif /* CONFIG_INTERWORKING */
3568da2e293dSchristos #ifdef CONFIG_HS20
3569da2e293dSchristos 	{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3570da2e293dSchristos 	  cli_cmd_flag_none,
3571da2e293dSchristos 	  "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3572da2e293dSchristos 	},
3573da2e293dSchristos 	{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3574da2e293dSchristos 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3575da2e293dSchristos 	  "<addr> <home realm> = get HS20 nai home realm list" },
3576c1f1514dSchristos 	{ "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3577c1f1514dSchristos 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3578c1f1514dSchristos 	  "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3579c1f1514dSchristos 	{ "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3580c1f1514dSchristos 	  "= fetch OSU provider information from all APs" },
3581c1f1514dSchristos 	{ "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3582c1f1514dSchristos 	  cli_cmd_flag_none,
3583c1f1514dSchristos 	  "= cancel fetch_osu command" },
3584da2e293dSchristos #endif /* CONFIG_HS20 */
3585da2e293dSchristos 	{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3586da2e293dSchristos 	  cli_cmd_flag_none,
358702ec05fbSchristos 	  "<0/1> = disable/enable automatic reconnection" },
3588da2e293dSchristos 	{ "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
358902ec05fbSchristos 	  cli_cmd_flag_none,
359002ec05fbSchristos 	  "<addr> = request TDLS discovery with <addr>" },
3591da2e293dSchristos 	{ "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
359202ec05fbSchristos 	  cli_cmd_flag_none,
359302ec05fbSchristos 	  "<addr> = request TDLS setup with <addr>" },
3594da2e293dSchristos 	{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
359502ec05fbSchristos 	  cli_cmd_flag_none,
359602ec05fbSchristos 	  "<addr> = tear down TDLS with <addr>" },
35978d355d6fSchristos 	{ "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
35988d355d6fSchristos 	  cli_cmd_flag_none,
35998d355d6fSchristos 	  "<addr> = TDLS link status with <addr>" },
36009a539354Schristos 	{ "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
36019a539354Schristos 	  cli_cmd_flag_none,
36029a539354Schristos 	  "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
36039a539354Schristos 	  "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
36049a539354Schristos 	  "= add WMM-AC traffic stream" },
36059a539354Schristos 	{ "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
36069a539354Schristos 	  cli_cmd_flag_none,
36079a539354Schristos 	  "<tsid> = delete WMM-AC traffic stream" },
36089a539354Schristos 	{ "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
36099a539354Schristos 	  cli_cmd_flag_none,
36109a539354Schristos 	  "= show status for Wireless Multi-Media Admission-Control" },
36119a539354Schristos 	{ "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
36129a539354Schristos 	  cli_cmd_flag_none,
36139a539354Schristos 	  "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
36149a539354Schristos 	  "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
36159a539354Schristos 	  "with TDLS peer" },
36169a539354Schristos 	{ "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
36179a539354Schristos 	  cli_cmd_flag_none,
36189a539354Schristos 	  "<addr> = disable channel switching with TDLS peer <addr>" },
3619da2e293dSchristos 	{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
362002ec05fbSchristos 	  cli_cmd_flag_none,
362102ec05fbSchristos 	  "= get signal parameters" },
36228d355d6fSchristos 	{ "signal_monitor", wpa_cli_cmd_signal_monitor, NULL,
36238d355d6fSchristos 	  cli_cmd_flag_none,
36248d355d6fSchristos 	  "= set signal monitor parameters" },
3625da2e293dSchristos 	{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3626da2e293dSchristos 	  cli_cmd_flag_none,
3627da2e293dSchristos 	  "= get TX/RX packet counters" },
3628da2e293dSchristos 	{ "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3629da2e293dSchristos 	  cli_cmd_flag_none,
3630da2e293dSchristos 	  "= trigger IEEE 802.1X/EAPOL reauthentication" },
3631da2e293dSchristos #ifdef CONFIG_AUTOSCAN
3632da2e293dSchristos 	{ "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
3633da2e293dSchristos 	  "[params] = Set or unset (if none) autoscan parameters" },
3634da2e293dSchristos #endif /* CONFIG_AUTOSCAN */
3635da2e293dSchristos #ifdef CONFIG_WNM
3636da2e293dSchristos 	{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3637da2e293dSchristos 	  "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
3638c1f1514dSchristos 	{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3639264891a8Schristos 	  "<query reason> [list]"
3640264891a8Schristos 	  " [neighbor=<BSSID>,<BSSID information>,<operating class>,<channel number>,<PHY type>[,<hexdump of optional subelements>]"
3641264891a8Schristos 	  " = Send BSS Transition Management Query" },
3642da2e293dSchristos #endif /* CONFIG_WNM */
3643da2e293dSchristos 	{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3644da2e293dSchristos 	  "<params..> = Sent unprocessed command" },
3645c1f1514dSchristos 	{ "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3646c1f1514dSchristos 	  "= flush wpa_supplicant state" },
3647c1f1514dSchristos #ifdef ANDROID
3648c1f1514dSchristos 	{ "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3649c1f1514dSchristos 	  "<command> = driver private commands" },
3650c1f1514dSchristos #endif /* ANDROID */
3651c1f1514dSchristos 	{ "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3652c1f1514dSchristos 	  "= radio_work <show/add/done>" },
3653c1f1514dSchristos 	{ "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3654c1f1514dSchristos 	  "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3655c1f1514dSchristos 	},
36569a539354Schristos 	{ "neighbor_rep_request",
36579a539354Schristos 	  wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
36588d355d6fSchristos 	  "[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)"
36599a539354Schristos 	},
36609a539354Schristos 	{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
36619a539354Schristos 	  "= flush ERP keys" },
36629a539354Schristos 	{ "mac_rand_scan",
36639a539354Schristos 	  wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
36649a539354Schristos 	  "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
36659a539354Schristos 	  "mask=mac-address-mask] = scan MAC randomization"
36669a539354Schristos 	},
36678d355d6fSchristos 	{ "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
36688d355d6fSchristos 	  cli_cmd_flag_none,
36698d355d6fSchristos 	  "<interface type> = retrieve preferred freq list for the specified interface type" },
36708d355d6fSchristos 	{ "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL,
36718d355d6fSchristos 	  cli_cmd_flag_none,
36728d355d6fSchristos 	  "<freq> <period> <interval> <count> = start P2P listen offload" },
36738d355d6fSchristos 	{ "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
36748d355d6fSchristos 	  cli_cmd_flag_none,
36758d355d6fSchristos 	  "= stop P2P listen offload" },
3676264891a8Schristos #ifdef CONFIG_DPP
3677264891a8Schristos 	{ "dpp_qr_code", wpa_cli_cmd_dpp_qr_code, NULL, cli_cmd_flag_none,
3678264891a8Schristos 	  "report a scanned DPP URI from a QR Code" },
3679264891a8Schristos 	{ "dpp_bootstrap_gen", wpa_cli_cmd_dpp_bootstrap_gen, NULL,
3680264891a8Schristos 	  cli_cmd_flag_sensitive,
3681264891a8Schristos 	  "type=<qrcode> [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" },
3682264891a8Schristos 	{ "dpp_bootstrap_remove", wpa_cli_cmd_dpp_bootstrap_remove, NULL,
3683264891a8Schristos 	  cli_cmd_flag_none,
3684264891a8Schristos 	  "*|<id> = remove DPP bootstrap information" },
3685264891a8Schristos 	{ "dpp_bootstrap_get_uri", wpa_cli_cmd_dpp_bootstrap_get_uri, NULL,
3686264891a8Schristos 	  cli_cmd_flag_none,
3687264891a8Schristos 	  "<id> = get DPP bootstrap URI" },
3688264891a8Schristos 	{ "dpp_bootstrap_info", wpa_cli_cmd_dpp_bootstrap_info, NULL,
3689264891a8Schristos 	  cli_cmd_flag_none,
3690264891a8Schristos 	  "<id> = show DPP bootstrap information" },
3691264891a8Schristos 	{ "dpp_auth_init", wpa_cli_cmd_dpp_auth_init, NULL, cli_cmd_flag_none,
3692264891a8Schristos 	  "peer=<id> [own=<id>] = initiate DPP bootstrapping" },
3693264891a8Schristos 	{ "dpp_listen", wpa_cli_cmd_dpp_listen, NULL, cli_cmd_flag_none,
3694264891a8Schristos 	  "<freq in MHz> = start DPP listen" },
3695264891a8Schristos 	{ "dpp_stop_listen", wpa_cli_cmd_dpp_stop_listen, NULL,
3696264891a8Schristos 	  cli_cmd_flag_none,
3697264891a8Schristos 	  "= stop DPP listen" },
3698264891a8Schristos 	{ "dpp_configurator_add", wpa_cli_cmd_dpp_configurator_add, NULL,
3699264891a8Schristos 	  cli_cmd_flag_sensitive,
3700264891a8Schristos 	  "[curve=..] [key=..] = add DPP configurator" },
3701264891a8Schristos 	{ "dpp_configurator_remove", wpa_cli_cmd_dpp_configurator_remove, NULL,
3702264891a8Schristos 	  cli_cmd_flag_none,
3703264891a8Schristos 	  "*|<id> = remove DPP configurator" },
3704264891a8Schristos 	{ "dpp_configurator_get_key", wpa_cli_cmd_dpp_configurator_get_key,
3705264891a8Schristos 	  NULL, cli_cmd_flag_none,
3706264891a8Schristos 	  "<id> = Get DPP configurator's private key" },
3707*0dddab58Schristos 	{ "dpp_configurator_sign", wpa_cli_cmd_dpp_configurator_sign, NULL,
3708*0dddab58Schristos 	  cli_cmd_flag_none,
3709*0dddab58Schristos 	  "conf=<role> configurator=<id> = generate self DPP configuration" },
3710264891a8Schristos 	{ "dpp_pkex_add", wpa_cli_cmd_dpp_pkex_add, NULL,
3711264891a8Schristos 	  cli_cmd_flag_sensitive,
3712264891a8Schristos 	  "add PKEX code" },
3713264891a8Schristos 	{ "dpp_pkex_remove", wpa_cli_cmd_dpp_pkex_remove, NULL,
3714264891a8Schristos 	  cli_cmd_flag_none,
3715264891a8Schristos 	  "*|<id> = remove DPP pkex information" },
3716264891a8Schristos #endif /* CONFIG_DPP */
3717da2e293dSchristos 	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
37188dbcf02cSchristos };
37198dbcf02cSchristos 
37208dbcf02cSchristos 
37218dbcf02cSchristos /*
37228dbcf02cSchristos  * Prints command usage, lines are padded with the specified string.
37238dbcf02cSchristos  */
print_cmd_help(const struct wpa_cli_cmd * cmd,const char * pad)37248d355d6fSchristos static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
37258dbcf02cSchristos {
37268dbcf02cSchristos 	char c;
37278dbcf02cSchristos 	size_t n;
37288dbcf02cSchristos 
37298dbcf02cSchristos 	printf("%s%s ", pad, cmd->cmd);
37308dbcf02cSchristos 	for (n = 0; (c = cmd->usage[n]); n++) {
37318dbcf02cSchristos 		printf("%c", c);
37328dbcf02cSchristos 		if (c == '\n')
37338dbcf02cSchristos 			printf("%s", pad);
37348dbcf02cSchristos 	}
37358dbcf02cSchristos 	printf("\n");
37368dbcf02cSchristos }
37378dbcf02cSchristos 
37388dbcf02cSchristos 
print_help(const char * cmd)3739da2e293dSchristos static void print_help(const char *cmd)
37408dbcf02cSchristos {
37418dbcf02cSchristos 	int n;
37428dbcf02cSchristos 	printf("commands:\n");
3743da2e293dSchristos 	for (n = 0; wpa_cli_commands[n].cmd; n++) {
3744da2e293dSchristos 		if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
37458dbcf02cSchristos 			print_cmd_help(&wpa_cli_commands[n], "  ");
37468dbcf02cSchristos 	}
3747da2e293dSchristos }
37488dbcf02cSchristos 
37498dbcf02cSchristos 
wpa_cli_edit_filter_history_cb(void * ctx,const char * cmd)375002ec05fbSchristos static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
37518dbcf02cSchristos {
37528dbcf02cSchristos 	const char *c, *delim;
37538dbcf02cSchristos 	int n;
37548dbcf02cSchristos 	size_t len;
37558dbcf02cSchristos 
37568dbcf02cSchristos 	delim = os_strchr(cmd, ' ');
37578dbcf02cSchristos 	if (delim)
37588dbcf02cSchristos 		len = delim - cmd;
37598dbcf02cSchristos 	else
37608dbcf02cSchristos 		len = os_strlen(cmd);
37618dbcf02cSchristos 
37628dbcf02cSchristos 	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
37638dbcf02cSchristos 		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
37648dbcf02cSchristos 			return (wpa_cli_commands[n].flags &
37658dbcf02cSchristos 				cli_cmd_flag_sensitive);
37668dbcf02cSchristos 	}
37678dbcf02cSchristos 	return 0;
37688dbcf02cSchristos }
376902ec05fbSchristos 
377002ec05fbSchristos 
wpa_list_cmd_list(void)377102ec05fbSchristos static char ** wpa_list_cmd_list(void)
377202ec05fbSchristos {
377302ec05fbSchristos 	char **res;
377402ec05fbSchristos 	int i, count;
3775c1f1514dSchristos 	struct cli_txt_entry *e;
377602ec05fbSchristos 
3777c1f1514dSchristos 	count = ARRAY_SIZE(wpa_cli_commands);
3778c1f1514dSchristos 	count += dl_list_len(&p2p_groups);
3779c1f1514dSchristos 	count += dl_list_len(&ifnames);
3780c1f1514dSchristos 	res = os_calloc(count + 1, sizeof(char *));
378102ec05fbSchristos 	if (res == NULL)
378202ec05fbSchristos 		return NULL;
378302ec05fbSchristos 
378402ec05fbSchristos 	for (i = 0; wpa_cli_commands[i].cmd; i++) {
378502ec05fbSchristos 		res[i] = os_strdup(wpa_cli_commands[i].cmd);
378602ec05fbSchristos 		if (res[i] == NULL)
378702ec05fbSchristos 			break;
378802ec05fbSchristos 	}
378902ec05fbSchristos 
3790c1f1514dSchristos 	dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3791c1f1514dSchristos 		size_t len = 8 + os_strlen(e->txt);
3792c1f1514dSchristos 		res[i] = os_malloc(len);
3793c1f1514dSchristos 		if (res[i] == NULL)
3794c1f1514dSchristos 			break;
3795c1f1514dSchristos 		os_snprintf(res[i], len, "ifname=%s", e->txt);
3796c1f1514dSchristos 		i++;
3797c1f1514dSchristos 	}
3798c1f1514dSchristos 
3799c1f1514dSchristos 	dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3800c1f1514dSchristos 		res[i] = os_strdup(e->txt);
3801c1f1514dSchristos 		if (res[i] == NULL)
3802c1f1514dSchristos 			break;
3803c1f1514dSchristos 		i++;
3804c1f1514dSchristos 	}
3805c1f1514dSchristos 
380602ec05fbSchristos 	return res;
380702ec05fbSchristos }
380802ec05fbSchristos 
380902ec05fbSchristos 
wpa_cli_cmd_completion(const char * cmd,const char * str,int pos)381002ec05fbSchristos static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
381102ec05fbSchristos 				      int pos)
381202ec05fbSchristos {
381302ec05fbSchristos 	int i;
381402ec05fbSchristos 
381502ec05fbSchristos 	for (i = 0; wpa_cli_commands[i].cmd; i++) {
381602ec05fbSchristos 		if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3817da2e293dSchristos 			if (wpa_cli_commands[i].completion)
3818da2e293dSchristos 				return wpa_cli_commands[i].completion(str,
3819da2e293dSchristos 								      pos);
382002ec05fbSchristos 			edit_clear_line();
382102ec05fbSchristos 			printf("\r%s\n", wpa_cli_commands[i].usage);
382202ec05fbSchristos 			edit_redraw();
382302ec05fbSchristos 			break;
382402ec05fbSchristos 		}
382502ec05fbSchristos 	}
382602ec05fbSchristos 
382702ec05fbSchristos 	return NULL;
382802ec05fbSchristos }
382902ec05fbSchristos 
383002ec05fbSchristos 
wpa_cli_edit_completion_cb(void * ctx,const char * str,int pos)383102ec05fbSchristos static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
383202ec05fbSchristos {
383302ec05fbSchristos 	char **res;
383402ec05fbSchristos 	const char *end;
383502ec05fbSchristos 	char *cmd;
383602ec05fbSchristos 
3837c1f1514dSchristos 	if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3838c1f1514dSchristos 		end = os_strchr(str, ' ');
3839c1f1514dSchristos 		if (end && pos > end - str) {
3840c1f1514dSchristos 			pos -= end - str + 1;
3841c1f1514dSchristos 			str = end + 1;
3842c1f1514dSchristos 		}
3843c1f1514dSchristos 	}
3844c1f1514dSchristos 
384502ec05fbSchristos 	end = os_strchr(str, ' ');
384602ec05fbSchristos 	if (end == NULL || str + pos < end)
384702ec05fbSchristos 		return wpa_list_cmd_list();
384802ec05fbSchristos 
384902ec05fbSchristos 	cmd = os_malloc(pos + 1);
385002ec05fbSchristos 	if (cmd == NULL)
385102ec05fbSchristos 		return NULL;
385202ec05fbSchristos 	os_memcpy(cmd, str, pos);
385302ec05fbSchristos 	cmd[end - str] = '\0';
385402ec05fbSchristos 	res = wpa_cli_cmd_completion(cmd, str, pos);
385502ec05fbSchristos 	os_free(cmd);
385602ec05fbSchristos 	return res;
385702ec05fbSchristos }
38588dbcf02cSchristos 
38598dbcf02cSchristos 
wpa_request(struct wpa_ctrl * ctrl,int argc,char * argv[])38608dbcf02cSchristos static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
38618dbcf02cSchristos {
38628d355d6fSchristos 	const struct wpa_cli_cmd *cmd, *match = NULL;
38638dbcf02cSchristos 	int count;
38648dbcf02cSchristos 	int ret = 0;
38658dbcf02cSchristos 
3866c1f1514dSchristos 	if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3867c1f1514dSchristos 		ifname_prefix = argv[0] + 7;
3868c1f1514dSchristos 		argv = &argv[1];
3869c1f1514dSchristos 		argc--;
3870c1f1514dSchristos 	} else
3871c1f1514dSchristos 		ifname_prefix = NULL;
3872c1f1514dSchristos 
3873c1f1514dSchristos 	if (argc == 0)
3874c1f1514dSchristos 		return -1;
3875c1f1514dSchristos 
38768dbcf02cSchristos 	count = 0;
38778dbcf02cSchristos 	cmd = wpa_cli_commands;
38788dbcf02cSchristos 	while (cmd->cmd) {
38798dbcf02cSchristos 		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
38808dbcf02cSchristos 		{
38818dbcf02cSchristos 			match = cmd;
38828dbcf02cSchristos 			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
38838dbcf02cSchristos 				/* we have an exact match */
38848dbcf02cSchristos 				count = 1;
38858dbcf02cSchristos 				break;
38868dbcf02cSchristos 			}
38878dbcf02cSchristos 			count++;
38888dbcf02cSchristos 		}
38898dbcf02cSchristos 		cmd++;
38908dbcf02cSchristos 	}
38918dbcf02cSchristos 
38928dbcf02cSchristos 	if (count > 1) {
38938dbcf02cSchristos 		printf("Ambiguous command '%s'; possible commands:", argv[0]);
38948dbcf02cSchristos 		cmd = wpa_cli_commands;
38958dbcf02cSchristos 		while (cmd->cmd) {
38968dbcf02cSchristos 			if (os_strncasecmp(cmd->cmd, argv[0],
38978dbcf02cSchristos 					   os_strlen(argv[0])) == 0) {
38988dbcf02cSchristos 				printf(" %s", cmd->cmd);
38998dbcf02cSchristos 			}
39008dbcf02cSchristos 			cmd++;
39018dbcf02cSchristos 		}
39028dbcf02cSchristos 		printf("\n");
39038dbcf02cSchristos 		ret = 1;
39048dbcf02cSchristos 	} else if (count == 0) {
39058dbcf02cSchristos 		printf("Unknown command '%s'\n", argv[0]);
39068dbcf02cSchristos 		ret = 1;
39078dbcf02cSchristos 	} else {
39088dbcf02cSchristos 		ret = match->handler(ctrl, argc - 1, &argv[1]);
39098dbcf02cSchristos 	}
39108dbcf02cSchristos 
39118dbcf02cSchristos 	return ret;
39128dbcf02cSchristos }
39138dbcf02cSchristos 
39148dbcf02cSchristos 
wpa_cli_exec(const char * program,const char * arg1,const char * arg2)39158dbcf02cSchristos static int wpa_cli_exec(const char *program, const char *arg1,
39168dbcf02cSchristos 			const char *arg2)
39178dbcf02cSchristos {
3918c1f1514dSchristos 	char *arg;
39198dbcf02cSchristos 	size_t len;
39208dbcf02cSchristos 	int res;
39218dbcf02cSchristos 
39228d355d6fSchristos 	/* If no interface is specified, set the global */
39238d355d6fSchristos 	if (!arg1)
39248d355d6fSchristos 		arg1 = "global";
39258d355d6fSchristos 
3926c1f1514dSchristos 	len = os_strlen(arg1) + os_strlen(arg2) + 2;
3927c1f1514dSchristos 	arg = os_malloc(len);
3928c1f1514dSchristos 	if (arg == NULL)
39298dbcf02cSchristos 		return -1;
3930c1f1514dSchristos 	os_snprintf(arg, len, "%s %s", arg1, arg2);
3931c1f1514dSchristos 	res = os_exec(program, arg, 1);
3932c1f1514dSchristos 	os_free(arg);
39338dbcf02cSchristos 
3934c1f1514dSchristos 	return res;
39358dbcf02cSchristos }
39368dbcf02cSchristos 
39378dbcf02cSchristos 
wpa_cli_action_process(const char * msg)39388dbcf02cSchristos static void wpa_cli_action_process(const char *msg)
39398dbcf02cSchristos {
3940c1f1514dSchristos 	const char *pos;
3941c1f1514dSchristos 	char *copy = NULL, *id, *pos2;
3942c1f1514dSchristos 	const char *ifname = ctrl_ifname;
3943c1f1514dSchristos 	char ifname_buf[100];
3944c1f1514dSchristos 
39458d355d6fSchristos 	if (eloop_terminated())
39468d355d6fSchristos 		return;
39478d355d6fSchristos 
3948c1f1514dSchristos 	pos = msg;
3949c1f1514dSchristos 	if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3950c1f1514dSchristos 		const char *end;
3951c1f1514dSchristos 		end = os_strchr(pos + 7, ' ');
3952c1f1514dSchristos 		if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3953c1f1514dSchristos 			pos += 7;
3954c1f1514dSchristos 			os_memcpy(ifname_buf, pos, end - pos);
3955c1f1514dSchristos 			ifname_buf[end - pos] = '\0';
3956c1f1514dSchristos 			ifname = ifname_buf;
3957c1f1514dSchristos 			pos = end + 1;
3958c1f1514dSchristos 		}
3959c1f1514dSchristos 	}
3960c1f1514dSchristos  	pos = skip_priority(msg);
39618dbcf02cSchristos 
39628d355d6fSchristos 	if (str_starts(pos, WPA_EVENT_CONNECTED)) {
39638dbcf02cSchristos 		int new_id = -1;
3964ccfa3bc9Schristos 		char *id, *copy;
39658dbcf02cSchristos 		os_unsetenv("WPA_ID");
39668dbcf02cSchristos 		os_unsetenv("WPA_ID_STR");
39678dbcf02cSchristos 		os_unsetenv("WPA_CTRL_DIR");
39688dbcf02cSchristos 
39698dbcf02cSchristos 		pos = os_strstr(pos, "[id=");
3970ccfa3bc9Schristos 		copy = pos ? os_strdup(pos + 4) : NULL;
39718dbcf02cSchristos 
39728dbcf02cSchristos 		if (copy) {
3973ccfa3bc9Schristos 			char *pos2 = id = copy;
39748dbcf02cSchristos 			while (*pos2 && *pos2 != ' ')
39758dbcf02cSchristos 				pos2++;
39768dbcf02cSchristos 			*pos2++ = '\0';
39778dbcf02cSchristos 			new_id = atoi(id);
39788dbcf02cSchristos 			os_setenv("WPA_ID", id, 1);
39798dbcf02cSchristos 			while (*pos2 && *pos2 != '=')
39808dbcf02cSchristos 				pos2++;
39818dbcf02cSchristos 			if (*pos2 == '=')
39828dbcf02cSchristos 				pos2++;
39838dbcf02cSchristos 			id = pos2;
39848dbcf02cSchristos 			while (*pos2 && *pos2 != ']')
39858dbcf02cSchristos 				pos2++;
39868dbcf02cSchristos 			*pos2 = '\0';
39878dbcf02cSchristos 			os_setenv("WPA_ID_STR", id, 1);
39888dbcf02cSchristos 			os_free(copy);
39898dbcf02cSchristos 		}
39908dbcf02cSchristos 
39918dbcf02cSchristos 		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
39928dbcf02cSchristos 
3993c1f1514dSchristos 		if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
39948dbcf02cSchristos 			wpa_cli_connected = 1;
39958dbcf02cSchristos 			wpa_cli_last_id = new_id;
3996c1f1514dSchristos 			wpa_cli_exec(action_file, ifname, "CONNECTED");
39978dbcf02cSchristos 		}
39988d355d6fSchristos 	} else if (str_starts(pos, WPA_EVENT_DISCONNECTED)) {
39998dbcf02cSchristos 		if (wpa_cli_connected) {
40008dbcf02cSchristos 			wpa_cli_connected = 0;
4001c1f1514dSchristos 			wpa_cli_exec(action_file, ifname, "DISCONNECTED");
40028dbcf02cSchristos 		}
4003*0dddab58Schristos 	} else if (str_starts(pos, WPA_EVENT_CHANNEL_SWITCH_STARTED)) {
4004*0dddab58Schristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40058d355d6fSchristos 	} else if (str_starts(pos, AP_EVENT_ENABLED)) {
40069a539354Schristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40078d355d6fSchristos 	} else if (str_starts(pos, AP_EVENT_DISABLED)) {
40089a539354Schristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40098d355d6fSchristos 	} else if (str_starts(pos, MESH_GROUP_STARTED)) {
40109a539354Schristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40118d355d6fSchristos 	} else if (str_starts(pos, MESH_GROUP_REMOVED)) {
40129a539354Schristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40138d355d6fSchristos 	} else if (str_starts(pos, MESH_PEER_CONNECTED)) {
40148d355d6fSchristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40158d355d6fSchristos 	} else if (str_starts(pos, MESH_PEER_DISCONNECTED)) {
40168d355d6fSchristos 		wpa_cli_exec(action_file, ctrl_ifname, pos);
40178d355d6fSchristos 	} else if (str_starts(pos, P2P_EVENT_GROUP_STARTED)) {
4018c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40198d355d6fSchristos 	} else if (str_starts(pos, P2P_EVENT_GROUP_REMOVED)) {
4020c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40218d355d6fSchristos 	} else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
4022c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40238d355d6fSchristos 	} else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
4024c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40258d355d6fSchristos 	} else if (str_starts(pos, P2P_EVENT_GO_NEG_FAILURE)) {
4026c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40278d355d6fSchristos 	} else if (str_starts(pos, WPS_EVENT_SUCCESS)) {
4028c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
4029264891a8Schristos 	} else if (str_starts(pos, WPS_EVENT_ACTIVE)) {
4030264891a8Schristos 		wpa_cli_exec(action_file, ifname, pos);
4031264891a8Schristos 	} else if (str_starts(pos, WPS_EVENT_TIMEOUT)) {
4032264891a8Schristos 		wpa_cli_exec(action_file, ifname, pos);
40338d355d6fSchristos 	} else if (str_starts(pos, WPS_EVENT_FAIL)) {
4034c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40358d355d6fSchristos 	} else if (str_starts(pos, AP_STA_CONNECTED)) {
4036c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40378d355d6fSchristos 	} else if (str_starts(pos, AP_STA_DISCONNECTED)) {
4038c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40398d355d6fSchristos 	} else if (str_starts(pos, ESS_DISASSOC_IMMINENT)) {
4040c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40418d355d6fSchristos 	} else if (str_starts(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
4042c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
40438d355d6fSchristos 	} else if (str_starts(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
4044c1f1514dSchristos 		wpa_cli_exec(action_file, ifname, pos);
4045264891a8Schristos 	} else if (str_starts(pos, HS20_T_C_ACCEPTANCE)) {
4046264891a8Schristos 		wpa_cli_exec(action_file, ifname, pos);
4047*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_CONF_RECEIVED)) {
4048*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4049*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_CONFOBJ_AKM)) {
4050*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4051*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_CONFOBJ_SSID)) {
4052*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4053*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_CONNECTOR)) {
4054*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4055*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_CONFOBJ_PASS)) {
4056*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4057*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_CONFOBJ_PSK)) {
4058*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4059*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_C_SIGN_KEY)) {
4060*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
4061*0dddab58Schristos 	} else if (str_starts(pos, DPP_EVENT_NET_ACCESS_KEY)) {
4062*0dddab58Schristos 		wpa_cli_exec(action_file, ifname, pos);
40638d355d6fSchristos 	} else if (str_starts(pos, WPA_EVENT_TERMINATING)) {
40648dbcf02cSchristos 		printf("wpa_supplicant is terminating - stop monitoring\n");
40658dbcf02cSchristos 		wpa_cli_quit = 1;
40668dbcf02cSchristos 	}
40678dbcf02cSchristos }
40688dbcf02cSchristos 
40698dbcf02cSchristos 
40708dbcf02cSchristos #ifndef CONFIG_ANSI_C_EXTRA
wpa_cli_action_cb(char * msg,size_t len)40718dbcf02cSchristos static void wpa_cli_action_cb(char *msg, size_t len)
40728dbcf02cSchristos {
40738dbcf02cSchristos 	wpa_cli_action_process(msg);
40748dbcf02cSchristos }
40758dbcf02cSchristos #endif /* CONFIG_ANSI_C_EXTRA */
40768dbcf02cSchristos 
40778dbcf02cSchristos 
wpa_cli_open_global_ctrl(void)4078*0dddab58Schristos static int wpa_cli_open_global_ctrl(void)
4079*0dddab58Schristos {
4080*0dddab58Schristos #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4081*0dddab58Schristos 	ctrl_conn = wpa_ctrl_open(NULL);
4082*0dddab58Schristos #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4083*0dddab58Schristos 	ctrl_conn = wpa_ctrl_open(global);
4084*0dddab58Schristos #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4085*0dddab58Schristos 	if (!ctrl_conn) {
4086*0dddab58Schristos 		fprintf(stderr,
4087*0dddab58Schristos 			"Failed to connect to wpa_supplicant global interface: %s  error: %s\n",
4088*0dddab58Schristos 			global, strerror(errno));
4089*0dddab58Schristos 		return -1;
4090*0dddab58Schristos 	}
4091*0dddab58Schristos 
4092*0dddab58Schristos 	if (interactive) {
4093*0dddab58Schristos 		update_ifnames(ctrl_conn);
4094*0dddab58Schristos 		mon_conn = wpa_ctrl_open(global);
4095*0dddab58Schristos 		if (mon_conn) {
4096*0dddab58Schristos 			if (wpa_ctrl_attach(mon_conn) == 0) {
4097*0dddab58Schristos 				wpa_cli_attached = 1;
4098*0dddab58Schristos 				eloop_register_read_sock(
4099*0dddab58Schristos 					wpa_ctrl_get_fd(mon_conn),
4100*0dddab58Schristos 					wpa_cli_mon_receive,
4101*0dddab58Schristos 					NULL, NULL);
4102*0dddab58Schristos 			} else {
4103*0dddab58Schristos 				printf("Failed to open monitor connection through global control interface\n");
4104*0dddab58Schristos 			}
4105*0dddab58Schristos 		}
4106*0dddab58Schristos 		update_stations(ctrl_conn);
4107*0dddab58Schristos 	}
4108*0dddab58Schristos 
4109*0dddab58Schristos 	return 0;
4110*0dddab58Schristos }
4111*0dddab58Schristos 
4112*0dddab58Schristos 
wpa_cli_reconnect(void)41138dbcf02cSchristos static void wpa_cli_reconnect(void)
41148dbcf02cSchristos {
41158dbcf02cSchristos 	wpa_cli_close_connection();
4116*0dddab58Schristos 	if ((global && wpa_cli_open_global_ctrl() < 0) ||
4117*0dddab58Schristos 	    (!global && wpa_cli_open_connection(ctrl_ifname, 1) < 0))
4118da2e293dSchristos 		return;
4119da2e293dSchristos 
4120da2e293dSchristos 	if (interactive) {
4121da2e293dSchristos 		edit_clear_line();
4122da2e293dSchristos 		printf("\rConnection to wpa_supplicant re-established\n");
4123da2e293dSchristos 		edit_redraw();
4124264891a8Schristos 		update_stations(ctrl_conn);
4125da2e293dSchristos 	}
41268dbcf02cSchristos }
41278dbcf02cSchristos 
41288dbcf02cSchristos 
cli_event(const char * str)412902ec05fbSchristos static void cli_event(const char *str)
41308dbcf02cSchristos {
413102ec05fbSchristos 	const char *start, *s;
413202ec05fbSchristos 
413302ec05fbSchristos 	start = os_strchr(str, '>');
413402ec05fbSchristos 	if (start == NULL)
413502ec05fbSchristos 		return;
413602ec05fbSchristos 
413702ec05fbSchristos 	start++;
413802ec05fbSchristos 
413902ec05fbSchristos 	if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
414002ec05fbSchristos 		s = os_strchr(start, ' ');
414102ec05fbSchristos 		if (s == NULL)
414202ec05fbSchristos 			return;
414302ec05fbSchristos 		s = os_strchr(s + 1, ' ');
414402ec05fbSchristos 		if (s == NULL)
414502ec05fbSchristos 			return;
414602ec05fbSchristos 		cli_txt_list_add(&bsses, s + 1);
414702ec05fbSchristos 		return;
414802ec05fbSchristos 	}
414902ec05fbSchristos 
415002ec05fbSchristos 	if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
415102ec05fbSchristos 		s = os_strchr(start, ' ');
415202ec05fbSchristos 		if (s == NULL)
415302ec05fbSchristos 			return;
415402ec05fbSchristos 		s = os_strchr(s + 1, ' ');
415502ec05fbSchristos 		if (s == NULL)
415602ec05fbSchristos 			return;
415702ec05fbSchristos 		cli_txt_list_del_addr(&bsses, s + 1);
415802ec05fbSchristos 		return;
415902ec05fbSchristos 	}
416002ec05fbSchristos 
416102ec05fbSchristos #ifdef CONFIG_P2P
416202ec05fbSchristos 	if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
416302ec05fbSchristos 		s = os_strstr(start, " p2p_dev_addr=");
416402ec05fbSchristos 		if (s == NULL)
416502ec05fbSchristos 			return;
416602ec05fbSchristos 		cli_txt_list_add_addr(&p2p_peers, s + 14);
416702ec05fbSchristos 		return;
416802ec05fbSchristos 	}
416902ec05fbSchristos 
417002ec05fbSchristos 	if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
417102ec05fbSchristos 		s = os_strstr(start, " p2p_dev_addr=");
417202ec05fbSchristos 		if (s == NULL)
417302ec05fbSchristos 			return;
417402ec05fbSchristos 		cli_txt_list_del_addr(&p2p_peers, s + 14);
417502ec05fbSchristos 		return;
417602ec05fbSchristos 	}
417702ec05fbSchristos 
417802ec05fbSchristos 	if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
417902ec05fbSchristos 		s = os_strchr(start, ' ');
418002ec05fbSchristos 		if (s == NULL)
418102ec05fbSchristos 			return;
41828d355d6fSchristos 		cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
418302ec05fbSchristos 		return;
418402ec05fbSchristos 	}
418502ec05fbSchristos 
418602ec05fbSchristos 	if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
418702ec05fbSchristos 		s = os_strchr(start, ' ');
418802ec05fbSchristos 		if (s == NULL)
418902ec05fbSchristos 			return;
41908d355d6fSchristos 		cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
419102ec05fbSchristos 		return;
419202ec05fbSchristos 	}
419302ec05fbSchristos #endif /* CONFIG_P2P */
419402ec05fbSchristos }
419502ec05fbSchristos 
419602ec05fbSchristos 
check_terminating(const char * msg)4197da2e293dSchristos static int check_terminating(const char *msg)
4198da2e293dSchristos {
4199da2e293dSchristos 	const char *pos = msg;
4200da2e293dSchristos 
4201da2e293dSchristos 	if (*pos == '<') {
4202da2e293dSchristos 		/* skip priority */
4203da2e293dSchristos 		pos = os_strchr(pos, '>');
4204da2e293dSchristos 		if (pos)
4205da2e293dSchristos 			pos++;
4206da2e293dSchristos 		else
4207da2e293dSchristos 			pos = msg;
4208da2e293dSchristos 	}
4209da2e293dSchristos 
42108d355d6fSchristos 	if (str_starts(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
4211da2e293dSchristos 		edit_clear_line();
4212da2e293dSchristos 		printf("\rConnection to wpa_supplicant lost - trying to "
4213da2e293dSchristos 		       "reconnect\n");
4214da2e293dSchristos 		edit_redraw();
4215da2e293dSchristos 		wpa_cli_attached = 0;
4216da2e293dSchristos 		wpa_cli_close_connection();
4217da2e293dSchristos 		return 1;
4218da2e293dSchristos 	}
4219da2e293dSchristos 
4220da2e293dSchristos 	return 0;
4221da2e293dSchristos }
4222da2e293dSchristos 
4223da2e293dSchristos 
wpa_cli_recv_pending(struct wpa_ctrl * ctrl,int action_monitor)422402ec05fbSchristos static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
422502ec05fbSchristos {
42268dbcf02cSchristos 	if (ctrl_conn == NULL) {
42278dbcf02cSchristos 		wpa_cli_reconnect();
42288dbcf02cSchristos 		return;
42298dbcf02cSchristos 	}
42308dbcf02cSchristos 	while (wpa_ctrl_pending(ctrl) > 0) {
4231c1f1514dSchristos 		char buf[4096];
42328dbcf02cSchristos 		size_t len = sizeof(buf) - 1;
42338dbcf02cSchristos 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
42348dbcf02cSchristos 			buf[len] = '\0';
42358dbcf02cSchristos 			if (action_monitor)
42368dbcf02cSchristos 				wpa_cli_action_process(buf);
42378dbcf02cSchristos 			else {
423802ec05fbSchristos 				cli_event(buf);
423902ec05fbSchristos 				if (wpa_cli_show_event(buf)) {
424002ec05fbSchristos 					edit_clear_line();
4241ccfa3bc9Schristos 					wpa_cli_msg_cb(buf, 0);
424202ec05fbSchristos 					edit_redraw();
424302ec05fbSchristos 				}
4244da2e293dSchristos 
4245da2e293dSchristos 				if (interactive && check_terminating(buf) > 0)
4246da2e293dSchristos 					return;
42478dbcf02cSchristos 			}
42488dbcf02cSchristos 		} else {
42498dbcf02cSchristos 			printf("Could not read pending message.\n");
42508dbcf02cSchristos 			break;
42518dbcf02cSchristos 		}
42528dbcf02cSchristos 	}
42538dbcf02cSchristos 
42548dbcf02cSchristos 	if (wpa_ctrl_pending(ctrl) < 0) {
42558dbcf02cSchristos 		printf("Connection to wpa_supplicant lost - trying to "
42568dbcf02cSchristos 		       "reconnect\n");
42578dbcf02cSchristos 		wpa_cli_reconnect();
42588dbcf02cSchristos 	}
42598dbcf02cSchristos }
42608dbcf02cSchristos 
426102ec05fbSchristos 
wpa_cli_ping(void * eloop_ctx,void * timeout_ctx)426202ec05fbSchristos static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
426302ec05fbSchristos {
4264c1f1514dSchristos 	if (ctrl_conn) {
4265c1f1514dSchristos 		int res;
4266c1f1514dSchristos 		char *prefix = ifname_prefix;
4267c1f1514dSchristos 
4268c1f1514dSchristos 		ifname_prefix = NULL;
4269c1f1514dSchristos 		res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
4270c1f1514dSchristos 		ifname_prefix = prefix;
4271c1f1514dSchristos 		if (res) {
427202ec05fbSchristos 			printf("Connection to wpa_supplicant lost - trying to "
427302ec05fbSchristos 			       "reconnect\n");
427402ec05fbSchristos 			wpa_cli_close_connection();
427502ec05fbSchristos 		}
4276c1f1514dSchristos 	}
427702ec05fbSchristos 	if (!ctrl_conn)
427802ec05fbSchristos 		wpa_cli_reconnect();
427902ec05fbSchristos 	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
428002ec05fbSchristos }
428102ec05fbSchristos 
428202ec05fbSchristos 
wpa_cli_mon_receive(int sock,void * eloop_ctx,void * sock_ctx)428302ec05fbSchristos static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
428402ec05fbSchristos {
428502ec05fbSchristos 	wpa_cli_recv_pending(mon_conn, 0);
428602ec05fbSchristos }
428702ec05fbSchristos 
428802ec05fbSchristos 
wpa_cli_edit_cmd_cb(void * ctx,char * cmd)428902ec05fbSchristos static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
429002ec05fbSchristos {
429102ec05fbSchristos 	char *argv[max_args];
429202ec05fbSchristos 	int argc;
429302ec05fbSchristos 	argc = tokenize_cmd(cmd, argv);
42948dbcf02cSchristos 	if (argc)
42958dbcf02cSchristos 		wpa_request(ctrl_conn, argc, argv);
42968dbcf02cSchristos }
429702ec05fbSchristos 
429802ec05fbSchristos 
wpa_cli_edit_eof_cb(void * ctx)429902ec05fbSchristos static void wpa_cli_edit_eof_cb(void *ctx)
430002ec05fbSchristos {
430102ec05fbSchristos 	eloop_terminate();
430202ec05fbSchristos }
430302ec05fbSchristos 
430402ec05fbSchristos 
4305da2e293dSchristos static int warning_displayed = 0;
4306da2e293dSchristos static char *hfile = NULL;
4307da2e293dSchristos static int edit_started = 0;
430802ec05fbSchristos 
start_edit(void)4309da2e293dSchristos static void start_edit(void)
4310da2e293dSchristos {
4311da2e293dSchristos 	char *home;
4312da2e293dSchristos 	char *ps = NULL;
4313da2e293dSchristos 
4314da2e293dSchristos #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
4315da2e293dSchristos 	ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
4316da2e293dSchristos #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
431702ec05fbSchristos 
43188d355d6fSchristos #ifdef CONFIG_WPA_CLI_HISTORY_DIR
43198d355d6fSchristos 	home = CONFIG_WPA_CLI_HISTORY_DIR;
43208d355d6fSchristos #else /* CONFIG_WPA_CLI_HISTORY_DIR */
432102ec05fbSchristos 	home = getenv("HOME");
43228d355d6fSchristos #endif /* CONFIG_WPA_CLI_HISTORY_DIR */
432302ec05fbSchristos 	if (home) {
432402ec05fbSchristos 		const char *fname = ".wpa_cli_history";
432502ec05fbSchristos 		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
432602ec05fbSchristos 		hfile = os_malloc(hfile_len);
432702ec05fbSchristos 		if (hfile)
432802ec05fbSchristos 			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
432902ec05fbSchristos 	}
433002ec05fbSchristos 
4331da2e293dSchristos 	if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
4332da2e293dSchristos 		      wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4333da2e293dSchristos 		eloop_terminate();
4334da2e293dSchristos 		return;
4335da2e293dSchristos 	}
433602ec05fbSchristos 
4337da2e293dSchristos 	edit_started = 1;
4338da2e293dSchristos 	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4339da2e293dSchristos }
4340da2e293dSchristos 
4341da2e293dSchristos 
update_bssid_list(struct wpa_ctrl * ctrl)4342c1f1514dSchristos static void update_bssid_list(struct wpa_ctrl *ctrl)
4343c1f1514dSchristos {
4344c1f1514dSchristos 	char buf[4096];
4345c1f1514dSchristos 	size_t len = sizeof(buf);
4346c1f1514dSchristos 	int ret;
4347264891a8Schristos 	const char *cmd = "BSS RANGE=ALL MASK=0x2";
4348c1f1514dSchristos 	char *pos, *end;
4349c1f1514dSchristos 
4350c1f1514dSchristos 	if (ctrl == NULL)
4351c1f1514dSchristos 		return;
4352c1f1514dSchristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4353c1f1514dSchristos 	if (ret < 0)
4354c1f1514dSchristos 		return;
4355c1f1514dSchristos 	buf[len] = '\0';
4356c1f1514dSchristos 
4357c1f1514dSchristos 	pos = buf;
4358c1f1514dSchristos 	while (pos) {
4359c1f1514dSchristos 		pos = os_strstr(pos, "bssid=");
4360c1f1514dSchristos 		if (pos == NULL)
4361c1f1514dSchristos 			break;
4362c1f1514dSchristos 		pos += 6;
4363c1f1514dSchristos 		end = os_strchr(pos, '\n');
4364c1f1514dSchristos 		if (end == NULL)
4365c1f1514dSchristos 			break;
4366c1f1514dSchristos 		*end = '\0';
4367c1f1514dSchristos 		cli_txt_list_add(&bsses, pos);
4368c1f1514dSchristos 		pos = end + 1;
4369c1f1514dSchristos 	}
4370c1f1514dSchristos }
4371c1f1514dSchristos 
4372c1f1514dSchristos 
update_ifnames(struct wpa_ctrl * ctrl)4373c1f1514dSchristos static void update_ifnames(struct wpa_ctrl *ctrl)
4374c1f1514dSchristos {
4375c1f1514dSchristos 	char buf[4096];
4376c1f1514dSchristos 	size_t len = sizeof(buf);
4377c1f1514dSchristos 	int ret;
4378264891a8Schristos 	const char *cmd = "INTERFACES";
4379c1f1514dSchristos 	char *pos, *end;
4380c1f1514dSchristos 	char txt[200];
4381c1f1514dSchristos 
4382c1f1514dSchristos 	cli_txt_list_flush(&ifnames);
4383c1f1514dSchristos 
4384c1f1514dSchristos 	if (ctrl == NULL)
4385c1f1514dSchristos 		return;
4386c1f1514dSchristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4387c1f1514dSchristos 	if (ret < 0)
4388c1f1514dSchristos 		return;
4389c1f1514dSchristos 	buf[len] = '\0';
4390c1f1514dSchristos 
4391c1f1514dSchristos 	pos = buf;
4392c1f1514dSchristos 	while (pos) {
4393c1f1514dSchristos 		end = os_strchr(pos, '\n');
4394c1f1514dSchristos 		if (end == NULL)
4395c1f1514dSchristos 			break;
4396c1f1514dSchristos 		*end = '\0';
4397c1f1514dSchristos 		ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
43989a539354Schristos 		if (!os_snprintf_error(sizeof(txt), ret))
4399c1f1514dSchristos 			cli_txt_list_add(&ifnames, txt);
4400c1f1514dSchristos 		pos = end + 1;
4401c1f1514dSchristos 	}
4402c1f1514dSchristos }
4403c1f1514dSchristos 
4404c1f1514dSchristos 
update_creds(struct wpa_ctrl * ctrl)4405264891a8Schristos static void update_creds(struct wpa_ctrl *ctrl)
4406264891a8Schristos {
4407264891a8Schristos 	char buf[4096];
4408264891a8Schristos 	size_t len = sizeof(buf);
4409264891a8Schristos 	int ret;
4410264891a8Schristos 	const char *cmd = "LIST_CREDS";
4411264891a8Schristos 	char *pos, *end;
4412264891a8Schristos 	int header = 1;
4413264891a8Schristos 
4414264891a8Schristos 	cli_txt_list_flush(&creds);
4415264891a8Schristos 
4416264891a8Schristos 	if (ctrl == NULL)
4417264891a8Schristos 		return;
4418264891a8Schristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4419264891a8Schristos 	if (ret < 0)
4420264891a8Schristos 		return;
4421264891a8Schristos 	buf[len] = '\0';
4422264891a8Schristos 
4423264891a8Schristos 	pos = buf;
4424264891a8Schristos 	while (pos) {
4425264891a8Schristos 		end = os_strchr(pos, '\n');
4426264891a8Schristos 		if (end == NULL)
4427264891a8Schristos 			break;
4428264891a8Schristos 		*end = '\0';
4429264891a8Schristos 		if (!header)
4430264891a8Schristos 			cli_txt_list_add_word(&creds, pos, '\t');
4431264891a8Schristos 		header = 0;
4432264891a8Schristos 		pos = end + 1;
4433264891a8Schristos 	}
4434264891a8Schristos }
4435264891a8Schristos 
4436264891a8Schristos 
update_networks(struct wpa_ctrl * ctrl)44378d355d6fSchristos static void update_networks(struct wpa_ctrl *ctrl)
44388d355d6fSchristos {
44398d355d6fSchristos 	char buf[4096];
44408d355d6fSchristos 	size_t len = sizeof(buf);
44418d355d6fSchristos 	int ret;
4442264891a8Schristos 	const char *cmd = "LIST_NETWORKS";
44438d355d6fSchristos 	char *pos, *end;
44448d355d6fSchristos 	int header = 1;
44458d355d6fSchristos 
44468d355d6fSchristos 	cli_txt_list_flush(&networks);
44478d355d6fSchristos 
44488d355d6fSchristos 	if (ctrl == NULL)
44498d355d6fSchristos 		return;
44508d355d6fSchristos 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
44518d355d6fSchristos 	if (ret < 0)
44528d355d6fSchristos 		return;
44538d355d6fSchristos 	buf[len] = '\0';
44548d355d6fSchristos 
44558d355d6fSchristos 	pos = buf;
44568d355d6fSchristos 	while (pos) {
44578d355d6fSchristos 		end = os_strchr(pos, '\n');
44588d355d6fSchristos 		if (end == NULL)
44598d355d6fSchristos 			break;
44608d355d6fSchristos 		*end = '\0';
44618d355d6fSchristos 		if (!header)
44628d355d6fSchristos 			cli_txt_list_add_word(&networks, pos, '\t');
44638d355d6fSchristos 		header = 0;
44648d355d6fSchristos 		pos = end + 1;
44658d355d6fSchristos 	}
44668d355d6fSchristos }
44678d355d6fSchristos 
44688d355d6fSchristos 
update_stations(struct wpa_ctrl * ctrl)4469264891a8Schristos static void update_stations(struct wpa_ctrl *ctrl)
4470264891a8Schristos {
4471264891a8Schristos #ifdef CONFIG_AP
4472264891a8Schristos 	char addr[32], cmd[64];
4473264891a8Schristos 
4474264891a8Schristos 	if (!ctrl || !interactive)
4475264891a8Schristos 		return;
4476264891a8Schristos 
4477264891a8Schristos 	cli_txt_list_flush(&stations);
4478264891a8Schristos 
4479264891a8Schristos 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0))
4480264891a8Schristos 		return;
4481264891a8Schristos 	do {
4482264891a8Schristos 		if (os_strcmp(addr, "") != 0)
4483264891a8Schristos 			cli_txt_list_add(&stations, addr);
4484264891a8Schristos 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
4485264891a8Schristos 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0);
4486264891a8Schristos #endif /* CONFIG_AP */
4487264891a8Schristos }
4488264891a8Schristos 
4489264891a8Schristos 
try_connection(void * eloop_ctx,void * timeout_ctx)4490da2e293dSchristos static void try_connection(void *eloop_ctx, void *timeout_ctx)
4491da2e293dSchristos {
4492c1f1514dSchristos 	if (ctrl_conn)
4493c1f1514dSchristos 		goto done;
4494c1f1514dSchristos 
4495da2e293dSchristos 	if (ctrl_ifname == NULL)
4496da2e293dSchristos 		ctrl_ifname = wpa_cli_get_default_ifname();
4497da2e293dSchristos 
44988d355d6fSchristos 	if (wpa_cli_open_connection(ctrl_ifname, 1)) {
4499da2e293dSchristos 		if (!warning_displayed) {
4500da2e293dSchristos 			printf("Could not connect to wpa_supplicant: "
45019a539354Schristos 			       "%s - re-trying\n",
45029a539354Schristos 			       ctrl_ifname ? ctrl_ifname : "(nil)");
4503da2e293dSchristos 			warning_displayed = 1;
4504da2e293dSchristos 		}
4505da2e293dSchristos 		eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4506da2e293dSchristos 		return;
4507da2e293dSchristos 	}
4508da2e293dSchristos 
4509c1f1514dSchristos 	update_bssid_list(ctrl_conn);
4510264891a8Schristos 	update_creds(ctrl_conn);
45118d355d6fSchristos 	update_networks(ctrl_conn);
4512264891a8Schristos 	update_stations(ctrl_conn);
4513c1f1514dSchristos 
4514da2e293dSchristos 	if (warning_displayed)
4515da2e293dSchristos 		printf("Connection established.\n");
4516da2e293dSchristos 
4517c1f1514dSchristos done:
4518da2e293dSchristos 	start_edit();
4519da2e293dSchristos }
4520da2e293dSchristos 
4521da2e293dSchristos 
wpa_cli_interactive(void)4522da2e293dSchristos static void wpa_cli_interactive(void)
4523da2e293dSchristos {
4524da2e293dSchristos 	printf("\nInteractive mode\n\n");
4525da2e293dSchristos 
4526da2e293dSchristos 	eloop_register_timeout(0, 0, try_connection, NULL, NULL);
452702ec05fbSchristos 	eloop_run();
4528da2e293dSchristos 	eloop_cancel_timeout(try_connection, NULL, NULL);
452902ec05fbSchristos 
453002ec05fbSchristos 	cli_txt_list_flush(&p2p_peers);
453102ec05fbSchristos 	cli_txt_list_flush(&p2p_groups);
453202ec05fbSchristos 	cli_txt_list_flush(&bsses);
4533c1f1514dSchristos 	cli_txt_list_flush(&ifnames);
4534264891a8Schristos 	cli_txt_list_flush(&creds);
45358d355d6fSchristos 	cli_txt_list_flush(&networks);
4536da2e293dSchristos 	if (edit_started)
453702ec05fbSchristos 		edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
45388dbcf02cSchristos 	os_free(hfile);
453902ec05fbSchristos 	eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
454002ec05fbSchristos 	wpa_cli_close_connection();
45418dbcf02cSchristos }
45428dbcf02cSchristos 
45438dbcf02cSchristos 
wpa_cli_action_ping(void * eloop_ctx,void * timeout_ctx)45448d355d6fSchristos static void wpa_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
45458d355d6fSchristos {
45468d355d6fSchristos 	struct wpa_ctrl *ctrl = eloop_ctx;
45478d355d6fSchristos 	char buf[256];
45488d355d6fSchristos 	size_t len;
45498d355d6fSchristos 
45508d355d6fSchristos 	/* verify that connection is still working */
45518d355d6fSchristos 	len = sizeof(buf) - 1;
45528d355d6fSchristos 	if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
45538d355d6fSchristos 			     wpa_cli_action_cb) < 0 ||
45548d355d6fSchristos 	    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
45558d355d6fSchristos 		printf("wpa_supplicant did not reply to PING command - exiting\n");
45568d355d6fSchristos 		eloop_terminate();
45578d355d6fSchristos 		return;
45588d355d6fSchristos 	}
45598d355d6fSchristos 	eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
45608d355d6fSchristos 			       ctrl, NULL);
45618d355d6fSchristos }
45628d355d6fSchristos 
45638d355d6fSchristos 
wpa_cli_action_receive(int sock,void * eloop_ctx,void * sock_ctx)45648d355d6fSchristos static void wpa_cli_action_receive(int sock, void *eloop_ctx, void *sock_ctx)
45658d355d6fSchristos {
45668d355d6fSchristos 	struct wpa_ctrl *ctrl = eloop_ctx;
45678d355d6fSchristos 
45688d355d6fSchristos 	wpa_cli_recv_pending(ctrl, 1);
45698d355d6fSchristos }
45708d355d6fSchristos 
45718d355d6fSchristos 
wpa_cli_action(struct wpa_ctrl * ctrl)45728dbcf02cSchristos static void wpa_cli_action(struct wpa_ctrl *ctrl)
45738dbcf02cSchristos {
45748dbcf02cSchristos #ifdef CONFIG_ANSI_C_EXTRA
45758dbcf02cSchristos 	/* TODO: ANSI C version(?) */
45768dbcf02cSchristos 	printf("Action processing not supported in ANSI C build.\n");
45778dbcf02cSchristos #else /* CONFIG_ANSI_C_EXTRA */
45788d355d6fSchristos 	int fd;
45798dbcf02cSchristos 
45808dbcf02cSchristos 	fd = wpa_ctrl_get_fd(ctrl);
45818d355d6fSchristos 	eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
45828d355d6fSchristos 			       ctrl, NULL);
45838d355d6fSchristos 	eloop_register_read_sock(fd, wpa_cli_action_receive, ctrl, NULL);
45848d355d6fSchristos 	eloop_run();
45858d355d6fSchristos 	eloop_cancel_timeout(wpa_cli_action_ping, ctrl, NULL);
45868d355d6fSchristos 	eloop_unregister_read_sock(fd);
45878dbcf02cSchristos #endif /* CONFIG_ANSI_C_EXTRA */
45888dbcf02cSchristos }
45898dbcf02cSchristos 
45908dbcf02cSchristos 
wpa_cli_cleanup(void)45918dbcf02cSchristos static void wpa_cli_cleanup(void)
45928dbcf02cSchristos {
45938dbcf02cSchristos 	wpa_cli_close_connection();
45948dbcf02cSchristos 	if (pid_file)
45958dbcf02cSchristos 		os_daemonize_terminate(pid_file);
45968dbcf02cSchristos 
45978dbcf02cSchristos 	os_program_deinit();
45988dbcf02cSchristos }
45998dbcf02cSchristos 
4600da2e293dSchristos 
wpa_cli_terminate(int sig,void * ctx)4601da2e293dSchristos static void wpa_cli_terminate(int sig, void *ctx)
46028dbcf02cSchristos {
4603da2e293dSchristos 	eloop_terminate();
46048dbcf02cSchristos }
46058dbcf02cSchristos 
46068dbcf02cSchristos 
wpa_cli_get_default_ifname(void)46078dbcf02cSchristos static char * wpa_cli_get_default_ifname(void)
46088dbcf02cSchristos {
46098dbcf02cSchristos 	char *ifname = NULL;
46108dbcf02cSchristos 
461102ec05fbSchristos #ifdef ANDROID
461202ec05fbSchristos 	char ifprop[PROPERTY_VALUE_MAX];
461302ec05fbSchristos 	if (property_get("wifi.interface", ifprop, NULL) != 0) {
461402ec05fbSchristos 		ifname = os_strdup(ifprop);
46158d355d6fSchristos 		printf("Using interface '%s'\n", ifname ? ifname : "N/A");
461602ec05fbSchristos 	}
46178d355d6fSchristos #else /* ANDROID */
46188d355d6fSchristos #ifdef CONFIG_CTRL_IFACE_UNIX
46198d355d6fSchristos 	struct dirent *dent;
46208d355d6fSchristos 	DIR *dir = opendir(ctrl_iface_dir);
46218d355d6fSchristos 	if (!dir) {
46228dbcf02cSchristos 		return NULL;
462302ec05fbSchristos 	}
46248dbcf02cSchristos 	while ((dent = readdir(dir))) {
46258dbcf02cSchristos #ifdef _DIRENT_HAVE_D_TYPE
46268dbcf02cSchristos 		/*
46278dbcf02cSchristos 		 * Skip the file if it is not a socket. Also accept
46288dbcf02cSchristos 		 * DT_UNKNOWN (0) in case the C library or underlying
46298dbcf02cSchristos 		 * file system does not support d_type.
46308dbcf02cSchristos 		 */
46318dbcf02cSchristos 		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
46328dbcf02cSchristos 			continue;
46338dbcf02cSchristos #endif /* _DIRENT_HAVE_D_TYPE */
46348dbcf02cSchristos 		if (os_strcmp(dent->d_name, ".") == 0 ||
46358dbcf02cSchristos 		    os_strcmp(dent->d_name, "..") == 0)
46368dbcf02cSchristos 			continue;
46378dbcf02cSchristos 		printf("Selected interface '%s'\n", dent->d_name);
46388dbcf02cSchristos 		ifname = os_strdup(dent->d_name);
46398dbcf02cSchristos 		break;
46408dbcf02cSchristos 	}
46418dbcf02cSchristos 	closedir(dir);
46428dbcf02cSchristos #endif /* CONFIG_CTRL_IFACE_UNIX */
46438dbcf02cSchristos 
46448dbcf02cSchristos #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4645c1f1514dSchristos 	char buf[4096], *pos;
46468dbcf02cSchristos 	size_t len;
46478dbcf02cSchristos 	struct wpa_ctrl *ctrl;
46488dbcf02cSchristos 	int ret;
46498dbcf02cSchristos 
46508dbcf02cSchristos 	ctrl = wpa_ctrl_open(NULL);
46518dbcf02cSchristos 	if (ctrl == NULL)
46528dbcf02cSchristos 		return NULL;
46538dbcf02cSchristos 
46548dbcf02cSchristos 	len = sizeof(buf) - 1;
46558dbcf02cSchristos 	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
46568dbcf02cSchristos 	if (ret >= 0) {
46578dbcf02cSchristos 		buf[len] = '\0';
46588dbcf02cSchristos 		pos = os_strchr(buf, '\n');
46598dbcf02cSchristos 		if (pos)
46608dbcf02cSchristos 			*pos = '\0';
46618dbcf02cSchristos 		ifname = os_strdup(buf);
46628dbcf02cSchristos 	}
46638dbcf02cSchristos 	wpa_ctrl_close(ctrl);
46648dbcf02cSchristos #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
46658d355d6fSchristos #endif /* ANDROID */
46668dbcf02cSchristos 
46678dbcf02cSchristos 	return ifname;
46688dbcf02cSchristos }
46698dbcf02cSchristos 
46708dbcf02cSchristos 
main(int argc,char * argv[])46718dbcf02cSchristos int main(int argc, char *argv[])
46728dbcf02cSchristos {
46738dbcf02cSchristos 	int c;
46748dbcf02cSchristos 	int daemonize = 0;
46758dbcf02cSchristos 	int ret = 0;
46768dbcf02cSchristos 
46778dbcf02cSchristos 	if (os_program_init())
46788dbcf02cSchristos 		return -1;
46798dbcf02cSchristos 
46808dbcf02cSchristos 	for (;;) {
46818d355d6fSchristos 		c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
46828dbcf02cSchristos 		if (c < 0)
46838dbcf02cSchristos 			break;
46848dbcf02cSchristos 		switch (c) {
46858dbcf02cSchristos 		case 'a':
46868dbcf02cSchristos 			action_file = optarg;
46878dbcf02cSchristos 			break;
46888dbcf02cSchristos 		case 'B':
46898dbcf02cSchristos 			daemonize = 1;
46908dbcf02cSchristos 			break;
46918dbcf02cSchristos 		case 'g':
46928dbcf02cSchristos 			global = optarg;
46938dbcf02cSchristos 			break;
46948dbcf02cSchristos 		case 'G':
46958dbcf02cSchristos 			ping_interval = atoi(optarg);
46968dbcf02cSchristos 			break;
46978dbcf02cSchristos 		case 'h':
46988dbcf02cSchristos 			usage();
46998dbcf02cSchristos 			return 0;
47008dbcf02cSchristos 		case 'v':
47018dbcf02cSchristos 			printf("%s\n", wpa_cli_version);
47028dbcf02cSchristos 			return 0;
47038dbcf02cSchristos 		case 'i':
47048dbcf02cSchristos 			os_free(ctrl_ifname);
47058dbcf02cSchristos 			ctrl_ifname = os_strdup(optarg);
47068dbcf02cSchristos 			break;
47078dbcf02cSchristos 		case 'p':
47088dbcf02cSchristos 			ctrl_iface_dir = optarg;
47098dbcf02cSchristos 			break;
47108dbcf02cSchristos 		case 'P':
47118dbcf02cSchristos 			pid_file = optarg;
47128dbcf02cSchristos 			break;
47138d355d6fSchristos 		case 's':
47148d355d6fSchristos 			client_socket_dir = optarg;
47158d355d6fSchristos 			break;
47168dbcf02cSchristos 		default:
47178dbcf02cSchristos 			usage();
47188dbcf02cSchristos 			return -1;
47198dbcf02cSchristos 		}
47208dbcf02cSchristos 	}
47218dbcf02cSchristos 
47228dbcf02cSchristos 	interactive = (argc == optind) && (action_file == NULL);
47238dbcf02cSchristos 
47248dbcf02cSchristos 	if (interactive)
47258d355d6fSchristos 		printf("%s\n\n%s\n\n", wpa_cli_version, cli_license);
47268dbcf02cSchristos 
472702ec05fbSchristos 	if (eloop_init())
472802ec05fbSchristos 		return -1;
472902ec05fbSchristos 
4730*0dddab58Schristos 	if (global && wpa_cli_open_global_ctrl() < 0)
47318dbcf02cSchristos 		return -1;
47328dbcf02cSchristos 
4733da2e293dSchristos 	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
47348dbcf02cSchristos 
47358dbcf02cSchristos 	if (ctrl_ifname == NULL)
47368dbcf02cSchristos 		ctrl_ifname = wpa_cli_get_default_ifname();
47378dbcf02cSchristos 
47388dbcf02cSchristos 	if (interactive) {
4739da2e293dSchristos 		wpa_cli_interactive();
47408dbcf02cSchristos 	} else {
47418dbcf02cSchristos 		if (!global &&
47428dbcf02cSchristos 		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4743da2e293dSchristos 			fprintf(stderr, "Failed to connect to non-global "
4744da2e293dSchristos 				"ctrl_ifname: %s  error: %s\n",
47459a539354Schristos 				ctrl_ifname ? ctrl_ifname : "(nil)",
47469a539354Schristos 				strerror(errno));
47478dbcf02cSchristos 			return -1;
47488dbcf02cSchristos 		}
47498dbcf02cSchristos 
47508dbcf02cSchristos 		if (action_file) {
47518dbcf02cSchristos 			if (wpa_ctrl_attach(ctrl_conn) == 0) {
47528dbcf02cSchristos 				wpa_cli_attached = 1;
47538dbcf02cSchristos 			} else {
47548dbcf02cSchristos 				printf("Warning: Failed to attach to "
47558dbcf02cSchristos 				       "wpa_supplicant.\n");
47568dbcf02cSchristos 				return -1;
47578dbcf02cSchristos 			}
47588dbcf02cSchristos 		}
47598dbcf02cSchristos 
47603975825dSroy 		if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
47618dbcf02cSchristos 			return -1;
47628dbcf02cSchristos 
4763da2e293dSchristos 		if (action_file)
47648dbcf02cSchristos 			wpa_cli_action(ctrl_conn);
47658dbcf02cSchristos 		else
4766da2e293dSchristos 			ret = wpa_request(ctrl_conn, argc - optind,
4767da2e293dSchristos 					  &argv[optind]);
4768da2e293dSchristos 	}
47698dbcf02cSchristos 
47708dbcf02cSchristos 	os_free(ctrl_ifname);
477102ec05fbSchristos 	eloop_destroy();
47728dbcf02cSchristos 	wpa_cli_cleanup();
47738dbcf02cSchristos 
47748dbcf02cSchristos 	return ret;
47758dbcf02cSchristos }
47768dbcf02cSchristos 
47778dbcf02cSchristos #else /* CONFIG_CTRL_IFACE */
main(int argc,char * argv[])47788dbcf02cSchristos int main(int argc, char *argv[])
47798dbcf02cSchristos {
47808dbcf02cSchristos 	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
47818dbcf02cSchristos 	return -1;
47828dbcf02cSchristos }
47838dbcf02cSchristos #endif /* CONFIG_CTRL_IFACE */
4784