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