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