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