wpa_cli.c revision 281806
1189251Ssam/*
2189251Ssam * WPA Supplicant - command line interface for wpa_supplicant daemon
3281806Srpaulo * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#include "includes.h"
10189251Ssam
11189251Ssam#ifdef CONFIG_CTRL_IFACE
12189251Ssam
13189251Ssam#ifdef CONFIG_CTRL_IFACE_UNIX
14189251Ssam#include <dirent.h>
15189251Ssam#endif /* CONFIG_CTRL_IFACE_UNIX */
16189251Ssam
17214734Srpaulo#include "common/wpa_ctrl.h"
18252726Srpaulo#include "utils/common.h"
19252726Srpaulo#include "utils/eloop.h"
20252726Srpaulo#include "utils/edit.h"
21252726Srpaulo#include "utils/list.h"
22214734Srpaulo#include "common/version.h"
23252726Srpaulo#include "common/ieee802_11_defs.h"
24252726Srpaulo#ifdef ANDROID
25252726Srpaulo#include <cutils/properties.h>
26252726Srpaulo#endif /* ANDROID */
27189251Ssam
28189251Ssam
29189251Ssamstatic const char *wpa_cli_version =
30189251Ssam"wpa_cli v" VERSION_STR "\n"
31281806Srpaulo"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
32189251Ssam
33189251Ssam
34189251Ssamstatic const char *wpa_cli_license =
35252726Srpaulo"This software may be distributed under the terms of the BSD license.\n"
36252726Srpaulo"See README for more details.\n";
37189251Ssam
38189251Ssamstatic const char *wpa_cli_full_license =
39252726Srpaulo"This software may be distributed under the terms of the BSD license.\n"
40189251Ssam"\n"
41189251Ssam"Redistribution and use in source and binary forms, with or without\n"
42189251Ssam"modification, are permitted provided that the following conditions are\n"
43189251Ssam"met:\n"
44189251Ssam"\n"
45189251Ssam"1. Redistributions of source code must retain the above copyright\n"
46189251Ssam"   notice, this list of conditions and the following disclaimer.\n"
47189251Ssam"\n"
48189251Ssam"2. Redistributions in binary form must reproduce the above copyright\n"
49189251Ssam"   notice, this list of conditions and the following disclaimer in the\n"
50189251Ssam"   documentation and/or other materials provided with the distribution.\n"
51189251Ssam"\n"
52189251Ssam"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53189251Ssam"   names of its contributors may be used to endorse or promote products\n"
54189251Ssam"   derived from this software without specific prior written permission.\n"
55189251Ssam"\n"
56189251Ssam"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57189251Ssam"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58189251Ssam"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59189251Ssam"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60189251Ssam"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61189251Ssam"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62189251Ssam"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63189251Ssam"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64189251Ssam"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65189251Ssam"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66189251Ssam"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67189251Ssam"\n";
68189251Ssam
69189251Ssamstatic struct wpa_ctrl *ctrl_conn;
70214734Srpaulostatic struct wpa_ctrl *mon_conn;
71189251Ssamstatic int wpa_cli_quit = 0;
72189251Ssamstatic int wpa_cli_attached = 0;
73281806Srpaulostatic int wpa_cli_connected = -1;
74189251Ssamstatic int wpa_cli_last_id = 0;
75252726Srpaulo#ifndef CONFIG_CTRL_IFACE_DIR
76252726Srpaulo#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77252726Srpaulo#endif /* CONFIG_CTRL_IFACE_DIR */
78252726Srpaulostatic const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79189251Ssamstatic char *ctrl_ifname = NULL;
80189251Ssamstatic const char *pid_file = NULL;
81189251Ssamstatic const char *action_file = NULL;
82189251Ssamstatic int ping_interval = 5;
83214734Srpaulostatic int interactive = 0;
84281806Srpaulostatic char *ifname_prefix = NULL;
85189251Ssam
86252726Srpaulostruct cli_txt_entry {
87252726Srpaulo	struct dl_list list;
88252726Srpaulo	char *txt;
89252726Srpaulo};
90189251Ssam
91252726Srpaulostatic DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92252726Srpaulostatic DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93252726Srpaulostatic DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
94281806Srpaulostatic DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
95189251Ssam
96189251Ssam
97252726Srpaulostatic void print_help(const char *cmd);
98252726Srpaulostatic void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
99252726Srpaulostatic void wpa_cli_close_connection(void);
100252726Srpaulostatic char * wpa_cli_get_default_ifname(void);
101252726Srpaulostatic char ** wpa_list_cmd_list(void);
102252726Srpaulo
103252726Srpaulo
104189251Ssamstatic void usage(void)
105189251Ssam{
106189251Ssam	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107189251Ssam	       "[-a<action file>] \\\n"
108189251Ssam	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  "
109189251Ssam	       "[command..]\n"
110189251Ssam	       "  -h = help (show this usage text)\n"
111189251Ssam	       "  -v = shown version information\n"
112189251Ssam	       "  -a = run in daemon mode executing the action file based on "
113189251Ssam	       "events from\n"
114189251Ssam	       "       wpa_supplicant\n"
115189251Ssam	       "  -B = run a daemon in the background\n"
116252726Srpaulo	       "  default path: " CONFIG_CTRL_IFACE_DIR "\n"
117189251Ssam	       "  default interface: first interface found in socket path\n");
118252726Srpaulo	print_help(NULL);
119189251Ssam}
120189251Ssam
121189251Ssam
122252726Srpaulostatic void cli_txt_list_free(struct cli_txt_entry *e)
123252726Srpaulo{
124252726Srpaulo	dl_list_del(&e->list);
125252726Srpaulo	os_free(e->txt);
126252726Srpaulo	os_free(e);
127252726Srpaulo}
128214734Srpaulo
129252726Srpaulo
130252726Srpaulostatic void cli_txt_list_flush(struct dl_list *list)
131189251Ssam{
132252726Srpaulo	struct cli_txt_entry *e;
133252726Srpaulo	while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134252726Srpaulo		cli_txt_list_free(e);
135214734Srpaulo}
136214734Srpaulo
137252726Srpaulo
138252726Srpaulostatic struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139252726Srpaulo					       const char *txt)
140214734Srpaulo{
141252726Srpaulo	struct cli_txt_entry *e;
142252726Srpaulo	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143252726Srpaulo		if (os_strcmp(e->txt, txt) == 0)
144252726Srpaulo			return e;
145252726Srpaulo	}
146252726Srpaulo	return NULL;
147252726Srpaulo}
148214734Srpaulo
149214734Srpaulo
150252726Srpaulostatic void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151252726Srpaulo{
152252726Srpaulo	struct cli_txt_entry *e;
153252726Srpaulo	e = cli_txt_list_get(txt_list, txt);
154252726Srpaulo	if (e)
155252726Srpaulo		cli_txt_list_free(e);
156252726Srpaulo}
157252726Srpaulo
158252726Srpaulo
159252726Srpaulostatic void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160252726Srpaulo{
161252726Srpaulo	u8 addr[ETH_ALEN];
162252726Srpaulo	char buf[18];
163252726Srpaulo	if (hwaddr_aton(txt, addr) < 0)
164252726Srpaulo		return;
165252726Srpaulo	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166252726Srpaulo	cli_txt_list_del(txt_list, buf);
167252726Srpaulo}
168252726Srpaulo
169252726Srpaulo
170252726Srpaulo#ifdef CONFIG_P2P
171252726Srpaulostatic void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172252726Srpaulo{
173252726Srpaulo	const char *end;
174252726Srpaulo	char *buf;
175252726Srpaulo	end = os_strchr(txt, ' ');
176252726Srpaulo	if (end == NULL)
177252726Srpaulo		end = txt + os_strlen(txt);
178281806Srpaulo	buf = dup_binstr(txt, end - txt);
179252726Srpaulo	if (buf == NULL)
180252726Srpaulo		return;
181252726Srpaulo	cli_txt_list_del(txt_list, buf);
182252726Srpaulo	os_free(buf);
183252726Srpaulo}
184252726Srpaulo#endif /* CONFIG_P2P */
185252726Srpaulo
186252726Srpaulo
187252726Srpaulostatic int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188252726Srpaulo{
189252726Srpaulo	struct cli_txt_entry *e;
190252726Srpaulo	e = cli_txt_list_get(txt_list, txt);
191252726Srpaulo	if (e)
192252726Srpaulo		return 0;
193252726Srpaulo	e = os_zalloc(sizeof(*e));
194252726Srpaulo	if (e == NULL)
195252726Srpaulo		return -1;
196252726Srpaulo	e->txt = os_strdup(txt);
197252726Srpaulo	if (e->txt == NULL) {
198252726Srpaulo		os_free(e);
199252726Srpaulo		return -1;
200252726Srpaulo	}
201252726Srpaulo	dl_list_add(txt_list, &e->list);
202252726Srpaulo	return 0;
203252726Srpaulo}
204252726Srpaulo
205252726Srpaulo
206252726Srpaulo#ifdef CONFIG_P2P
207252726Srpaulostatic int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208252726Srpaulo{
209252726Srpaulo	u8 addr[ETH_ALEN];
210252726Srpaulo	char buf[18];
211252726Srpaulo	if (hwaddr_aton(txt, addr) < 0)
212252726Srpaulo		return -1;
213252726Srpaulo	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214252726Srpaulo	return cli_txt_list_add(txt_list, buf);
215252726Srpaulo}
216252726Srpaulo
217252726Srpaulo
218252726Srpaulostatic int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219252726Srpaulo{
220252726Srpaulo	const char *end;
221252726Srpaulo	char *buf;
222252726Srpaulo	int ret;
223252726Srpaulo	end = os_strchr(txt, ' ');
224252726Srpaulo	if (end == NULL)
225252726Srpaulo		end = txt + os_strlen(txt);
226281806Srpaulo	buf = dup_binstr(txt, end - txt);
227252726Srpaulo	if (buf == NULL)
228252726Srpaulo		return -1;
229252726Srpaulo	ret = cli_txt_list_add(txt_list, buf);
230252726Srpaulo	os_free(buf);
231252726Srpaulo	return ret;
232252726Srpaulo}
233252726Srpaulo#endif /* CONFIG_P2P */
234252726Srpaulo
235252726Srpaulo
236252726Srpaulostatic char ** cli_txt_list_array(struct dl_list *txt_list)
237252726Srpaulo{
238252726Srpaulo	unsigned int i, count = dl_list_len(txt_list);
239252726Srpaulo	char **res;
240252726Srpaulo	struct cli_txt_entry *e;
241252726Srpaulo
242252726Srpaulo	res = os_calloc(count + 1, sizeof(char *));
243252726Srpaulo	if (res == NULL)
244252726Srpaulo		return NULL;
245252726Srpaulo
246252726Srpaulo	i = 0;
247252726Srpaulo	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248252726Srpaulo		res[i] = os_strdup(e->txt);
249252726Srpaulo		if (res[i] == NULL)
250214734Srpaulo			break;
251252726Srpaulo		i++;
252252726Srpaulo	}
253252726Srpaulo
254252726Srpaulo	return res;
255252726Srpaulo}
256252726Srpaulo
257252726Srpaulo
258252726Srpaulostatic int get_cmd_arg_num(const char *str, int pos)
259252726Srpaulo{
260252726Srpaulo	int arg = 0, i;
261252726Srpaulo
262252726Srpaulo	for (i = 0; i <= pos; i++) {
263252726Srpaulo		if (str[i] != ' ') {
264252726Srpaulo			arg++;
265252726Srpaulo			while (i <= pos && str[i] != ' ')
266252726Srpaulo				i++;
267214734Srpaulo		}
268214734Srpaulo	}
269252726Srpaulo
270252726Srpaulo	if (arg > 0)
271252726Srpaulo		arg--;
272252726Srpaulo	return arg;
273214734Srpaulo}
274214734Srpaulo
275214734Srpaulo
276252726Srpaulostatic int str_starts(const char *src, const char *match)
277252726Srpaulo{
278252726Srpaulo	return os_strncmp(src, match, os_strlen(match)) == 0;
279252726Srpaulo}
280252726Srpaulo
281252726Srpaulo
282252726Srpaulostatic int wpa_cli_show_event(const char *event)
283252726Srpaulo{
284252726Srpaulo	const char *start;
285252726Srpaulo
286252726Srpaulo	start = os_strchr(event, '>');
287252726Srpaulo	if (start == NULL)
288252726Srpaulo		return 1;
289252726Srpaulo
290252726Srpaulo	start++;
291252726Srpaulo	/*
292252726Srpaulo	 * Skip BSS added/removed events since they can be relatively frequent
293252726Srpaulo	 * and are likely of not much use for an interactive user.
294252726Srpaulo	 */
295252726Srpaulo	if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296252726Srpaulo	    str_starts(start, WPA_EVENT_BSS_REMOVED))
297252726Srpaulo		return 0;
298252726Srpaulo
299252726Srpaulo	return 1;
300252726Srpaulo}
301252726Srpaulo
302252726Srpaulo
303214734Srpaulostatic int wpa_cli_open_connection(const char *ifname, int attach)
304214734Srpaulo{
305189251Ssam#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306189251Ssam	ctrl_conn = wpa_ctrl_open(ifname);
307214734Srpaulo	if (ctrl_conn == NULL)
308214734Srpaulo		return -1;
309214734Srpaulo
310214734Srpaulo	if (attach && interactive)
311214734Srpaulo		mon_conn = wpa_ctrl_open(ifname);
312214734Srpaulo	else
313214734Srpaulo		mon_conn = NULL;
314189251Ssam#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315252726Srpaulo	char *cfile = NULL;
316189251Ssam	int flen, res;
317189251Ssam
318189251Ssam	if (ifname == NULL)
319214734Srpaulo		return -1;
320189251Ssam
321252726Srpaulo#ifdef ANDROID
322252726Srpaulo	if (access(ctrl_iface_dir, F_OK) < 0) {
323252726Srpaulo		cfile = os_strdup(ifname);
324252726Srpaulo		if (cfile == NULL)
325252726Srpaulo			return -1;
326189251Ssam	}
327252726Srpaulo#endif /* ANDROID */
328189251Ssam
329252726Srpaulo	if (cfile == NULL) {
330252726Srpaulo		flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331252726Srpaulo		cfile = os_malloc(flen);
332252726Srpaulo		if (cfile == NULL)
333252726Srpaulo			return -1;
334252726Srpaulo		res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335252726Srpaulo				  ifname);
336281806Srpaulo		if (os_snprintf_error(flen, res)) {
337252726Srpaulo			os_free(cfile);
338252726Srpaulo			return -1;
339252726Srpaulo		}
340252726Srpaulo	}
341252726Srpaulo
342189251Ssam	ctrl_conn = wpa_ctrl_open(cfile);
343214734Srpaulo	if (ctrl_conn == NULL) {
344214734Srpaulo		os_free(cfile);
345214734Srpaulo		return -1;
346214734Srpaulo	}
347214734Srpaulo
348214734Srpaulo	if (attach && interactive)
349214734Srpaulo		mon_conn = wpa_ctrl_open(cfile);
350214734Srpaulo	else
351214734Srpaulo		mon_conn = NULL;
352189251Ssam	os_free(cfile);
353189251Ssam#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354214734Srpaulo
355214734Srpaulo	if (mon_conn) {
356214734Srpaulo		if (wpa_ctrl_attach(mon_conn) == 0) {
357214734Srpaulo			wpa_cli_attached = 1;
358252726Srpaulo			if (interactive)
359252726Srpaulo				eloop_register_read_sock(
360252726Srpaulo					wpa_ctrl_get_fd(mon_conn),
361252726Srpaulo					wpa_cli_mon_receive, NULL, NULL);
362214734Srpaulo		} else {
363214734Srpaulo			printf("Warning: Failed to attach to "
364214734Srpaulo			       "wpa_supplicant.\n");
365252726Srpaulo			wpa_cli_close_connection();
366214734Srpaulo			return -1;
367214734Srpaulo		}
368214734Srpaulo	}
369214734Srpaulo
370214734Srpaulo	return 0;
371189251Ssam}
372189251Ssam
373189251Ssam
374189251Ssamstatic void wpa_cli_close_connection(void)
375189251Ssam{
376189251Ssam	if (ctrl_conn == NULL)
377189251Ssam		return;
378189251Ssam
379189251Ssam	if (wpa_cli_attached) {
380214734Srpaulo		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381189251Ssam		wpa_cli_attached = 0;
382189251Ssam	}
383189251Ssam	wpa_ctrl_close(ctrl_conn);
384189251Ssam	ctrl_conn = NULL;
385214734Srpaulo	if (mon_conn) {
386252726Srpaulo		eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387214734Srpaulo		wpa_ctrl_close(mon_conn);
388214734Srpaulo		mon_conn = NULL;
389214734Srpaulo	}
390189251Ssam}
391189251Ssam
392189251Ssam
393189251Ssamstatic void wpa_cli_msg_cb(char *msg, size_t len)
394189251Ssam{
395189251Ssam	printf("%s\n", msg);
396189251Ssam}
397189251Ssam
398189251Ssam
399189251Ssamstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400189251Ssam{
401281806Srpaulo	char buf[4096];
402189251Ssam	size_t len;
403189251Ssam	int ret;
404189251Ssam
405189251Ssam	if (ctrl_conn == NULL) {
406189251Ssam		printf("Not connected to wpa_supplicant - command dropped.\n");
407189251Ssam		return -1;
408189251Ssam	}
409281806Srpaulo	if (ifname_prefix) {
410281806Srpaulo		os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411281806Srpaulo			    ifname_prefix, cmd);
412281806Srpaulo		buf[sizeof(buf) - 1] = '\0';
413281806Srpaulo		cmd = buf;
414281806Srpaulo	}
415189251Ssam	len = sizeof(buf) - 1;
416189251Ssam	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417189251Ssam			       wpa_cli_msg_cb);
418189251Ssam	if (ret == -2) {
419189251Ssam		printf("'%s' command timed out.\n", cmd);
420189251Ssam		return -2;
421189251Ssam	} else if (ret < 0) {
422189251Ssam		printf("'%s' command failed.\n", cmd);
423189251Ssam		return -1;
424189251Ssam	}
425189251Ssam	if (print) {
426189251Ssam		buf[len] = '\0';
427189251Ssam		printf("%s", buf);
428252726Srpaulo		if (interactive && len > 0 && buf[len - 1] != '\n')
429252726Srpaulo			printf("\n");
430189251Ssam	}
431189251Ssam	return 0;
432189251Ssam}
433189251Ssam
434189251Ssam
435189251Ssamstatic int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436189251Ssam{
437189251Ssam	return _wpa_ctrl_command(ctrl, cmd, 1);
438189251Ssam}
439189251Ssam
440189251Ssam
441252726Srpaulostatic int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442252726Srpaulo		     char *argv[])
443252726Srpaulo{
444252726Srpaulo	int i, res;
445252726Srpaulo	char *pos, *end;
446252726Srpaulo
447252726Srpaulo	pos = buf;
448252726Srpaulo	end = buf + buflen;
449252726Srpaulo
450252726Srpaulo	res = os_snprintf(pos, end - pos, "%s", cmd);
451281806Srpaulo	if (os_snprintf_error(end - pos, res))
452252726Srpaulo		goto fail;
453252726Srpaulo	pos += res;
454252726Srpaulo
455252726Srpaulo	for (i = 0; i < argc; i++) {
456252726Srpaulo		res = os_snprintf(pos, end - pos, " %s", argv[i]);
457281806Srpaulo		if (os_snprintf_error(end - pos, res))
458252726Srpaulo			goto fail;
459252726Srpaulo		pos += res;
460252726Srpaulo	}
461252726Srpaulo
462252726Srpaulo	buf[buflen - 1] = '\0';
463252726Srpaulo	return 0;
464252726Srpaulo
465252726Srpaulofail:
466252726Srpaulo	printf("Too long command\n");
467252726Srpaulo	return -1;
468252726Srpaulo}
469252726Srpaulo
470252726Srpaulo
471252726Srpaulostatic int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472252726Srpaulo		       int argc, char *argv[])
473252726Srpaulo{
474281806Srpaulo	char buf[4096];
475252726Srpaulo	if (argc < min_args) {
476252726Srpaulo		printf("Invalid %s command - at least %d argument%s "
477252726Srpaulo		       "required.\n", cmd, min_args,
478252726Srpaulo		       min_args > 1 ? "s are" : " is");
479252726Srpaulo		return -1;
480252726Srpaulo	}
481252726Srpaulo	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482252726Srpaulo		return -1;
483252726Srpaulo	return wpa_ctrl_command(ctrl, buf);
484252726Srpaulo}
485252726Srpaulo
486252726Srpaulo
487252726Srpaulostatic int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488252726Srpaulo{
489252726Srpaulo	return wpa_ctrl_command(ctrl, "IFNAME");
490252726Srpaulo}
491252726Srpaulo
492252726Srpaulo
493189251Ssamstatic int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494189251Ssam{
495252726Srpaulo	if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496252726Srpaulo		return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497252726Srpaulo	if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498252726Srpaulo		return wpa_ctrl_command(ctrl, "STATUS-WPS");
499281806Srpaulo	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500281806Srpaulo		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
501252726Srpaulo	return wpa_ctrl_command(ctrl, "STATUS");
502189251Ssam}
503189251Ssam
504189251Ssam
505189251Ssamstatic int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506189251Ssam{
507189251Ssam	return wpa_ctrl_command(ctrl, "PING");
508189251Ssam}
509189251Ssam
510189251Ssam
511252726Srpaulostatic int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512252726Srpaulo{
513252726Srpaulo	return wpa_ctrl_command(ctrl, "RELOG");
514252726Srpaulo}
515252726Srpaulo
516252726Srpaulo
517252726Srpaulostatic int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518252726Srpaulo{
519252726Srpaulo	return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
520252726Srpaulo}
521252726Srpaulo
522252726Srpaulo
523189251Ssamstatic int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524189251Ssam{
525189251Ssam	return wpa_ctrl_command(ctrl, "MIB");
526189251Ssam}
527189251Ssam
528189251Ssam
529189251Ssamstatic int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530189251Ssam{
531189251Ssam	return wpa_ctrl_command(ctrl, "PMKSA");
532189251Ssam}
533189251Ssam
534189251Ssam
535281806Srpaulostatic int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
536281806Srpaulo				   char *argv[])
537281806Srpaulo{
538281806Srpaulo	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
539281806Srpaulo}
540281806Srpaulo
541281806Srpaulo
542189251Ssamstatic int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
543189251Ssam{
544252726Srpaulo	print_help(argc > 0 ? argv[0] : NULL);
545189251Ssam	return 0;
546189251Ssam}
547189251Ssam
548189251Ssam
549252726Srpaulostatic char ** wpa_cli_complete_help(const char *str, int pos)
550252726Srpaulo{
551252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
552252726Srpaulo	char **res = NULL;
553252726Srpaulo
554252726Srpaulo	switch (arg) {
555252726Srpaulo	case 1:
556252726Srpaulo		res = wpa_list_cmd_list();
557252726Srpaulo		break;
558252726Srpaulo	}
559252726Srpaulo
560252726Srpaulo	return res;
561252726Srpaulo}
562252726Srpaulo
563252726Srpaulo
564189251Ssamstatic int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
565189251Ssam{
566189251Ssam	printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
567189251Ssam	return 0;
568189251Ssam}
569189251Ssam
570189251Ssam
571189251Ssamstatic int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
572189251Ssam{
573189251Ssam	wpa_cli_quit = 1;
574252726Srpaulo	if (interactive)
575252726Srpaulo		eloop_terminate();
576189251Ssam	return 0;
577189251Ssam}
578189251Ssam
579189251Ssam
580189251Ssamstatic int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
581189251Ssam{
582189251Ssam	char cmd[256];
583189251Ssam	int res;
584189251Ssam
585281806Srpaulo	if (argc == 1) {
586281806Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
587281806Srpaulo		if (os_snprintf_error(sizeof(cmd), res)) {
588281806Srpaulo			printf("Too long SET command.\n");
589281806Srpaulo			return -1;
590281806Srpaulo		}
591281806Srpaulo		return wpa_ctrl_command(ctrl, cmd);
592189251Ssam	}
593189251Ssam
594281806Srpaulo	return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
595281806Srpaulo}
596281806Srpaulo
597281806Srpaulo
598281806Srpaulostatic char ** wpa_cli_complete_set(const char *str, int pos)
599281806Srpaulo{
600281806Srpaulo	int arg = get_cmd_arg_num(str, pos);
601281806Srpaulo	const char *fields[] = {
602281806Srpaulo		/* runtime values */
603281806Srpaulo		"EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
604281806Srpaulo		"EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
605281806Srpaulo		"dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
606281806Srpaulo		"wps_fragment_size", "wps_version_number", "ampdu",
607281806Srpaulo		"tdls_testing", "tdls_disabled", "pno", "radio_disabled",
608281806Srpaulo		"uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
609281806Srpaulo		"no_keep_alive",
610281806Srpaulo		/* global configuration parameters */
611281806Srpaulo		"eapol_version", "ap_scan", "disable_scan_offload",
612281806Srpaulo		"fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
613281806Srpaulo		"pkcs11_module_path", "openssl_ciphers",
614281806Srpaulo		"pcsc_reader", "pcsc_pin",
615281806Srpaulo		"driver_param", "dot11RSNAConfigPMKLifetime",
616281806Srpaulo		"dot11RSNAConfigPMKReauthThreshold",
617281806Srpaulo		"dot11RSNAConfigSATimeout",
618281806Srpaulo		"update_config", "load_dynamic_eap", "uuid", "device_name",
619281806Srpaulo		"manufacturer", "model_name", "model_number", "serial_number",
620281806Srpaulo		"device_type", "os_version", "config_methods",
621281806Srpaulo		"wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
622281806Srpaulo		"p2p_listen_reg_class", "p2p_listen_channel",
623281806Srpaulo		"p2p_oper_reg_class", "p2p_oper_channel",
624281806Srpaulo		"p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
625281806Srpaulo		"p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
626281806Srpaulo		"p2p_no_go_freq",
627281806Srpaulo		"p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
628281806Srpaulo		"p2p_go_vht",
629281806Srpaulo		"p2p_ignore_shared_freq", "country", "bss_max_count",
630281806Srpaulo		"bss_expiration_age", "bss_expiration_scan_count",
631281806Srpaulo		"filter_ssids", "filter_rssi", "max_num_sta",
632281806Srpaulo		"disassoc_low_ack", "hs20", "interworking", "hessid",
633281806Srpaulo		"access_network_type", "pbc_in_m1", "autoscan",
634281806Srpaulo		"wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
635281806Srpaulo		"wps_nfc_dev_pw", "ext_password_backend",
636281806Srpaulo		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
637281806Srpaulo		"sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
638281806Srpaulo		"ignore_old_scan_res", "freq_list", "external_sim",
639281806Srpaulo		"tdls_external_control", "p2p_search_delay"
640281806Srpaulo	};
641281806Srpaulo	int i, num_fields = ARRAY_SIZE(fields);
642281806Srpaulo
643281806Srpaulo	if (arg == 1) {
644281806Srpaulo		char **res = os_calloc(num_fields + 1, sizeof(char *));
645281806Srpaulo		if (res == NULL)
646281806Srpaulo			return NULL;
647281806Srpaulo		for (i = 0; i < num_fields; i++) {
648281806Srpaulo			res[i] = os_strdup(fields[i]);
649281806Srpaulo			if (res[i] == NULL)
650281806Srpaulo				return res;
651281806Srpaulo		}
652281806Srpaulo		return res;
653189251Ssam	}
654189251Ssam
655281806Srpaulo	if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
656281806Srpaulo		return cli_txt_list_array(&bsses);
657281806Srpaulo
658281806Srpaulo	return NULL;
659189251Ssam}
660189251Ssam
661281806Srpaulostatic int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
662281806Srpaulo{
663281806Srpaulo	return wpa_ctrl_command(ctrl, "DUMP");
664281806Srpaulo}
665189251Ssam
666281806Srpaulo
667252726Srpaulostatic int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
668252726Srpaulo{
669252726Srpaulo	return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
670252726Srpaulo}
671252726Srpaulo
672252726Srpaulo
673189251Ssamstatic int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
674189251Ssam{
675189251Ssam	return wpa_ctrl_command(ctrl, "LOGOFF");
676189251Ssam}
677189251Ssam
678189251Ssam
679189251Ssamstatic int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
680189251Ssam{
681189251Ssam	return wpa_ctrl_command(ctrl, "LOGON");
682189251Ssam}
683189251Ssam
684189251Ssam
685189251Ssamstatic int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
686189251Ssam				   char *argv[])
687189251Ssam{
688189251Ssam	return wpa_ctrl_command(ctrl, "REASSOCIATE");
689189251Ssam}
690189251Ssam
691189251Ssam
692281806Srpaulostatic int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
693281806Srpaulo{
694281806Srpaulo	return wpa_ctrl_command(ctrl, "REATTACH");
695281806Srpaulo}
696281806Srpaulo
697281806Srpaulo
698189251Ssamstatic int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
699189251Ssam				       char *argv[])
700189251Ssam{
701252726Srpaulo	return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
702252726Srpaulo}
703189251Ssam
704189251Ssam
705252726Srpaulostatic int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
706252726Srpaulo{
707252726Srpaulo	return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
708189251Ssam}
709189251Ssam
710189251Ssam
711252726Srpaulostatic int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
712252726Srpaulo				     char *argv[])
713189251Ssam{
714252726Srpaulo	return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
715252726Srpaulo}
716252726Srpaulo
717252726Srpaulo
718252726Srpaulostatic int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
719252726Srpaulo				      char *argv[])
720252726Srpaulo{
721252726Srpaulo	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
722252726Srpaulo}
723252726Srpaulo
724252726Srpaulo
725252726Srpaulostatic int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
726252726Srpaulo				        char *argv[])
727252726Srpaulo{
728252726Srpaulo	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
729252726Srpaulo}
730252726Srpaulo
731252726Srpaulo
732252726Srpaulostatic int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
733252726Srpaulo{
734189251Ssam	char cmd[256];
735189251Ssam	int res;
736189251Ssam
737252726Srpaulo	if (argc < 1)
738252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
739252726Srpaulo	else
740252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
741281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res)) {
742252726Srpaulo		printf("Too long BSS_FLUSH command.\n");
743189251Ssam		return -1;
744189251Ssam	}
745189251Ssam	return wpa_ctrl_command(ctrl, cmd);
746189251Ssam}
747189251Ssam
748189251Ssam
749189251Ssamstatic int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
750189251Ssam				char *argv[])
751189251Ssam{
752252726Srpaulo	return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
753252726Srpaulo}
754189251Ssam
755252726Srpaulo
756252726Srpaulostatic int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
757252726Srpaulo{
758252726Srpaulo	return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
759252726Srpaulo}
760252726Srpaulo
761252726Srpaulo
762252726Srpaulostatic int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
763252726Srpaulo{
764252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
765252726Srpaulo}
766252726Srpaulo
767252726Srpaulo
768252726Srpaulostatic int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
769252726Srpaulo{
770252726Srpaulo	if (argc == 0) {
771252726Srpaulo		printf("Invalid WPS_PIN command: need one or two arguments:\n"
772252726Srpaulo		       "- BSSID: use 'any' to select any\n"
773252726Srpaulo		       "- PIN: optional, used only with devices that have no "
774252726Srpaulo		       "display\n");
775189251Ssam		return -1;
776189251Ssam	}
777189251Ssam
778252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
779189251Ssam}
780189251Ssam
781189251Ssam
782252726Srpaulostatic int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
783252726Srpaulo				     char *argv[])
784189251Ssam{
785252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
786252726Srpaulo}
787189251Ssam
788252726Srpaulo
789252726Srpaulostatic int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
790252726Srpaulo				  char *argv[])
791252726Srpaulo{
792252726Srpaulo	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
793252726Srpaulo}
794252726Srpaulo
795252726Srpaulo
796252726Srpaulo#ifdef CONFIG_WPS_NFC
797252726Srpaulo
798252726Srpaulostatic int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
799252726Srpaulo{
800252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
801252726Srpaulo}
802252726Srpaulo
803252726Srpaulo
804281806Srpaulostatic int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
805281806Srpaulo					    char *argv[])
806281806Srpaulo{
807281806Srpaulo	return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
808281806Srpaulo}
809281806Srpaulo
810281806Srpaulo
811252726Srpaulostatic int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
812252726Srpaulo				     char *argv[])
813252726Srpaulo{
814252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
815252726Srpaulo}
816252726Srpaulo
817252726Srpaulo
818252726Srpaulostatic int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
819252726Srpaulo					char *argv[])
820252726Srpaulo{
821252726Srpaulo	int ret;
822252726Srpaulo	char *buf;
823252726Srpaulo	size_t buflen;
824252726Srpaulo
825189251Ssam	if (argc != 1) {
826252726Srpaulo		printf("Invalid 'wps_nfc_tag_read' command - one argument "
827252726Srpaulo		       "is required.\n");
828189251Ssam		return -1;
829189251Ssam	}
830189251Ssam
831252726Srpaulo	buflen = 18 + os_strlen(argv[0]);
832252726Srpaulo	buf = os_malloc(buflen);
833252726Srpaulo	if (buf == NULL)
834189251Ssam		return -1;
835252726Srpaulo	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
836252726Srpaulo
837252726Srpaulo	ret = wpa_ctrl_command(ctrl, buf);
838252726Srpaulo	os_free(buf);
839252726Srpaulo
840252726Srpaulo	return ret;
841189251Ssam}
842189251Ssam
843189251Ssam
844252726Srpaulostatic int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
845252726Srpaulo					    char *argv[])
846189251Ssam{
847252726Srpaulo	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
848252726Srpaulo}
849189251Ssam
850189251Ssam
851252726Srpaulostatic int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
852252726Srpaulo					    char *argv[])
853252726Srpaulo{
854252726Srpaulo	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
855189251Ssam}
856189251Ssam
857189251Ssam
858281806Srpaulostatic int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
859252726Srpaulo					   char *argv[])
860189251Ssam{
861281806Srpaulo	return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
862189251Ssam}
863189251Ssam
864252726Srpaulo#endif /* CONFIG_WPS_NFC */
865214734Srpaulo
866252726Srpaulo
867189251Ssamstatic int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
868189251Ssam{
869189251Ssam	char cmd[256];
870189251Ssam	int res;
871189251Ssam
872214734Srpaulo	if (argc == 2)
873214734Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
874214734Srpaulo				  argv[0], argv[1]);
875252726Srpaulo	else if (argc == 5 || argc == 6) {
876214734Srpaulo		char ssid_hex[2 * 32 + 1];
877214734Srpaulo		char key_hex[2 * 64 + 1];
878214734Srpaulo		int i;
879214734Srpaulo
880214734Srpaulo		ssid_hex[0] = '\0';
881214734Srpaulo		for (i = 0; i < 32; i++) {
882214734Srpaulo			if (argv[2][i] == '\0')
883214734Srpaulo				break;
884214734Srpaulo			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
885214734Srpaulo		}
886214734Srpaulo
887214734Srpaulo		key_hex[0] = '\0';
888252726Srpaulo		if (argc == 6) {
889252726Srpaulo			for (i = 0; i < 64; i++) {
890252726Srpaulo				if (argv[5][i] == '\0')
891252726Srpaulo					break;
892252726Srpaulo				os_snprintf(&key_hex[i * 2], 3, "%02x",
893252726Srpaulo					    argv[5][i]);
894252726Srpaulo			}
895214734Srpaulo		}
896214734Srpaulo
897214734Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
898214734Srpaulo				  "WPS_REG %s %s %s %s %s %s",
899214734Srpaulo				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
900214734Srpaulo				  key_hex);
901214734Srpaulo	} else {
902189251Ssam		printf("Invalid WPS_REG command: need two arguments:\n"
903252726Srpaulo		       "- BSSID of the target AP\n"
904189251Ssam		       "- AP PIN\n");
905214734Srpaulo		printf("Alternatively, six arguments can be used to "
906214734Srpaulo		       "reconfigure the AP:\n"
907252726Srpaulo		       "- BSSID of the target AP\n"
908214734Srpaulo		       "- AP PIN\n"
909214734Srpaulo		       "- new SSID\n"
910214734Srpaulo		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
911214734Srpaulo		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
912214734Srpaulo		       "- new key\n");
913189251Ssam		return -1;
914189251Ssam	}
915189251Ssam
916281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res)) {
917189251Ssam		printf("Too long WPS_REG command.\n");
918189251Ssam		return -1;
919189251Ssam	}
920189251Ssam	return wpa_ctrl_command(ctrl, cmd);
921189251Ssam}
922189251Ssam
923189251Ssam
924252726Srpaulostatic int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
925252726Srpaulo				  char *argv[])
926252726Srpaulo{
927252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
928252726Srpaulo}
929252726Srpaulo
930252726Srpaulo
931214734Srpaulostatic int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
932214734Srpaulo				    char *argv[])
933214734Srpaulo{
934252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
935214734Srpaulo}
936214734Srpaulo
937214734Srpaulo
938214734Srpaulostatic int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
939214734Srpaulo				   char *argv[])
940214734Srpaulo{
941214734Srpaulo	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
942214734Srpaulo
943214734Srpaulo}
944214734Srpaulo
945214734Srpaulo
946214734Srpaulostatic int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
947214734Srpaulo				  char *argv[])
948214734Srpaulo{
949252726Srpaulo	if (argc < 2) {
950252726Srpaulo		printf("Invalid WPS_ER_PIN command: need at least two "
951252726Srpaulo		       "arguments:\n"
952214734Srpaulo		       "- UUID: use 'any' to select any\n"
953252726Srpaulo		       "- PIN: Enrollee PIN\n"
954252726Srpaulo		       "optional: - Enrollee MAC address\n");
955214734Srpaulo		return -1;
956214734Srpaulo	}
957214734Srpaulo
958252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
959214734Srpaulo}
960214734Srpaulo
961214734Srpaulo
962214734Srpaulostatic int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
963214734Srpaulo				  char *argv[])
964214734Srpaulo{
965252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
966214734Srpaulo}
967214734Srpaulo
968214734Srpaulo
969214734Srpaulostatic int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
970214734Srpaulo				    char *argv[])
971214734Srpaulo{
972214734Srpaulo	if (argc != 2) {
973214734Srpaulo		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
974214734Srpaulo		       "- UUID: specify which AP to use\n"
975214734Srpaulo		       "- PIN: AP PIN\n");
976214734Srpaulo		return -1;
977214734Srpaulo	}
978214734Srpaulo
979252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
980252726Srpaulo}
981252726Srpaulo
982252726Srpaulo
983252726Srpaulostatic int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
984252726Srpaulo					 char *argv[])
985252726Srpaulo{
986252726Srpaulo	if (argc != 2) {
987252726Srpaulo		printf("Invalid WPS_ER_SET_CONFIG command: need two "
988252726Srpaulo		       "arguments:\n"
989252726Srpaulo		       "- UUID: specify which AP to use\n"
990252726Srpaulo		       "- Network configuration id\n");
991214734Srpaulo		return -1;
992214734Srpaulo	}
993252726Srpaulo
994252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
995214734Srpaulo}
996214734Srpaulo
997214734Srpaulo
998252726Srpaulostatic int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
999252726Srpaulo				     char *argv[])
1000214734Srpaulo{
1001214734Srpaulo	char cmd[256];
1002214734Srpaulo	int res;
1003214734Srpaulo
1004252726Srpaulo	if (argc == 5 || argc == 6) {
1005252726Srpaulo		char ssid_hex[2 * 32 + 1];
1006252726Srpaulo		char key_hex[2 * 64 + 1];
1007252726Srpaulo		int i;
1008252726Srpaulo
1009252726Srpaulo		ssid_hex[0] = '\0';
1010252726Srpaulo		for (i = 0; i < 32; i++) {
1011252726Srpaulo			if (argv[2][i] == '\0')
1012252726Srpaulo				break;
1013252726Srpaulo			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1014252726Srpaulo		}
1015252726Srpaulo
1016252726Srpaulo		key_hex[0] = '\0';
1017252726Srpaulo		if (argc == 6) {
1018252726Srpaulo			for (i = 0; i < 64; i++) {
1019252726Srpaulo				if (argv[5][i] == '\0')
1020252726Srpaulo					break;
1021252726Srpaulo				os_snprintf(&key_hex[i * 2], 3, "%02x",
1022252726Srpaulo					    argv[5][i]);
1023252726Srpaulo			}
1024252726Srpaulo		}
1025252726Srpaulo
1026252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
1027252726Srpaulo				  "WPS_ER_CONFIG %s %s %s %s %s %s",
1028252726Srpaulo				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
1029252726Srpaulo				  key_hex);
1030252726Srpaulo	} else {
1031252726Srpaulo		printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1032252726Srpaulo		       "- AP UUID\n"
1033252726Srpaulo		       "- AP PIN\n"
1034252726Srpaulo		       "- new SSID\n"
1035252726Srpaulo		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1036252726Srpaulo		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
1037252726Srpaulo		       "- new key\n");
1038214734Srpaulo		return -1;
1039214734Srpaulo	}
1040214734Srpaulo
1041281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res)) {
1042252726Srpaulo		printf("Too long WPS_ER_CONFIG command.\n");
1043214734Srpaulo		return -1;
1044214734Srpaulo	}
1045214734Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1046214734Srpaulo}
1047214734Srpaulo
1048214734Srpaulo
1049252726Srpaulo#ifdef CONFIG_WPS_NFC
1050252726Srpaulostatic int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1051252726Srpaulo					       char *argv[])
1052189251Ssam{
1053252726Srpaulo	if (argc != 2) {
1054252726Srpaulo		printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1055252726Srpaulo		       "arguments:\n"
1056252726Srpaulo		       "- WPS/NDEF: token format\n"
1057252726Srpaulo		       "- UUID: specify which AP to use\n");
1058189251Ssam		return -1;
1059189251Ssam	}
1060252726Srpaulo
1061252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1062189251Ssam}
1063252726Srpaulo#endif /* CONFIG_WPS_NFC */
1064189251Ssam
1065189251Ssam
1066252726Srpaulostatic int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1067252726Srpaulo{
1068252726Srpaulo	return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
1069252726Srpaulo}
1070252726Srpaulo
1071252726Srpaulo
1072252726Srpaulostatic int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1073252726Srpaulo{
1074252726Srpaulo	return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
1075252726Srpaulo}
1076252726Srpaulo
1077252726Srpaulo
1078189251Ssamstatic int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1079189251Ssam{
1080189251Ssam	char cmd[256], *pos, *end;
1081189251Ssam	int i, ret;
1082189251Ssam
1083189251Ssam	if (argc < 2) {
1084189251Ssam		printf("Invalid IDENTITY command: needs two arguments "
1085189251Ssam		       "(network id and identity)\n");
1086189251Ssam		return -1;
1087189251Ssam	}
1088189251Ssam
1089189251Ssam	end = cmd + sizeof(cmd);
1090189251Ssam	pos = cmd;
1091189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1092189251Ssam			  argv[0], argv[1]);
1093281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1094189251Ssam		printf("Too long IDENTITY command.\n");
1095189251Ssam		return -1;
1096189251Ssam	}
1097189251Ssam	pos += ret;
1098189251Ssam	for (i = 2; i < argc; i++) {
1099189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1100281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1101189251Ssam			printf("Too long IDENTITY command.\n");
1102189251Ssam			return -1;
1103189251Ssam		}
1104189251Ssam		pos += ret;
1105189251Ssam	}
1106189251Ssam
1107189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1108189251Ssam}
1109189251Ssam
1110189251Ssam
1111189251Ssamstatic int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1112189251Ssam{
1113189251Ssam	char cmd[256], *pos, *end;
1114189251Ssam	int i, ret;
1115189251Ssam
1116189251Ssam	if (argc < 2) {
1117189251Ssam		printf("Invalid PASSWORD command: needs two arguments "
1118189251Ssam		       "(network id and password)\n");
1119189251Ssam		return -1;
1120189251Ssam	}
1121189251Ssam
1122189251Ssam	end = cmd + sizeof(cmd);
1123189251Ssam	pos = cmd;
1124189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1125189251Ssam			  argv[0], argv[1]);
1126281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1127189251Ssam		printf("Too long PASSWORD command.\n");
1128189251Ssam		return -1;
1129189251Ssam	}
1130189251Ssam	pos += ret;
1131189251Ssam	for (i = 2; i < argc; i++) {
1132189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1133281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1134189251Ssam			printf("Too long PASSWORD command.\n");
1135189251Ssam			return -1;
1136189251Ssam		}
1137189251Ssam		pos += ret;
1138189251Ssam	}
1139189251Ssam
1140189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1141189251Ssam}
1142189251Ssam
1143189251Ssam
1144189251Ssamstatic int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1145189251Ssam				    char *argv[])
1146189251Ssam{
1147189251Ssam	char cmd[256], *pos, *end;
1148189251Ssam	int i, ret;
1149189251Ssam
1150189251Ssam	if (argc < 2) {
1151189251Ssam		printf("Invalid NEW_PASSWORD command: needs two arguments "
1152189251Ssam		       "(network id and password)\n");
1153189251Ssam		return -1;
1154189251Ssam	}
1155189251Ssam
1156189251Ssam	end = cmd + sizeof(cmd);
1157189251Ssam	pos = cmd;
1158189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1159189251Ssam			  argv[0], argv[1]);
1160281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1161189251Ssam		printf("Too long NEW_PASSWORD command.\n");
1162189251Ssam		return -1;
1163189251Ssam	}
1164189251Ssam	pos += ret;
1165189251Ssam	for (i = 2; i < argc; i++) {
1166189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1167281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1168189251Ssam			printf("Too long NEW_PASSWORD command.\n");
1169189251Ssam			return -1;
1170189251Ssam		}
1171189251Ssam		pos += ret;
1172189251Ssam	}
1173189251Ssam
1174189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1175189251Ssam}
1176189251Ssam
1177189251Ssam
1178189251Ssamstatic int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1179189251Ssam{
1180189251Ssam	char cmd[256], *pos, *end;
1181189251Ssam	int i, ret;
1182189251Ssam
1183189251Ssam	if (argc < 2) {
1184189251Ssam		printf("Invalid PIN command: needs two arguments "
1185189251Ssam		       "(network id and pin)\n");
1186189251Ssam		return -1;
1187189251Ssam	}
1188189251Ssam
1189189251Ssam	end = cmd + sizeof(cmd);
1190189251Ssam	pos = cmd;
1191189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1192189251Ssam			  argv[0], argv[1]);
1193281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1194189251Ssam		printf("Too long PIN command.\n");
1195189251Ssam		return -1;
1196189251Ssam	}
1197189251Ssam	pos += ret;
1198189251Ssam	for (i = 2; i < argc; i++) {
1199189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1200281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1201189251Ssam			printf("Too long PIN command.\n");
1202189251Ssam			return -1;
1203189251Ssam		}
1204189251Ssam		pos += ret;
1205189251Ssam	}
1206189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1207189251Ssam}
1208189251Ssam
1209189251Ssam
1210189251Ssamstatic int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1211189251Ssam{
1212189251Ssam	char cmd[256], *pos, *end;
1213189251Ssam	int i, ret;
1214189251Ssam
1215189251Ssam	if (argc < 2) {
1216189251Ssam		printf("Invalid OTP command: needs two arguments (network "
1217189251Ssam		       "id and password)\n");
1218189251Ssam		return -1;
1219189251Ssam	}
1220189251Ssam
1221189251Ssam	end = cmd + sizeof(cmd);
1222189251Ssam	pos = cmd;
1223189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1224189251Ssam			  argv[0], argv[1]);
1225281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1226189251Ssam		printf("Too long OTP command.\n");
1227189251Ssam		return -1;
1228189251Ssam	}
1229189251Ssam	pos += ret;
1230189251Ssam	for (i = 2; i < argc; i++) {
1231189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1232281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1233189251Ssam			printf("Too long OTP command.\n");
1234189251Ssam			return -1;
1235189251Ssam		}
1236189251Ssam		pos += ret;
1237189251Ssam	}
1238189251Ssam
1239189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1240189251Ssam}
1241189251Ssam
1242189251Ssam
1243281806Srpaulostatic int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1244281806Srpaulo{
1245281806Srpaulo	char cmd[256], *pos, *end;
1246281806Srpaulo	int i, ret;
1247281806Srpaulo
1248281806Srpaulo	if (argc < 2) {
1249281806Srpaulo		printf("Invalid SIM command: needs two arguments "
1250281806Srpaulo		       "(network id and SIM operation response)\n");
1251281806Srpaulo		return -1;
1252281806Srpaulo	}
1253281806Srpaulo
1254281806Srpaulo	end = cmd + sizeof(cmd);
1255281806Srpaulo	pos = cmd;
1256281806Srpaulo	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1257281806Srpaulo			  argv[0], argv[1]);
1258281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1259281806Srpaulo		printf("Too long SIM command.\n");
1260281806Srpaulo		return -1;
1261281806Srpaulo	}
1262281806Srpaulo	pos += ret;
1263281806Srpaulo	for (i = 2; i < argc; i++) {
1264281806Srpaulo		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1265281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1266281806Srpaulo			printf("Too long SIM command.\n");
1267281806Srpaulo			return -1;
1268281806Srpaulo		}
1269281806Srpaulo		pos += ret;
1270281806Srpaulo	}
1271281806Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1272281806Srpaulo}
1273281806Srpaulo
1274281806Srpaulo
1275189251Ssamstatic int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1276189251Ssam				  char *argv[])
1277189251Ssam{
1278189251Ssam	char cmd[256], *pos, *end;
1279189251Ssam	int i, ret;
1280189251Ssam
1281189251Ssam	if (argc < 2) {
1282189251Ssam		printf("Invalid PASSPHRASE command: needs two arguments "
1283189251Ssam		       "(network id and passphrase)\n");
1284189251Ssam		return -1;
1285189251Ssam	}
1286189251Ssam
1287189251Ssam	end = cmd + sizeof(cmd);
1288189251Ssam	pos = cmd;
1289189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1290189251Ssam			  argv[0], argv[1]);
1291281806Srpaulo	if (os_snprintf_error(end - pos, ret)) {
1292189251Ssam		printf("Too long PASSPHRASE command.\n");
1293189251Ssam		return -1;
1294189251Ssam	}
1295189251Ssam	pos += ret;
1296189251Ssam	for (i = 2; i < argc; i++) {
1297189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1298281806Srpaulo		if (os_snprintf_error(end - pos, ret)) {
1299189251Ssam			printf("Too long PASSPHRASE command.\n");
1300189251Ssam			return -1;
1301189251Ssam		}
1302189251Ssam		pos += ret;
1303189251Ssam	}
1304189251Ssam
1305189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1306189251Ssam}
1307189251Ssam
1308189251Ssam
1309189251Ssamstatic int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1310189251Ssam{
1311189251Ssam	if (argc < 2) {
1312189251Ssam		printf("Invalid BSSID command: needs two arguments (network "
1313189251Ssam		       "id and BSSID)\n");
1314189251Ssam		return -1;
1315189251Ssam	}
1316189251Ssam
1317252726Srpaulo	return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
1318252726Srpaulo}
1319189251Ssam
1320252726Srpaulo
1321252726Srpaulostatic int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1322252726Srpaulo{
1323252726Srpaulo	return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1324189251Ssam}
1325189251Ssam
1326189251Ssam
1327252726Srpaulostatic int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1328252726Srpaulo{
1329252726Srpaulo	return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
1330252726Srpaulo}
1331252726Srpaulo
1332252726Srpaulo
1333189251Ssamstatic int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1334189251Ssam				     char *argv[])
1335189251Ssam{
1336189251Ssam	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1337189251Ssam}
1338189251Ssam
1339189251Ssam
1340189251Ssamstatic int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1341189251Ssam				      char *argv[])
1342189251Ssam{
1343252726Srpaulo	return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
1344189251Ssam}
1345189251Ssam
1346189251Ssam
1347189251Ssamstatic int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1348189251Ssam				      char *argv[])
1349189251Ssam{
1350252726Srpaulo	return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
1351189251Ssam}
1352189251Ssam
1353189251Ssam
1354189251Ssamstatic int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1355189251Ssam				       char *argv[])
1356189251Ssam{
1357252726Srpaulo	return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
1358189251Ssam}
1359189251Ssam
1360189251Ssam
1361189251Ssamstatic int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1362189251Ssam				   char *argv[])
1363189251Ssam{
1364189251Ssam	return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1365189251Ssam}
1366189251Ssam
1367189251Ssam
1368189251Ssamstatic int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1369189251Ssam				      char *argv[])
1370189251Ssam{
1371252726Srpaulo	return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1372189251Ssam}
1373189251Ssam
1374189251Ssam
1375189251Ssamstatic void wpa_cli_show_network_variables(void)
1376189251Ssam{
1377189251Ssam	printf("set_network variables:\n"
1378189251Ssam	       "  ssid (network name, SSID)\n"
1379189251Ssam	       "  psk (WPA passphrase or pre-shared key)\n"
1380189251Ssam	       "  key_mgmt (key management protocol)\n"
1381189251Ssam	       "  identity (EAP identity)\n"
1382189251Ssam	       "  password (EAP password)\n"
1383189251Ssam	       "  ...\n"
1384189251Ssam	       "\n"
1385189251Ssam	       "Note: Values are entered in the same format as the "
1386189251Ssam	       "configuration file is using,\n"
1387189251Ssam	       "i.e., strings values need to be inside double quotation "
1388189251Ssam	       "marks.\n"
1389189251Ssam	       "For example: set_network 1 ssid \"network name\"\n"
1390189251Ssam	       "\n"
1391189251Ssam	       "Please see wpa_supplicant.conf documentation for full list "
1392189251Ssam	       "of\navailable variables.\n");
1393189251Ssam}
1394189251Ssam
1395189251Ssam
1396189251Ssamstatic int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1397189251Ssam				   char *argv[])
1398189251Ssam{
1399189251Ssam	if (argc == 0) {
1400189251Ssam		wpa_cli_show_network_variables();
1401189251Ssam		return 0;
1402189251Ssam	}
1403189251Ssam
1404252726Srpaulo	if (argc < 3) {
1405189251Ssam		printf("Invalid SET_NETWORK command: needs three arguments\n"
1406189251Ssam		       "(network id, variable name, and value)\n");
1407189251Ssam		return -1;
1408189251Ssam	}
1409189251Ssam
1410252726Srpaulo	return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
1411189251Ssam}
1412189251Ssam
1413189251Ssam
1414189251Ssamstatic int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1415189251Ssam				   char *argv[])
1416189251Ssam{
1417189251Ssam	if (argc == 0) {
1418189251Ssam		wpa_cli_show_network_variables();
1419189251Ssam		return 0;
1420189251Ssam	}
1421189251Ssam
1422189251Ssam	if (argc != 2) {
1423189251Ssam		printf("Invalid GET_NETWORK command: needs two arguments\n"
1424189251Ssam		       "(network id and variable name)\n");
1425189251Ssam		return -1;
1426189251Ssam	}
1427189251Ssam
1428252726Srpaulo	return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1429252726Srpaulo}
1430252726Srpaulo
1431252726Srpaulo
1432281806Srpaulostatic int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1433281806Srpaulo				   char *argv[])
1434281806Srpaulo{
1435281806Srpaulo	if (argc == 0) {
1436281806Srpaulo		wpa_cli_show_network_variables();
1437281806Srpaulo		return 0;
1438281806Srpaulo	}
1439281806Srpaulo
1440281806Srpaulo	if (argc < 3) {
1441281806Srpaulo		printf("Invalid DUP_NETWORK command: needs three arguments\n"
1442281806Srpaulo		       "(src netid, dest netid, and variable name)\n");
1443281806Srpaulo		return -1;
1444281806Srpaulo	}
1445281806Srpaulo
1446281806Srpaulo	return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1447281806Srpaulo}
1448281806Srpaulo
1449281806Srpaulo
1450252726Srpaulostatic int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1451252726Srpaulo				  char *argv[])
1452252726Srpaulo{
1453252726Srpaulo	return wpa_ctrl_command(ctrl, "LIST_CREDS");
1454252726Srpaulo}
1455252726Srpaulo
1456252726Srpaulo
1457252726Srpaulostatic int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458252726Srpaulo{
1459252726Srpaulo	return wpa_ctrl_command(ctrl, "ADD_CRED");
1460252726Srpaulo}
1461252726Srpaulo
1462252726Srpaulo
1463252726Srpaulostatic int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1464252726Srpaulo				   char *argv[])
1465252726Srpaulo{
1466252726Srpaulo	return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1467252726Srpaulo}
1468252726Srpaulo
1469252726Srpaulo
1470252726Srpaulostatic int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1471252726Srpaulo{
1472252726Srpaulo	if (argc != 3) {
1473252726Srpaulo		printf("Invalid SET_CRED command: needs three arguments\n"
1474252726Srpaulo		       "(cred id, variable name, and value)\n");
1475189251Ssam		return -1;
1476189251Ssam	}
1477252726Srpaulo
1478252726Srpaulo	return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
1479189251Ssam}
1480189251Ssam
1481189251Ssam
1482281806Srpaulostatic int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1483281806Srpaulo{
1484281806Srpaulo	if (argc != 2) {
1485281806Srpaulo		printf("Invalid GET_CRED command: needs two arguments\n"
1486281806Srpaulo		       "(cred id, variable name)\n");
1487281806Srpaulo		return -1;
1488281806Srpaulo	}
1489281806Srpaulo
1490281806Srpaulo	return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1491281806Srpaulo}
1492281806Srpaulo
1493281806Srpaulo
1494189251Ssamstatic int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1495189251Ssam				  char *argv[])
1496189251Ssam{
1497189251Ssam	return wpa_ctrl_command(ctrl, "DISCONNECT");
1498189251Ssam}
1499189251Ssam
1500189251Ssam
1501189251Ssamstatic int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1502189251Ssam				  char *argv[])
1503189251Ssam{
1504189251Ssam	return wpa_ctrl_command(ctrl, "RECONNECT");
1505189251Ssam}
1506189251Ssam
1507189251Ssam
1508189251Ssamstatic int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1509189251Ssam				   char *argv[])
1510189251Ssam{
1511189251Ssam	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1512189251Ssam}
1513189251Ssam
1514189251Ssam
1515189251Ssamstatic int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516189251Ssam{
1517281806Srpaulo	return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
1518189251Ssam}
1519189251Ssam
1520189251Ssam
1521189251Ssamstatic int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1522189251Ssam				    char *argv[])
1523189251Ssam{
1524189251Ssam	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1525189251Ssam}
1526189251Ssam
1527189251Ssam
1528189251Ssamstatic int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1529189251Ssam{
1530252726Srpaulo	return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1531252726Srpaulo}
1532189251Ssam
1533252726Srpaulo
1534252726Srpaulostatic char ** wpa_cli_complete_bss(const char *str, int pos)
1535252726Srpaulo{
1536252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1537252726Srpaulo	char **res = NULL;
1538252726Srpaulo
1539252726Srpaulo	switch (arg) {
1540252726Srpaulo	case 1:
1541252726Srpaulo		res = cli_txt_list_array(&bsses);
1542252726Srpaulo		break;
1543189251Ssam	}
1544189251Ssam
1545252726Srpaulo	return res;
1546189251Ssam}
1547189251Ssam
1548189251Ssam
1549189251Ssamstatic int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1550189251Ssam				      char *argv[])
1551189251Ssam{
1552189251Ssam	if (argc < 1 || argc > 2) {
1553189251Ssam		printf("Invalid GET_CAPABILITY command: need either one or "
1554189251Ssam		       "two arguments\n");
1555189251Ssam		return -1;
1556189251Ssam	}
1557189251Ssam
1558189251Ssam	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1559189251Ssam		printf("Invalid GET_CAPABILITY command: second argument, "
1560189251Ssam		       "if any, must be 'strict'\n");
1561189251Ssam		return -1;
1562189251Ssam	}
1563189251Ssam
1564252726Srpaulo	return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1565189251Ssam}
1566189251Ssam
1567189251Ssam
1568189251Ssamstatic int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1569189251Ssam{
1570189251Ssam	printf("Available interfaces:\n");
1571189251Ssam	return wpa_ctrl_command(ctrl, "INTERFACES");
1572189251Ssam}
1573189251Ssam
1574189251Ssam
1575189251Ssamstatic int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1576189251Ssam{
1577189251Ssam	if (argc < 1) {
1578189251Ssam		wpa_cli_list_interfaces(ctrl);
1579189251Ssam		return 0;
1580189251Ssam	}
1581189251Ssam
1582189251Ssam	wpa_cli_close_connection();
1583189251Ssam	os_free(ctrl_ifname);
1584189251Ssam	ctrl_ifname = os_strdup(argv[0]);
1585281806Srpaulo	if (!ctrl_ifname) {
1586281806Srpaulo		printf("Failed to allocate memory\n");
1587281806Srpaulo		return 0;
1588281806Srpaulo	}
1589189251Ssam
1590281806Srpaulo	if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
1591189251Ssam		printf("Connected to interface '%s.\n", ctrl_ifname);
1592189251Ssam	} else {
1593189251Ssam		printf("Could not connect to interface '%s' - re-trying\n",
1594189251Ssam		       ctrl_ifname);
1595189251Ssam	}
1596189251Ssam	return 0;
1597189251Ssam}
1598189251Ssam
1599189251Ssam
1600189251Ssamstatic int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1601189251Ssam				   char *argv[])
1602189251Ssam{
1603189251Ssam	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1604189251Ssam}
1605189251Ssam
1606189251Ssam
1607189251Ssamstatic int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1608189251Ssam				 char *argv[])
1609189251Ssam{
1610189251Ssam	return wpa_ctrl_command(ctrl, "TERMINATE");
1611189251Ssam}
1612189251Ssam
1613189251Ssam
1614189251Ssamstatic int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1615189251Ssam				     char *argv[])
1616189251Ssam{
1617189251Ssam	char cmd[256];
1618189251Ssam	int res;
1619189251Ssam
1620189251Ssam	if (argc < 1) {
1621189251Ssam		printf("Invalid INTERFACE_ADD command: needs at least one "
1622189251Ssam		       "argument (interface name)\n"
1623189251Ssam		       "All arguments: ifname confname driver ctrl_interface "
1624189251Ssam		       "driver_param bridge_name\n");
1625189251Ssam		return -1;
1626189251Ssam	}
1627189251Ssam
1628189251Ssam	/*
1629189251Ssam	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1630189251Ssam	 * <driver_param>TAB<bridge_name>
1631189251Ssam	 */
1632189251Ssam	res = os_snprintf(cmd, sizeof(cmd),
1633189251Ssam			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1634189251Ssam			  argv[0],
1635189251Ssam			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1636189251Ssam			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1637189251Ssam			  argc > 5 ? argv[5] : "");
1638281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res))
1639189251Ssam		return -1;
1640189251Ssam	cmd[sizeof(cmd) - 1] = '\0';
1641189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1642189251Ssam}
1643189251Ssam
1644189251Ssam
1645189251Ssamstatic int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1646189251Ssam					char *argv[])
1647189251Ssam{
1648252726Srpaulo	return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1649189251Ssam}
1650189251Ssam
1651189251Ssam
1652189251Ssamstatic int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1653189251Ssam				      char *argv[])
1654189251Ssam{
1655189251Ssam	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1656189251Ssam}
1657189251Ssam
1658189251Ssam
1659214734Srpaulo#ifdef CONFIG_AP
1660214734Srpaulostatic int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1661214734Srpaulo{
1662252726Srpaulo	return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1663214734Srpaulo}
1664214734Srpaulo
1665214734Srpaulo
1666214734Srpaulostatic int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1667214734Srpaulo				char *addr, size_t addr_len)
1668214734Srpaulo{
1669214734Srpaulo	char buf[4096], *pos;
1670214734Srpaulo	size_t len;
1671214734Srpaulo	int ret;
1672214734Srpaulo
1673214734Srpaulo	if (ctrl_conn == NULL) {
1674214734Srpaulo		printf("Not connected to hostapd - command dropped.\n");
1675214734Srpaulo		return -1;
1676214734Srpaulo	}
1677214734Srpaulo	len = sizeof(buf) - 1;
1678252726Srpaulo	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1679214734Srpaulo			       wpa_cli_msg_cb);
1680214734Srpaulo	if (ret == -2) {
1681214734Srpaulo		printf("'%s' command timed out.\n", cmd);
1682214734Srpaulo		return -2;
1683214734Srpaulo	} else if (ret < 0) {
1684214734Srpaulo		printf("'%s' command failed.\n", cmd);
1685214734Srpaulo		return -1;
1686214734Srpaulo	}
1687214734Srpaulo
1688214734Srpaulo	buf[len] = '\0';
1689252726Srpaulo	if (os_memcmp(buf, "FAIL", 4) == 0)
1690214734Srpaulo		return -1;
1691214734Srpaulo	printf("%s", buf);
1692214734Srpaulo
1693214734Srpaulo	pos = buf;
1694214734Srpaulo	while (*pos != '\0' && *pos != '\n')
1695214734Srpaulo		pos++;
1696214734Srpaulo	*pos = '\0';
1697214734Srpaulo	os_strlcpy(addr, buf, addr_len);
1698214734Srpaulo	return 0;
1699214734Srpaulo}
1700214734Srpaulo
1701214734Srpaulo
1702214734Srpaulostatic int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1703214734Srpaulo{
1704214734Srpaulo	char addr[32], cmd[64];
1705214734Srpaulo
1706214734Srpaulo	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1707214734Srpaulo		return 0;
1708214734Srpaulo	do {
1709214734Srpaulo		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1710214734Srpaulo	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1711214734Srpaulo
1712214734Srpaulo	return -1;
1713214734Srpaulo}
1714252726Srpaulo
1715252726Srpaulo
1716252726Srpaulostatic int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1717252726Srpaulo				      char *argv[])
1718252726Srpaulo{
1719252726Srpaulo	return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1720252726Srpaulo}
1721252726Srpaulo
1722252726Srpaulo
1723252726Srpaulostatic int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1724252726Srpaulo				    char *argv[])
1725252726Srpaulo{
1726252726Srpaulo	return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1727252726Srpaulo}
1728281806Srpaulo
1729281806Srpaulostatic int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1730281806Srpaulo				    char *argv[])
1731281806Srpaulo{
1732281806Srpaulo	return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1733281806Srpaulo}
1734281806Srpaulo
1735214734Srpaulo#endif /* CONFIG_AP */
1736214734Srpaulo
1737214734Srpaulo
1738214734Srpaulostatic int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1739214734Srpaulo{
1740214734Srpaulo	return wpa_ctrl_command(ctrl, "SUSPEND");
1741214734Srpaulo}
1742214734Srpaulo
1743214734Srpaulo
1744214734Srpaulostatic int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1745214734Srpaulo{
1746214734Srpaulo	return wpa_ctrl_command(ctrl, "RESUME");
1747214734Srpaulo}
1748214734Srpaulo
1749214734Srpaulo
1750281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS
1751214734Srpaulostatic int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1752214734Srpaulo{
1753214734Srpaulo	return wpa_ctrl_command(ctrl, "DROP_SA");
1754214734Srpaulo}
1755281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */
1756214734Srpaulo
1757214734Srpaulo
1758214734Srpaulostatic int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1759214734Srpaulo{
1760252726Srpaulo	return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
1761252726Srpaulo}
1762252726Srpaulo
1763252726Srpaulo
1764281806Srpaulo#ifdef CONFIG_MESH
1765281806Srpaulo
1766281806Srpaulostatic int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
1767281806Srpaulo					  char *argv[])
1768281806Srpaulo{
1769281806Srpaulo	return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
1770281806Srpaulo}
1771281806Srpaulo
1772281806Srpaulo
1773281806Srpaulostatic int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
1774281806Srpaulo				      char *argv[])
1775281806Srpaulo{
1776281806Srpaulo	return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
1777281806Srpaulo}
1778281806Srpaulo
1779281806Srpaulo
1780281806Srpaulostatic int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
1781281806Srpaulo					 char *argv[])
1782281806Srpaulo{
1783281806Srpaulo	return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
1784281806Srpaulo}
1785281806Srpaulo
1786281806Srpaulo#endif /* CONFIG_MESH */
1787281806Srpaulo
1788281806Srpaulo
1789252726Srpaulo#ifdef CONFIG_P2P
1790252726Srpaulo
1791252726Srpaulostatic int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1792252726Srpaulo{
1793252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1794252726Srpaulo}
1795252726Srpaulo
1796252726Srpaulo
1797252726Srpaulostatic char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1798252726Srpaulo{
1799252726Srpaulo	char **res = NULL;
1800252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1801252726Srpaulo
1802252726Srpaulo	res = os_calloc(6, sizeof(char *));
1803252726Srpaulo	if (res == NULL)
1804252726Srpaulo		return NULL;
1805252726Srpaulo	res[0] = os_strdup("type=social");
1806252726Srpaulo	if (res[0] == NULL) {
1807252726Srpaulo		os_free(res);
1808252726Srpaulo		return NULL;
1809252726Srpaulo	}
1810252726Srpaulo	res[1] = os_strdup("type=progressive");
1811252726Srpaulo	if (res[1] == NULL)
1812252726Srpaulo		return res;
1813252726Srpaulo	res[2] = os_strdup("delay=");
1814252726Srpaulo	if (res[2] == NULL)
1815252726Srpaulo		return res;
1816252726Srpaulo	res[3] = os_strdup("dev_id=");
1817252726Srpaulo	if (res[3] == NULL)
1818252726Srpaulo		return res;
1819252726Srpaulo	if (arg == 1)
1820252726Srpaulo		res[4] = os_strdup("[timeout]");
1821252726Srpaulo
1822252726Srpaulo	return res;
1823252726Srpaulo}
1824252726Srpaulo
1825252726Srpaulo
1826252726Srpaulostatic int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1827252726Srpaulo				     char *argv[])
1828252726Srpaulo{
1829252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1830252726Srpaulo}
1831252726Srpaulo
1832252726Srpaulo
1833281806Srpaulostatic int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
1834281806Srpaulo					 char *argv[])
1835281806Srpaulo{
1836281806Srpaulo	return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
1837281806Srpaulo}
1838281806Srpaulo
1839281806Srpaulo
1840281806Srpaulostatic int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
1841281806Srpaulo					      char *argv[])
1842281806Srpaulo{
1843281806Srpaulo	return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
1844281806Srpaulo}
1845281806Srpaulo
1846281806Srpaulo
1847252726Srpaulostatic int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1848252726Srpaulo				   char *argv[])
1849252726Srpaulo{
1850252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
1851252726Srpaulo}
1852252726Srpaulo
1853252726Srpaulo
1854252726Srpaulostatic char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1855252726Srpaulo{
1856252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1857252726Srpaulo	char **res = NULL;
1858252726Srpaulo
1859252726Srpaulo	switch (arg) {
1860252726Srpaulo	case 1:
1861252726Srpaulo		res = cli_txt_list_array(&p2p_peers);
1862252726Srpaulo		break;
1863252726Srpaulo	}
1864252726Srpaulo
1865252726Srpaulo	return res;
1866252726Srpaulo}
1867252726Srpaulo
1868252726Srpaulo
1869252726Srpaulostatic int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1870252726Srpaulo				  char *argv[])
1871252726Srpaulo{
1872252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
1873252726Srpaulo}
1874252726Srpaulo
1875252726Srpaulo
1876252726Srpaulostatic int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1877252726Srpaulo					char *argv[])
1878252726Srpaulo{
1879252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
1880252726Srpaulo}
1881252726Srpaulo
1882252726Srpaulo
1883252726Srpaulostatic char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1884252726Srpaulo{
1885252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1886252726Srpaulo	char **res = NULL;
1887252726Srpaulo
1888252726Srpaulo	switch (arg) {
1889252726Srpaulo	case 1:
1890252726Srpaulo		res = cli_txt_list_array(&p2p_groups);
1891252726Srpaulo		break;
1892252726Srpaulo	}
1893252726Srpaulo
1894252726Srpaulo	return res;
1895252726Srpaulo}
1896252726Srpaulo
1897252726Srpaulo
1898252726Srpaulostatic int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1899252726Srpaulo					char *argv[])
1900252726Srpaulo{
1901252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
1902252726Srpaulo}
1903252726Srpaulo
1904252726Srpaulo
1905252726Srpaulostatic int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1906252726Srpaulo				     char *argv[])
1907252726Srpaulo{
1908252726Srpaulo	if (argc != 2 && argc != 3) {
1909252726Srpaulo		printf("Invalid P2P_PROV_DISC command: needs at least "
1910252726Srpaulo		       "two arguments, address and config method\n"
1911252726Srpaulo		       "(display, keypad, or pbc) and an optional join\n");
1912252726Srpaulo		return -1;
1913252726Srpaulo	}
1914252726Srpaulo
1915252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
1916252726Srpaulo}
1917252726Srpaulo
1918252726Srpaulo
1919252726Srpaulostatic int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1920252726Srpaulo					  char *argv[])
1921252726Srpaulo{
1922252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1923252726Srpaulo}
1924252726Srpaulo
1925252726Srpaulo
1926252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1927252726Srpaulo					 char *argv[])
1928252726Srpaulo{
1929252726Srpaulo	char cmd[4096];
1930252726Srpaulo
1931281806Srpaulo	if (argc < 2) {
1932252726Srpaulo		printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1933281806Srpaulo		       "or more arguments (address and TLVs)\n");
1934252726Srpaulo		return -1;
1935252726Srpaulo	}
1936252726Srpaulo
1937252726Srpaulo	if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
1938252726Srpaulo		return -1;
1939252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1940252726Srpaulo}
1941252726Srpaulo
1942252726Srpaulo
1943252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1944252726Srpaulo						int argc, char *argv[])
1945252726Srpaulo{
1946252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
1947252726Srpaulo}
1948252726Srpaulo
1949252726Srpaulo
1950252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1951252726Srpaulo					  char *argv[])
1952252726Srpaulo{
1953252726Srpaulo	char cmd[4096];
1954214734Srpaulo	int res;
1955214734Srpaulo
1956252726Srpaulo	if (argc != 4) {
1957252726Srpaulo		printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1958252726Srpaulo		       "arguments (freq, address, dialog token, and TLVs)\n");
1959252726Srpaulo		return -1;
1960252726Srpaulo	}
1961252726Srpaulo
1962252726Srpaulo	res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1963252726Srpaulo			  argv[0], argv[1], argv[2], argv[3]);
1964281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res))
1965252726Srpaulo		return -1;
1966252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
1967252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1968252726Srpaulo}
1969252726Srpaulo
1970252726Srpaulo
1971252726Srpaulostatic int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1972252726Srpaulo					  char *argv[])
1973252726Srpaulo{
1974252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1975252726Srpaulo}
1976252726Srpaulo
1977252726Srpaulo
1978252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1979252726Srpaulo					      int argc, char *argv[])
1980252726Srpaulo{
1981252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
1982252726Srpaulo}
1983252726Srpaulo
1984252726Srpaulo
1985252726Srpaulostatic int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1986252726Srpaulo					 char *argv[])
1987252726Srpaulo{
1988252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1989252726Srpaulo}
1990252726Srpaulo
1991252726Srpaulo
1992252726Srpaulostatic int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1993252726Srpaulo				       char *argv[])
1994252726Srpaulo{
1995281806Srpaulo	if (argc < 3) {
1996281806Srpaulo		printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
1997281806Srpaulo		return -1;
1998281806Srpaulo	}
1999252726Srpaulo
2000281806Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2001281806Srpaulo}
2002281806Srpaulo
2003281806Srpaulo
2004281806Srpaulostatic int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2005281806Srpaulo				       char *argv[])
2006281806Srpaulo{
2007281806Srpaulo	if (argc < 5 || argc > 6) {
2008281806Srpaulo		printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
2009252726Srpaulo		       "arguments\n");
2010252726Srpaulo		return -1;
2011252726Srpaulo	}
2012252726Srpaulo
2013281806Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
2014252726Srpaulo}
2015252726Srpaulo
2016252726Srpaulo
2017252726Srpaulostatic int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2018252726Srpaulo				       char *argv[])
2019252726Srpaulo{
2020252726Srpaulo	char cmd[4096];
2021252726Srpaulo	int res;
2022252726Srpaulo
2023252726Srpaulo	if (argc != 2 && argc != 3) {
2024252726Srpaulo		printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2025252726Srpaulo		       "arguments\n");
2026252726Srpaulo		return -1;
2027252726Srpaulo	}
2028252726Srpaulo
2029252726Srpaulo	if (argc == 3)
2030252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
2031252726Srpaulo				  "P2P_SERVICE_DEL %s %s %s",
2032252726Srpaulo				  argv[0], argv[1], argv[2]);
2033252726Srpaulo	else
2034252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
2035252726Srpaulo				  "P2P_SERVICE_DEL %s %s",
2036252726Srpaulo				  argv[0], argv[1]);
2037281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res))
2038252726Srpaulo		return -1;
2039252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
2040252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2041252726Srpaulo}
2042252726Srpaulo
2043252726Srpaulo
2044252726Srpaulostatic int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2045252726Srpaulo				  int argc, char *argv[])
2046252726Srpaulo{
2047252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
2048252726Srpaulo}
2049252726Srpaulo
2050252726Srpaulo
2051252726Srpaulostatic int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2052252726Srpaulo				  int argc, char *argv[])
2053252726Srpaulo{
2054252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
2055252726Srpaulo}
2056252726Srpaulo
2057252726Srpaulo
2058252726Srpaulostatic int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2059252726Srpaulo{
2060252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
2061252726Srpaulo}
2062252726Srpaulo
2063252726Srpaulo
2064252726Srpaulostatic char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2065252726Srpaulo{
2066252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
2067252726Srpaulo	char **res = NULL;
2068252726Srpaulo
2069252726Srpaulo	switch (arg) {
2070252726Srpaulo	case 1:
2071252726Srpaulo		res = cli_txt_list_array(&p2p_peers);
2072252726Srpaulo		break;
2073252726Srpaulo	}
2074252726Srpaulo
2075252726Srpaulo	return res;
2076252726Srpaulo}
2077252726Srpaulo
2078252726Srpaulo
2079252726Srpaulostatic int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2080252726Srpaulo				     char *addr, size_t addr_len,
2081252726Srpaulo				     int discovered)
2082252726Srpaulo{
2083252726Srpaulo	char buf[4096], *pos;
2084252726Srpaulo	size_t len;
2085252726Srpaulo	int ret;
2086252726Srpaulo
2087252726Srpaulo	if (ctrl_conn == NULL)
2088252726Srpaulo		return -1;
2089252726Srpaulo	len = sizeof(buf) - 1;
2090252726Srpaulo	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2091252726Srpaulo			       wpa_cli_msg_cb);
2092252726Srpaulo	if (ret == -2) {
2093252726Srpaulo		printf("'%s' command timed out.\n", cmd);
2094252726Srpaulo		return -2;
2095252726Srpaulo	} else if (ret < 0) {
2096252726Srpaulo		printf("'%s' command failed.\n", cmd);
2097252726Srpaulo		return -1;
2098252726Srpaulo	}
2099252726Srpaulo
2100252726Srpaulo	buf[len] = '\0';
2101252726Srpaulo	if (os_memcmp(buf, "FAIL", 4) == 0)
2102252726Srpaulo		return -1;
2103252726Srpaulo
2104252726Srpaulo	pos = buf;
2105252726Srpaulo	while (*pos != '\0' && *pos != '\n')
2106252726Srpaulo		pos++;
2107252726Srpaulo	*pos++ = '\0';
2108252726Srpaulo	os_strlcpy(addr, buf, addr_len);
2109252726Srpaulo	if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2110252726Srpaulo		printf("%s\n", addr);
2111252726Srpaulo	return 0;
2112252726Srpaulo}
2113252726Srpaulo
2114252726Srpaulo
2115252726Srpaulostatic int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2116252726Srpaulo{
2117252726Srpaulo	char addr[32], cmd[64];
2118252726Srpaulo	int discovered;
2119252726Srpaulo
2120252726Srpaulo	discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2121252726Srpaulo
2122252726Srpaulo	if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2123252726Srpaulo				      addr, sizeof(addr), discovered))
2124252726Srpaulo		return -1;
2125252726Srpaulo	do {
2126252726Srpaulo		os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2127252726Srpaulo	} while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2128252726Srpaulo			 discovered) == 0);
2129252726Srpaulo
2130252726Srpaulo	return 0;
2131252726Srpaulo}
2132252726Srpaulo
2133252726Srpaulo
2134252726Srpaulostatic int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2135252726Srpaulo{
2136252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2137252726Srpaulo}
2138252726Srpaulo
2139252726Srpaulo
2140281806Srpaulostatic char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2141281806Srpaulo{
2142281806Srpaulo	int arg = get_cmd_arg_num(str, pos);
2143281806Srpaulo	const char *fields[] = {
2144281806Srpaulo		"discoverability",
2145281806Srpaulo		"managed",
2146281806Srpaulo		"listen_channel",
2147281806Srpaulo		"ssid_postfix",
2148281806Srpaulo		"noa",
2149281806Srpaulo		"ps",
2150281806Srpaulo		"oppps",
2151281806Srpaulo		"ctwindow",
2152281806Srpaulo		"disabled",
2153281806Srpaulo		"conc_pref",
2154281806Srpaulo		"force_long_sd",
2155281806Srpaulo		"peer_filter",
2156281806Srpaulo		"cross_connect",
2157281806Srpaulo		"go_apsd",
2158281806Srpaulo		"client_apsd",
2159281806Srpaulo		"disallow_freq",
2160281806Srpaulo		"disc_int",
2161281806Srpaulo		"per_sta_psk",
2162281806Srpaulo	};
2163281806Srpaulo	int i, num_fields = ARRAY_SIZE(fields);
2164281806Srpaulo
2165281806Srpaulo	if (arg == 1) {
2166281806Srpaulo		char **res = os_calloc(num_fields + 1, sizeof(char *));
2167281806Srpaulo		if (res == NULL)
2168281806Srpaulo			return NULL;
2169281806Srpaulo		for (i = 0; i < num_fields; i++) {
2170281806Srpaulo			res[i] = os_strdup(fields[i]);
2171281806Srpaulo			if (res[i] == NULL)
2172281806Srpaulo				return res;
2173281806Srpaulo		}
2174281806Srpaulo		return res;
2175281806Srpaulo	}
2176281806Srpaulo
2177281806Srpaulo	if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2178281806Srpaulo		return cli_txt_list_array(&p2p_peers);
2179281806Srpaulo
2180281806Srpaulo	return NULL;
2181281806Srpaulo}
2182281806Srpaulo
2183281806Srpaulo
2184252726Srpaulostatic int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2185252726Srpaulo{
2186252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2187252726Srpaulo}
2188252726Srpaulo
2189252726Srpaulo
2190252726Srpaulostatic int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2191252726Srpaulo				  char *argv[])
2192252726Srpaulo{
2193252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2194252726Srpaulo}
2195252726Srpaulo
2196252726Srpaulo
2197252726Srpaulostatic int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2198252726Srpaulo				       char *argv[])
2199252726Srpaulo{
2200252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2201252726Srpaulo}
2202252726Srpaulo
2203252726Srpaulo
2204252726Srpaulostatic int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2205252726Srpaulo					char *argv[])
2206252726Srpaulo{
2207252726Srpaulo	if (argc != 0 && argc != 2 && argc != 4) {
2208252726Srpaulo		printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2209252726Srpaulo		       "(preferred duration, interval; in microsecods).\n"
2210252726Srpaulo		       "Optional second pair can be used to provide "
2211252726Srpaulo		       "acceptable values.\n");
2212252726Srpaulo		return -1;
2213252726Srpaulo	}
2214252726Srpaulo
2215252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2216252726Srpaulo}
2217252726Srpaulo
2218252726Srpaulo
2219252726Srpaulostatic int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2220252726Srpaulo				      char *argv[])
2221252726Srpaulo{
2222252726Srpaulo	if (argc != 0 && argc != 2) {
2223252726Srpaulo		printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2224252726Srpaulo		       "(availability period, availability interval; in "
2225252726Srpaulo		       "millisecods).\n"
2226252726Srpaulo		       "Extended Listen Timing can be cancelled with this "
2227252726Srpaulo		       "command when used without parameters.\n");
2228252726Srpaulo		return -1;
2229252726Srpaulo	}
2230252726Srpaulo
2231252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2232252726Srpaulo}
2233252726Srpaulo
2234281806Srpaulo
2235281806Srpaulostatic int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2236281806Srpaulo					 char *argv[])
2237281806Srpaulo{
2238281806Srpaulo	return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2239281806Srpaulo}
2240281806Srpaulo
2241252726Srpaulo#endif /* CONFIG_P2P */
2242252726Srpaulo
2243252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY
2244252726Srpaulo
2245252726Srpaulostatic int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2246252726Srpaulo				       char *argv[])
2247252726Srpaulo{
2248252726Srpaulo	char cmd[100];
2249252726Srpaulo	int res;
2250252726Srpaulo
2251252726Srpaulo	if (argc != 1 && argc != 2) {
2252252726Srpaulo		printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2253252726Srpaulo		       "arguments (subelem, hexdump)\n");
2254252726Srpaulo		return -1;
2255252726Srpaulo	}
2256252726Srpaulo
2257252726Srpaulo	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2258252726Srpaulo			  argv[0], argc > 1 ? argv[1] : "");
2259281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res))
2260252726Srpaulo		return -1;
2261252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
2262252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2263252726Srpaulo}
2264252726Srpaulo
2265252726Srpaulo
2266252726Srpaulostatic int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2267252726Srpaulo				       char *argv[])
2268252726Srpaulo{
2269252726Srpaulo	char cmd[100];
2270252726Srpaulo	int res;
2271252726Srpaulo
2272214734Srpaulo	if (argc != 1) {
2273252726Srpaulo		printf("Invalid WFD_SUBELEM_GET command: needs one "
2274252726Srpaulo		       "argument (subelem)\n");
2275214734Srpaulo		return -1;
2276214734Srpaulo	}
2277214734Srpaulo
2278252726Srpaulo	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2279252726Srpaulo			  argv[0]);
2280281806Srpaulo	if (os_snprintf_error(sizeof(cmd), res))
2281214734Srpaulo		return -1;
2282252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
2283252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2284252726Srpaulo}
2285252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */
2286252726Srpaulo
2287252726Srpaulo
2288252726Srpaulo#ifdef CONFIG_INTERWORKING
2289252726Srpaulostatic int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2290252726Srpaulo				  char *argv[])
2291252726Srpaulo{
2292252726Srpaulo	return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2293252726Srpaulo}
2294252726Srpaulo
2295252726Srpaulo
2296252726Srpaulostatic int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2297252726Srpaulo				       char *argv[])
2298252726Srpaulo{
2299252726Srpaulo	return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2300252726Srpaulo}
2301252726Srpaulo
2302252726Srpaulo
2303252726Srpaulostatic int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2304252726Srpaulo					   char *argv[])
2305252726Srpaulo{
2306252726Srpaulo	return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2307252726Srpaulo}
2308252726Srpaulo
2309252726Srpaulo
2310252726Srpaulostatic int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2311252726Srpaulo					    char *argv[])
2312252726Srpaulo{
2313252726Srpaulo	return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2314252726Srpaulo}
2315252726Srpaulo
2316252726Srpaulo
2317281806Srpaulostatic int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2318281806Srpaulo						char *argv[])
2319281806Srpaulo{
2320281806Srpaulo	return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2321281806Srpaulo}
2322281806Srpaulo
2323281806Srpaulo
2324252726Srpaulostatic int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2325252726Srpaulo{
2326252726Srpaulo	return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2327252726Srpaulo}
2328252726Srpaulo
2329252726Srpaulo
2330252726Srpaulostatic int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2331252726Srpaulo				   char *argv[])
2332252726Srpaulo{
2333252726Srpaulo	return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2334252726Srpaulo}
2335252726Srpaulo
2336252726Srpaulo
2337252726Srpaulostatic int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2338252726Srpaulo					char *argv[])
2339252726Srpaulo{
2340252726Srpaulo	return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2341252726Srpaulo}
2342252726Srpaulo#endif /* CONFIG_INTERWORKING */
2343252726Srpaulo
2344252726Srpaulo
2345252726Srpaulo#ifdef CONFIG_HS20
2346252726Srpaulo
2347252726Srpaulostatic int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2348252726Srpaulo				     char *argv[])
2349252726Srpaulo{
2350252726Srpaulo	return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2351252726Srpaulo}
2352252726Srpaulo
2353252726Srpaulo
2354252726Srpaulostatic int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2355252726Srpaulo					       char *argv[])
2356252726Srpaulo{
2357252726Srpaulo	char cmd[512];
2358252726Srpaulo
2359252726Srpaulo	if (argc == 0) {
2360252726Srpaulo		printf("Command needs one or two arguments (dst mac addr and "
2361252726Srpaulo		       "optional home realm)\n");
2362252726Srpaulo		return -1;
2363214734Srpaulo	}
2364252726Srpaulo
2365252726Srpaulo	if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2366252726Srpaulo		      argc, argv) < 0)
2367252726Srpaulo		return -1;
2368252726Srpaulo
2369214734Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2370214734Srpaulo}
2371214734Srpaulo
2372281806Srpaulo
2373281806Srpaulostatic int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2374281806Srpaulo					 char *argv[])
2375281806Srpaulo{
2376281806Srpaulo	char cmd[512];
2377281806Srpaulo
2378281806Srpaulo	if (argc < 2) {
2379281806Srpaulo		printf("Command needs two arguments (dst mac addr and "
2380281806Srpaulo		       "icon name)\n");
2381281806Srpaulo		return -1;
2382281806Srpaulo	}
2383281806Srpaulo
2384281806Srpaulo	if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2385281806Srpaulo		return -1;
2386281806Srpaulo
2387281806Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2388281806Srpaulo}
2389281806Srpaulo
2390281806Srpaulo
2391281806Srpaulostatic int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2392281806Srpaulo{
2393281806Srpaulo	return wpa_ctrl_command(ctrl, "FETCH_OSU");
2394281806Srpaulo}
2395281806Srpaulo
2396281806Srpaulo
2397281806Srpaulostatic int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2398281806Srpaulo					char *argv[])
2399281806Srpaulo{
2400281806Srpaulo	return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2401281806Srpaulo}
2402281806Srpaulo
2403252726Srpaulo#endif /* CONFIG_HS20 */
2404214734Srpaulo
2405252726Srpaulo
2406252726Srpaulostatic int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2407252726Srpaulo				       char *argv[])
2408252726Srpaulo{
2409252726Srpaulo	return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2410252726Srpaulo}
2411252726Srpaulo
2412252726Srpaulo
2413252726Srpaulostatic int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2414252726Srpaulo				     char *argv[])
2415252726Srpaulo{
2416252726Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2417252726Srpaulo}
2418252726Srpaulo
2419252726Srpaulo
2420252726Srpaulostatic int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2421252726Srpaulo				  char *argv[])
2422252726Srpaulo{
2423252726Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2424252726Srpaulo}
2425252726Srpaulo
2426252726Srpaulo
2427252726Srpaulostatic int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2428252726Srpaulo				     char *argv[])
2429252726Srpaulo{
2430252726Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2431252726Srpaulo}
2432252726Srpaulo
2433252726Srpaulo
2434281806Srpaulostatic int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2435281806Srpaulo				    char *argv[])
2436281806Srpaulo{
2437281806Srpaulo	return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2438281806Srpaulo}
2439281806Srpaulo
2440281806Srpaulo
2441281806Srpaulostatic int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2442281806Srpaulo				    char *argv[])
2443281806Srpaulo{
2444281806Srpaulo	return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2445281806Srpaulo}
2446281806Srpaulo
2447281806Srpaulo
2448281806Srpaulostatic int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2449281806Srpaulo				    char *argv[])
2450281806Srpaulo{
2451281806Srpaulo	return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2452281806Srpaulo}
2453281806Srpaulo
2454281806Srpaulo
2455281806Srpaulostatic int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2456281806Srpaulo					char *argv[])
2457281806Srpaulo{
2458281806Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2459281806Srpaulo}
2460281806Srpaulo
2461281806Srpaulo
2462281806Srpaulostatic int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2463281806Srpaulo					       char *argv[])
2464281806Srpaulo{
2465281806Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2466281806Srpaulo}
2467281806Srpaulo
2468281806Srpaulo
2469252726Srpaulostatic int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2470252726Srpaulo				   char *argv[])
2471252726Srpaulo{
2472252726Srpaulo	return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2473252726Srpaulo}
2474252726Srpaulo
2475252726Srpaulo
2476252726Srpaulostatic int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2477252726Srpaulo				   char *argv[])
2478252726Srpaulo{
2479252726Srpaulo	return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2480252726Srpaulo}
2481252726Srpaulo
2482252726Srpaulo
2483252726Srpaulostatic int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2484252726Srpaulo				      char *argv[])
2485252726Srpaulo{
2486252726Srpaulo	return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2487252726Srpaulo}
2488252726Srpaulo
2489252726Srpaulo
2490252726Srpaulo#ifdef CONFIG_AUTOSCAN
2491252726Srpaulo
2492252726Srpaulostatic int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2493252726Srpaulo{
2494252726Srpaulo	if (argc == 0)
2495252726Srpaulo		return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2496252726Srpaulo
2497252726Srpaulo	return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2498252726Srpaulo}
2499252726Srpaulo
2500252726Srpaulo#endif /* CONFIG_AUTOSCAN */
2501252726Srpaulo
2502252726Srpaulo
2503252726Srpaulo#ifdef CONFIG_WNM
2504252726Srpaulo
2505252726Srpaulostatic int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2506252726Srpaulo{
2507252726Srpaulo	return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2508252726Srpaulo}
2509252726Srpaulo
2510281806Srpaulo
2511281806Srpaulostatic int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2512281806Srpaulo{
2513281806Srpaulo	return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2514281806Srpaulo}
2515281806Srpaulo
2516252726Srpaulo#endif /* CONFIG_WNM */
2517252726Srpaulo
2518252726Srpaulo
2519252726Srpaulostatic int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2520252726Srpaulo{
2521252726Srpaulo	if (argc == 0)
2522252726Srpaulo		return -1;
2523252726Srpaulo	return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2524252726Srpaulo}
2525252726Srpaulo
2526252726Srpaulo
2527281806Srpaulo#ifdef ANDROID
2528281806Srpaulostatic int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2529281806Srpaulo{
2530281806Srpaulo	return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2531281806Srpaulo}
2532281806Srpaulo#endif /* ANDROID */
2533281806Srpaulo
2534281806Srpaulo
2535281806Srpaulostatic int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2536281806Srpaulo{
2537281806Srpaulo	return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2538281806Srpaulo}
2539281806Srpaulo
2540281806Srpaulo
2541281806Srpaulostatic int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2542281806Srpaulo{
2543281806Srpaulo	return wpa_ctrl_command(ctrl, "FLUSH");
2544281806Srpaulo}
2545281806Srpaulo
2546281806Srpaulo
2547281806Srpaulostatic int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2548281806Srpaulo{
2549281806Srpaulo	return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2550281806Srpaulo}
2551281806Srpaulo
2552281806Srpaulo
2553281806Srpaulostatic int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2554281806Srpaulo					    char *argv[])
2555281806Srpaulo{
2556281806Srpaulo	return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2557281806Srpaulo}
2558281806Srpaulo
2559281806Srpaulo
2560281806Srpaulostatic int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2561281806Srpaulo{
2562281806Srpaulo	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2563281806Srpaulo}
2564281806Srpaulo
2565281806Srpaulo
2566281806Srpaulostatic int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2567281806Srpaulo				     char *argv[])
2568281806Srpaulo{
2569281806Srpaulo	return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2570281806Srpaulo}
2571281806Srpaulo
2572281806Srpaulo
2573189251Ssamenum wpa_cli_cmd_flags {
2574189251Ssam	cli_cmd_flag_none		= 0x00,
2575189251Ssam	cli_cmd_flag_sensitive		= 0x01
2576189251Ssam};
2577189251Ssam
2578189251Ssamstruct wpa_cli_cmd {
2579189251Ssam	const char *cmd;
2580189251Ssam	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2581252726Srpaulo	char ** (*completion)(const char *str, int pos);
2582189251Ssam	enum wpa_cli_cmd_flags flags;
2583189251Ssam	const char *usage;
2584189251Ssam};
2585189251Ssam
2586189251Ssamstatic struct wpa_cli_cmd wpa_cli_commands[] = {
2587252726Srpaulo	{ "status", wpa_cli_cmd_status, NULL,
2588189251Ssam	  cli_cmd_flag_none,
2589189251Ssam	  "[verbose] = get current WPA/EAPOL/EAP status" },
2590252726Srpaulo	{ "ifname", wpa_cli_cmd_ifname, NULL,
2591189251Ssam	  cli_cmd_flag_none,
2592252726Srpaulo	  "= get current interface name" },
2593252726Srpaulo	{ "ping", wpa_cli_cmd_ping, NULL,
2594252726Srpaulo	  cli_cmd_flag_none,
2595189251Ssam	  "= pings wpa_supplicant" },
2596252726Srpaulo	{ "relog", wpa_cli_cmd_relog, NULL,
2597189251Ssam	  cli_cmd_flag_none,
2598252726Srpaulo	  "= re-open log-file (allow rolling logs)" },
2599252726Srpaulo	{ "note", wpa_cli_cmd_note, NULL,
2600252726Srpaulo	  cli_cmd_flag_none,
2601252726Srpaulo	  "<text> = add a note to wpa_supplicant debug log" },
2602252726Srpaulo	{ "mib", wpa_cli_cmd_mib, NULL,
2603252726Srpaulo	  cli_cmd_flag_none,
2604189251Ssam	  "= get MIB variables (dot1x, dot11)" },
2605252726Srpaulo	{ "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2606189251Ssam	  cli_cmd_flag_none,
2607252726Srpaulo	  "[command] = show usage help" },
2608252726Srpaulo	{ "interface", wpa_cli_cmd_interface, NULL,
2609189251Ssam	  cli_cmd_flag_none,
2610189251Ssam	  "[ifname] = show interfaces/select interface" },
2611252726Srpaulo	{ "level", wpa_cli_cmd_level, NULL,
2612189251Ssam	  cli_cmd_flag_none,
2613189251Ssam	  "<debug level> = change debug level" },
2614252726Srpaulo	{ "license", wpa_cli_cmd_license, NULL,
2615189251Ssam	  cli_cmd_flag_none,
2616189251Ssam	  "= show full wpa_cli license" },
2617252726Srpaulo	{ "quit", wpa_cli_cmd_quit, NULL,
2618189251Ssam	  cli_cmd_flag_none,
2619189251Ssam	  "= exit wpa_cli" },
2620281806Srpaulo	{ "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2621189251Ssam	  cli_cmd_flag_none,
2622189251Ssam	  "= set variables (shows list of variables when run without "
2623189251Ssam	  "arguments)" },
2624281806Srpaulo	{ "dump", wpa_cli_cmd_dump, NULL,
2625281806Srpaulo	  cli_cmd_flag_none,
2626281806Srpaulo	  "= dump config variables" },
2627252726Srpaulo	{ "get", wpa_cli_cmd_get, NULL,
2628189251Ssam	  cli_cmd_flag_none,
2629252726Srpaulo	  "<name> = get information" },
2630252726Srpaulo	{ "logon", wpa_cli_cmd_logon, NULL,
2631252726Srpaulo	  cli_cmd_flag_none,
2632189251Ssam	  "= IEEE 802.1X EAPOL state machine logon" },
2633252726Srpaulo	{ "logoff", wpa_cli_cmd_logoff, NULL,
2634189251Ssam	  cli_cmd_flag_none,
2635189251Ssam	  "= IEEE 802.1X EAPOL state machine logoff" },
2636252726Srpaulo	{ "pmksa", wpa_cli_cmd_pmksa, NULL,
2637189251Ssam	  cli_cmd_flag_none,
2638189251Ssam	  "= show PMKSA cache" },
2639281806Srpaulo	{ "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2640281806Srpaulo	  cli_cmd_flag_none,
2641281806Srpaulo	  "= flush PMKSA cache entries" },
2642252726Srpaulo	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
2643189251Ssam	  cli_cmd_flag_none,
2644189251Ssam	  "= force reassociation" },
2645281806Srpaulo	{ "reattach", wpa_cli_cmd_reattach, NULL,
2646281806Srpaulo	  cli_cmd_flag_none,
2647281806Srpaulo	  "= force reassociation back to the same BSS" },
2648252726Srpaulo	{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2649189251Ssam	  cli_cmd_flag_none,
2650189251Ssam	  "<BSSID> = force preauthentication" },
2651252726Srpaulo	{ "identity", wpa_cli_cmd_identity, NULL,
2652189251Ssam	  cli_cmd_flag_none,
2653189251Ssam	  "<network id> <identity> = configure identity for an SSID" },
2654252726Srpaulo	{ "password", wpa_cli_cmd_password, NULL,
2655189251Ssam	  cli_cmd_flag_sensitive,
2656189251Ssam	  "<network id> <password> = configure password for an SSID" },
2657252726Srpaulo	{ "new_password", wpa_cli_cmd_new_password, NULL,
2658189251Ssam	  cli_cmd_flag_sensitive,
2659189251Ssam	  "<network id> <password> = change password for an SSID" },
2660252726Srpaulo	{ "pin", wpa_cli_cmd_pin, NULL,
2661189251Ssam	  cli_cmd_flag_sensitive,
2662189251Ssam	  "<network id> <pin> = configure pin for an SSID" },
2663252726Srpaulo	{ "otp", wpa_cli_cmd_otp, NULL,
2664189251Ssam	  cli_cmd_flag_sensitive,
2665189251Ssam	  "<network id> <password> = configure one-time-password for an SSID"
2666189251Ssam	},
2667252726Srpaulo	{ "passphrase", wpa_cli_cmd_passphrase, NULL,
2668189251Ssam	  cli_cmd_flag_sensitive,
2669189251Ssam	  "<network id> <passphrase> = configure private key passphrase\n"
2670189251Ssam	  "  for an SSID" },
2671281806Srpaulo	{ "sim", wpa_cli_cmd_sim, NULL,
2672281806Srpaulo	  cli_cmd_flag_sensitive,
2673281806Srpaulo	  "<network id> <pin> = report SIM operation result" },
2674252726Srpaulo	{ "bssid", wpa_cli_cmd_bssid, NULL,
2675189251Ssam	  cli_cmd_flag_none,
2676189251Ssam	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
2677252726Srpaulo	{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2678189251Ssam	  cli_cmd_flag_none,
2679252726Srpaulo	  "<BSSID> = add a BSSID to the blacklist\n"
2680252726Srpaulo	  "blacklist clear = clear the blacklist\n"
2681252726Srpaulo	  "blacklist = display the blacklist" },
2682252726Srpaulo	{ "log_level", wpa_cli_cmd_log_level, NULL,
2683252726Srpaulo	  cli_cmd_flag_none,
2684252726Srpaulo	  "<level> [<timestamp>] = update the log level/timestamp\n"
2685252726Srpaulo	  "log_level = display the current log level and log options" },
2686252726Srpaulo	{ "list_networks", wpa_cli_cmd_list_networks, NULL,
2687252726Srpaulo	  cli_cmd_flag_none,
2688189251Ssam	  "= list configured networks" },
2689252726Srpaulo	{ "select_network", wpa_cli_cmd_select_network, NULL,
2690189251Ssam	  cli_cmd_flag_none,
2691189251Ssam	  "<network id> = select a network (disable others)" },
2692252726Srpaulo	{ "enable_network", wpa_cli_cmd_enable_network, NULL,
2693189251Ssam	  cli_cmd_flag_none,
2694189251Ssam	  "<network id> = enable a network" },
2695252726Srpaulo	{ "disable_network", wpa_cli_cmd_disable_network, NULL,
2696189251Ssam	  cli_cmd_flag_none,
2697189251Ssam	  "<network id> = disable a network" },
2698252726Srpaulo	{ "add_network", wpa_cli_cmd_add_network, NULL,
2699189251Ssam	  cli_cmd_flag_none,
2700189251Ssam	  "= add a network" },
2701252726Srpaulo	{ "remove_network", wpa_cli_cmd_remove_network, NULL,
2702189251Ssam	  cli_cmd_flag_none,
2703189251Ssam	  "<network id> = remove a network" },
2704252726Srpaulo	{ "set_network", wpa_cli_cmd_set_network, NULL,
2705189251Ssam	  cli_cmd_flag_sensitive,
2706189251Ssam	  "<network id> <variable> <value> = set network variables (shows\n"
2707189251Ssam	  "  list of variables when run without arguments)" },
2708252726Srpaulo	{ "get_network", wpa_cli_cmd_get_network, NULL,
2709189251Ssam	  cli_cmd_flag_none,
2710189251Ssam	  "<network id> <variable> = get network variables" },
2711281806Srpaulo	{ "dup_network", wpa_cli_cmd_dup_network, NULL,
2712281806Srpaulo	  cli_cmd_flag_none,
2713281806Srpaulo	  "<src network id> <dst network id> <variable> = duplicate network variables"
2714281806Srpaulo	},
2715252726Srpaulo	{ "list_creds", wpa_cli_cmd_list_creds, NULL,
2716189251Ssam	  cli_cmd_flag_none,
2717252726Srpaulo	  "= list configured credentials" },
2718252726Srpaulo	{ "add_cred", wpa_cli_cmd_add_cred, NULL,
2719252726Srpaulo	  cli_cmd_flag_none,
2720252726Srpaulo	  "= add a credential" },
2721252726Srpaulo	{ "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2722252726Srpaulo	  cli_cmd_flag_none,
2723252726Srpaulo	  "<cred id> = remove a credential" },
2724252726Srpaulo	{ "set_cred", wpa_cli_cmd_set_cred, NULL,
2725252726Srpaulo	  cli_cmd_flag_sensitive,
2726252726Srpaulo	  "<cred id> <variable> <value> = set credential variables" },
2727281806Srpaulo	{ "get_cred", wpa_cli_cmd_get_cred, NULL,
2728281806Srpaulo	  cli_cmd_flag_none,
2729281806Srpaulo	  "<cred id> <variable> = get credential variables" },
2730252726Srpaulo	{ "save_config", wpa_cli_cmd_save_config, NULL,
2731252726Srpaulo	  cli_cmd_flag_none,
2732189251Ssam	  "= save the current configuration" },
2733252726Srpaulo	{ "disconnect", wpa_cli_cmd_disconnect, NULL,
2734189251Ssam	  cli_cmd_flag_none,
2735189251Ssam	  "= disconnect and wait for reassociate/reconnect command before\n"
2736189251Ssam	  "  connecting" },
2737252726Srpaulo	{ "reconnect", wpa_cli_cmd_reconnect, NULL,
2738189251Ssam	  cli_cmd_flag_none,
2739189251Ssam	  "= like reassociate, but only takes effect if already disconnected"
2740189251Ssam	},
2741252726Srpaulo	{ "scan", wpa_cli_cmd_scan, NULL,
2742189251Ssam	  cli_cmd_flag_none,
2743189251Ssam	  "= request new BSS scan" },
2744252726Srpaulo	{ "scan_results", wpa_cli_cmd_scan_results, NULL,
2745189251Ssam	  cli_cmd_flag_none,
2746189251Ssam	  "= get latest scan results" },
2747252726Srpaulo	{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2748189251Ssam	  cli_cmd_flag_none,
2749189251Ssam	  "<<idx> | <bssid>> = get detailed scan result info" },
2750252726Srpaulo	{ "get_capability", wpa_cli_cmd_get_capability, NULL,
2751189251Ssam	  cli_cmd_flag_none,
2752281806Srpaulo	  "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
2753252726Srpaulo	  "= get capabilies" },
2754252726Srpaulo	{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2755189251Ssam	  cli_cmd_flag_none,
2756189251Ssam	  "= force wpa_supplicant to re-read its configuration file" },
2757252726Srpaulo	{ "terminate", wpa_cli_cmd_terminate, NULL,
2758189251Ssam	  cli_cmd_flag_none,
2759189251Ssam	  "= terminate wpa_supplicant" },
2760252726Srpaulo	{ "interface_add", wpa_cli_cmd_interface_add, NULL,
2761189251Ssam	  cli_cmd_flag_none,
2762189251Ssam	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2763189251Ssam	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2764189251Ssam	  "  are optional" },
2765252726Srpaulo	{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2766189251Ssam	  cli_cmd_flag_none,
2767189251Ssam	  "<ifname> = removes the interface" },
2768252726Srpaulo	{ "interface_list", wpa_cli_cmd_interface_list, NULL,
2769189251Ssam	  cli_cmd_flag_none,
2770189251Ssam	  "= list available interfaces" },
2771252726Srpaulo	{ "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2772189251Ssam	  cli_cmd_flag_none,
2773189251Ssam	  "<value> = set ap_scan parameter" },
2774252726Srpaulo	{ "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2775189251Ssam	  cli_cmd_flag_none,
2776252726Srpaulo	  "<value> = set scan_interval parameter (in seconds)" },
2777252726Srpaulo	{ "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2778252726Srpaulo	  cli_cmd_flag_none,
2779252726Srpaulo	  "<value> = set BSS expiration age parameter" },
2780252726Srpaulo	{ "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2781252726Srpaulo	  cli_cmd_flag_none,
2782252726Srpaulo	  "<value> = set BSS expiration scan count parameter" },
2783252726Srpaulo	{ "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2784252726Srpaulo	  cli_cmd_flag_none,
2785252726Srpaulo	  "<value> = set BSS flush age (0 by default)" },
2786252726Srpaulo	{ "stkstart", wpa_cli_cmd_stkstart, NULL,
2787252726Srpaulo	  cli_cmd_flag_none,
2788189251Ssam	  "<addr> = request STK negotiation with <addr>" },
2789252726Srpaulo	{ "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2790189251Ssam	  cli_cmd_flag_none,
2791189251Ssam	  "<addr> = request over-the-DS FT with <addr>" },
2792252726Srpaulo	{ "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2793189251Ssam	  cli_cmd_flag_none,
2794189251Ssam	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2795252726Srpaulo	{ "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2796189251Ssam	  cli_cmd_flag_sensitive,
2797189251Ssam	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2798189251Ssam	  "hardcoded)" },
2799252726Srpaulo	{ "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2800214734Srpaulo	  cli_cmd_flag_sensitive,
2801252726Srpaulo	  "<PIN> = verify PIN checksum" },
2802252726Srpaulo	{ "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2803252726Srpaulo	  "Cancels the pending WPS operation" },
2804252726Srpaulo#ifdef CONFIG_WPS_NFC
2805252726Srpaulo	{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2806252726Srpaulo	  cli_cmd_flag_none,
2807252726Srpaulo	  "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2808281806Srpaulo	{ "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2809281806Srpaulo	  cli_cmd_flag_none,
2810281806Srpaulo	  "<WPS|NDEF> = build configuration token" },
2811252726Srpaulo	{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2812252726Srpaulo	  cli_cmd_flag_none,
2813252726Srpaulo	  "<WPS|NDEF> = create password token" },
2814252726Srpaulo	{ "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2815189251Ssam	  cli_cmd_flag_sensitive,
2816252726Srpaulo	  "<hexdump of payload> = report read NFC tag with WPS data" },
2817252726Srpaulo	{ "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2818252726Srpaulo	  cli_cmd_flag_none,
2819252726Srpaulo	  "<NDEF> <WPS> = create NFC handover request" },
2820252726Srpaulo	{ "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2821252726Srpaulo	  cli_cmd_flag_none,
2822252726Srpaulo	  "<NDEF> <WPS> = create NFC handover select" },
2823281806Srpaulo	{ "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2824252726Srpaulo	  cli_cmd_flag_none,
2825281806Srpaulo	  "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2826281806Srpaulo	  "NFC handover" },
2827252726Srpaulo#endif /* CONFIG_WPS_NFC */
2828252726Srpaulo	{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2829252726Srpaulo	  cli_cmd_flag_sensitive,
2830189251Ssam	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2831252726Srpaulo	{ "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2832252726Srpaulo	  cli_cmd_flag_sensitive,
2833252726Srpaulo	  "[params..] = enable/disable AP PIN" },
2834252726Srpaulo	{ "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2835214734Srpaulo	  cli_cmd_flag_none,
2836252726Srpaulo	  "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2837252726Srpaulo	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2838214734Srpaulo	  cli_cmd_flag_none,
2839214734Srpaulo	  "= stop Wi-Fi Protected Setup External Registrar" },
2840252726Srpaulo	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2841214734Srpaulo	  cli_cmd_flag_sensitive,
2842214734Srpaulo	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2843252726Srpaulo	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2844214734Srpaulo	  cli_cmd_flag_none,
2845214734Srpaulo	  "<UUID> = accept an Enrollee PBC using External Registrar" },
2846252726Srpaulo	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2847214734Srpaulo	  cli_cmd_flag_sensitive,
2848214734Srpaulo	  "<UUID> <PIN> = learn AP configuration" },
2849252726Srpaulo	{ "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2850214734Srpaulo	  cli_cmd_flag_none,
2851252726Srpaulo	  "<UUID> <network id> = set AP configuration for enrolling" },
2852252726Srpaulo	{ "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2853252726Srpaulo	  cli_cmd_flag_sensitive,
2854252726Srpaulo	  "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2855252726Srpaulo#ifdef CONFIG_WPS_NFC
2856252726Srpaulo	{ "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2857252726Srpaulo	  cli_cmd_flag_none,
2858252726Srpaulo	  "<WPS/NDEF> <UUID> = build NFC configuration token" },
2859252726Srpaulo#endif /* CONFIG_WPS_NFC */
2860252726Srpaulo	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2861252726Srpaulo	  cli_cmd_flag_none,
2862214734Srpaulo	  "<addr> = request RSN authentication with <addr> in IBSS" },
2863214734Srpaulo#ifdef CONFIG_AP
2864252726Srpaulo	{ "sta", wpa_cli_cmd_sta, NULL,
2865214734Srpaulo	  cli_cmd_flag_none,
2866214734Srpaulo	  "<addr> = get information about an associated station (AP)" },
2867252726Srpaulo	{ "all_sta", wpa_cli_cmd_all_sta, NULL,
2868214734Srpaulo	  cli_cmd_flag_none,
2869214734Srpaulo	  "= get information about all associated stations (AP)" },
2870252726Srpaulo	{ "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2871252726Srpaulo	  cli_cmd_flag_none,
2872252726Srpaulo	  "<addr> = deauthenticate a station" },
2873252726Srpaulo	{ "disassociate", wpa_cli_cmd_disassociate, NULL,
2874252726Srpaulo	  cli_cmd_flag_none,
2875252726Srpaulo	  "<addr> = disassociate a station" },
2876281806Srpaulo	{ "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2877281806Srpaulo	  cli_cmd_flag_none,
2878281806Srpaulo	  "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2879281806Srpaulo	  " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2880281806Srpaulo	  " = CSA parameters" },
2881214734Srpaulo#endif /* CONFIG_AP */
2882252726Srpaulo	{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2883214734Srpaulo	  "= notification of suspend/hibernate" },
2884252726Srpaulo	{ "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2885214734Srpaulo	  "= notification of resume/thaw" },
2886281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS
2887252726Srpaulo	{ "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2888214734Srpaulo	  "= drop SA without deauth/disassoc (test command)" },
2889281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */
2890252726Srpaulo	{ "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2891214734Srpaulo	  cli_cmd_flag_none,
2892214734Srpaulo	  "<addr> = roam to the specified BSS" },
2893281806Srpaulo#ifdef CONFIG_MESH
2894281806Srpaulo	{ "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
2895281806Srpaulo	  cli_cmd_flag_none,
2896281806Srpaulo	  "[ifname] = Create a new mesh interface" },
2897281806Srpaulo	{ "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
2898281806Srpaulo	  cli_cmd_flag_none,
2899281806Srpaulo	  "<network id> = join a mesh network (disable others)" },
2900281806Srpaulo	{ "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
2901281806Srpaulo	  cli_cmd_flag_none,
2902281806Srpaulo	  "<ifname> = Remove mesh group interface" },
2903281806Srpaulo#endif /* CONFIG_MESH */
2904252726Srpaulo#ifdef CONFIG_P2P
2905252726Srpaulo	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2906252726Srpaulo	  cli_cmd_flag_none,
2907252726Srpaulo	  "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2908252726Srpaulo	{ "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2909252726Srpaulo	  "= stop P2P Devices search" },
2910281806Srpaulo	{ "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
2911281806Srpaulo	  cli_cmd_flag_none,
2912281806Srpaulo	  "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
2913281806Srpaulo	{ "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
2914281806Srpaulo	  cli_cmd_flag_none,
2915281806Srpaulo	  "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
2916252726Srpaulo	{ "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2917252726Srpaulo	  cli_cmd_flag_none,
2918252726Srpaulo	  "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2919252726Srpaulo	{ "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2920252726Srpaulo	  "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2921252726Srpaulo	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2922252726Srpaulo	  wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2923252726Srpaulo	  "<ifname> = remove P2P group interface (terminate group if GO)" },
2924252726Srpaulo	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2925252726Srpaulo	  "[ht40] = add a new P2P group (local end as GO)" },
2926252726Srpaulo	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2927252726Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2928252726Srpaulo	  "<addr> <method> = request provisioning discovery" },
2929252726Srpaulo	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2930252726Srpaulo	  cli_cmd_flag_none,
2931252726Srpaulo	  "= get the passphrase for a group (GO only)" },
2932252726Srpaulo	{ "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2933252726Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2934252726Srpaulo	  "<addr> <TLVs> = schedule service discovery request" },
2935252726Srpaulo	{ "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2936252726Srpaulo	  NULL, cli_cmd_flag_none,
2937252726Srpaulo	  "<id> = cancel pending service discovery request" },
2938252726Srpaulo	{ "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2939252726Srpaulo	  cli_cmd_flag_none,
2940252726Srpaulo	  "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2941252726Srpaulo	{ "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2942252726Srpaulo	  cli_cmd_flag_none,
2943252726Srpaulo	  "= indicate change in local services" },
2944252726Srpaulo	{ "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2945252726Srpaulo	  cli_cmd_flag_none,
2946252726Srpaulo	  "<external> = set external processing of service discovery" },
2947252726Srpaulo	{ "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2948252726Srpaulo	  cli_cmd_flag_none,
2949252726Srpaulo	  "= remove all stored service entries" },
2950252726Srpaulo	{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2951252726Srpaulo	  cli_cmd_flag_none,
2952281806Srpaulo	  "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
2953252726Srpaulo	  "service" },
2954281806Srpaulo	{ "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
2955281806Srpaulo	  cli_cmd_flag_none,
2956281806Srpaulo	  "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
2957281806Srpaulo	  "local ASP service" },
2958252726Srpaulo	{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2959252726Srpaulo	  cli_cmd_flag_none,
2960252726Srpaulo	  "<bonjour|upnp> <query|version> [|service] = remove a local "
2961252726Srpaulo	  "service" },
2962252726Srpaulo	{ "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2963252726Srpaulo	  cli_cmd_flag_none,
2964252726Srpaulo	  "<addr> = reject connection attempts from a specific peer" },
2965252726Srpaulo	{ "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2966252726Srpaulo	  cli_cmd_flag_none,
2967252726Srpaulo	  "<cmd> [peer=addr] = invite peer" },
2968252726Srpaulo	{ "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2969252726Srpaulo	  "[discovered] = list known (optionally, only fully discovered) P2P "
2970252726Srpaulo	  "peers" },
2971252726Srpaulo	{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2972252726Srpaulo	  cli_cmd_flag_none,
2973252726Srpaulo	  "<address> = show information about known P2P peer" },
2974281806Srpaulo	{ "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2975281806Srpaulo	  cli_cmd_flag_none,
2976252726Srpaulo	  "<field> <value> = set a P2P parameter" },
2977252726Srpaulo	{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2978252726Srpaulo	  "= flush P2P state" },
2979252726Srpaulo	{ "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2980252726Srpaulo	  "= cancel P2P group formation" },
2981252726Srpaulo	{ "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2982252726Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2983252726Srpaulo	  "<address> = unauthorize a peer" },
2984252726Srpaulo	{ "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2985252726Srpaulo	  cli_cmd_flag_none,
2986252726Srpaulo	  "[<duration> <interval>] [<duration> <interval>] = request GO "
2987252726Srpaulo	  "presence" },
2988252726Srpaulo	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2989252726Srpaulo	  cli_cmd_flag_none,
2990252726Srpaulo	  "[<period> <interval>] = set extended listen timing" },
2991281806Srpaulo	{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2992281806Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2993281806Srpaulo	  "<address|iface=address> = remove a peer from all groups" },
2994252726Srpaulo#endif /* CONFIG_P2P */
2995252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY
2996252726Srpaulo	{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2997252726Srpaulo	  cli_cmd_flag_none,
2998252726Srpaulo	  "<subelem> [contents] = set Wi-Fi Display subelement" },
2999252726Srpaulo	{ "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3000252726Srpaulo	  cli_cmd_flag_none,
3001252726Srpaulo	  "<subelem> = get Wi-Fi Display subelement" },
3002252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */
3003252726Srpaulo#ifdef CONFIG_INTERWORKING
3004252726Srpaulo	{ "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
3005252726Srpaulo	  "= fetch ANQP information for all APs" },
3006252726Srpaulo	{ "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3007252726Srpaulo	  cli_cmd_flag_none,
3008252726Srpaulo	  "= stop fetch_anqp operation" },
3009252726Srpaulo	{ "interworking_select", wpa_cli_cmd_interworking_select, NULL,
3010252726Srpaulo	  cli_cmd_flag_none,
3011252726Srpaulo	  "[auto] = perform Interworking network selection" },
3012252726Srpaulo	{ "interworking_connect", wpa_cli_cmd_interworking_connect,
3013252726Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
3014252726Srpaulo	  "<BSSID> = connect using Interworking credentials" },
3015281806Srpaulo	{ "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3016281806Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
3017281806Srpaulo	  "<BSSID> = connect using Interworking credentials" },
3018252726Srpaulo	{ "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3019252726Srpaulo	  cli_cmd_flag_none,
3020252726Srpaulo	  "<addr> <info id>[,<info id>]... = request ANQP information" },
3021252726Srpaulo	{ "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3022252726Srpaulo	  cli_cmd_flag_none,
3023252726Srpaulo	  "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3024252726Srpaulo	{ "gas_response_get", wpa_cli_cmd_gas_response_get,
3025252726Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
3026252726Srpaulo	  "<addr> <dialog token> [start,len] = Fetch last GAS response" },
3027252726Srpaulo#endif /* CONFIG_INTERWORKING */
3028252726Srpaulo#ifdef CONFIG_HS20
3029252726Srpaulo	{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3030252726Srpaulo	  cli_cmd_flag_none,
3031252726Srpaulo	  "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3032252726Srpaulo	},
3033252726Srpaulo	{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3034252726Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
3035252726Srpaulo	  "<addr> <home realm> = get HS20 nai home realm list" },
3036281806Srpaulo	{ "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3037281806Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
3038281806Srpaulo	  "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3039281806Srpaulo	{ "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3040281806Srpaulo	  "= fetch OSU provider information from all APs" },
3041281806Srpaulo	{ "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3042281806Srpaulo	  cli_cmd_flag_none,
3043281806Srpaulo	  "= cancel fetch_osu command" },
3044252726Srpaulo#endif /* CONFIG_HS20 */
3045252726Srpaulo	{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3046252726Srpaulo	  cli_cmd_flag_none,
3047252726Srpaulo	  "<0/1> = disable/enable automatic reconnection" },
3048252726Srpaulo	{ "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
3049252726Srpaulo	  cli_cmd_flag_none,
3050252726Srpaulo	  "<addr> = request TDLS discovery with <addr>" },
3051252726Srpaulo	{ "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
3052252726Srpaulo	  cli_cmd_flag_none,
3053252726Srpaulo	  "<addr> = request TDLS setup with <addr>" },
3054252726Srpaulo	{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
3055252726Srpaulo	  cli_cmd_flag_none,
3056252726Srpaulo	  "<addr> = tear down TDLS with <addr>" },
3057281806Srpaulo	{ "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3058281806Srpaulo	  cli_cmd_flag_none,
3059281806Srpaulo	  "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3060281806Srpaulo	  "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3061281806Srpaulo	  "= add WMM-AC traffic stream" },
3062281806Srpaulo	{ "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3063281806Srpaulo	  cli_cmd_flag_none,
3064281806Srpaulo	  "<tsid> = delete WMM-AC traffic stream" },
3065281806Srpaulo	{ "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3066281806Srpaulo	  cli_cmd_flag_none,
3067281806Srpaulo	  "= show status for Wireless Multi-Media Admission-Control" },
3068281806Srpaulo	{ "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3069281806Srpaulo	  cli_cmd_flag_none,
3070281806Srpaulo	  "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3071281806Srpaulo	  "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3072281806Srpaulo	  "with TDLS peer" },
3073281806Srpaulo	{ "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3074281806Srpaulo	  cli_cmd_flag_none,
3075281806Srpaulo	  "<addr> = disable channel switching with TDLS peer <addr>" },
3076252726Srpaulo	{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
3077252726Srpaulo	  cli_cmd_flag_none,
3078252726Srpaulo	  "= get signal parameters" },
3079252726Srpaulo	{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3080252726Srpaulo	  cli_cmd_flag_none,
3081252726Srpaulo	  "= get TX/RX packet counters" },
3082252726Srpaulo	{ "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3083252726Srpaulo	  cli_cmd_flag_none,
3084252726Srpaulo	  "= trigger IEEE 802.1X/EAPOL reauthentication" },
3085252726Srpaulo#ifdef CONFIG_AUTOSCAN
3086252726Srpaulo	{ "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
3087252726Srpaulo	  "[params] = Set or unset (if none) autoscan parameters" },
3088252726Srpaulo#endif /* CONFIG_AUTOSCAN */
3089252726Srpaulo#ifdef CONFIG_WNM
3090252726Srpaulo	{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3091252726Srpaulo	  "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
3092281806Srpaulo	{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3093281806Srpaulo	  "<query reason> = Send BSS Transition Management Query" },
3094252726Srpaulo#endif /* CONFIG_WNM */
3095252726Srpaulo	{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3096252726Srpaulo	  "<params..> = Sent unprocessed command" },
3097281806Srpaulo	{ "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3098281806Srpaulo	  "= flush wpa_supplicant state" },
3099281806Srpaulo#ifdef ANDROID
3100281806Srpaulo	{ "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3101281806Srpaulo	  "<command> = driver private commands" },
3102281806Srpaulo#endif /* ANDROID */
3103281806Srpaulo	{ "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3104281806Srpaulo	  "= radio_work <show/add/done>" },
3105281806Srpaulo	{ "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3106281806Srpaulo	  "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3107281806Srpaulo	},
3108281806Srpaulo	{ "neighbor_rep_request",
3109281806Srpaulo	  wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3110281806Srpaulo	  "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3111281806Srpaulo	  "(with optional given SSID, default: current SSID)"
3112281806Srpaulo	},
3113281806Srpaulo	{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3114281806Srpaulo	  "= flush ERP keys" },
3115281806Srpaulo	{ "mac_rand_scan",
3116281806Srpaulo	  wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3117281806Srpaulo	  "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3118281806Srpaulo	  "mask=mac-address-mask] = scan MAC randomization"
3119281806Srpaulo	},
3120252726Srpaulo	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
3121189251Ssam};
3122189251Ssam
3123189251Ssam
3124189251Ssam/*
3125189251Ssam * Prints command usage, lines are padded with the specified string.
3126189251Ssam */
3127189251Ssamstatic void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3128189251Ssam{
3129189251Ssam	char c;
3130189251Ssam	size_t n;
3131189251Ssam
3132189251Ssam	printf("%s%s ", pad, cmd->cmd);
3133189251Ssam	for (n = 0; (c = cmd->usage[n]); n++) {
3134189251Ssam		printf("%c", c);
3135189251Ssam		if (c == '\n')
3136189251Ssam			printf("%s", pad);
3137189251Ssam	}
3138189251Ssam	printf("\n");
3139189251Ssam}
3140189251Ssam
3141189251Ssam
3142252726Srpaulostatic void print_help(const char *cmd)
3143189251Ssam{
3144189251Ssam	int n;
3145189251Ssam	printf("commands:\n");
3146252726Srpaulo	for (n = 0; wpa_cli_commands[n].cmd; n++) {
3147252726Srpaulo		if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3148252726Srpaulo			print_cmd_help(&wpa_cli_commands[n], "  ");
3149252726Srpaulo	}
3150189251Ssam}
3151189251Ssam
3152189251Ssam
3153252726Srpaulostatic int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3154189251Ssam{
3155189251Ssam	const char *c, *delim;
3156189251Ssam	int n;
3157189251Ssam	size_t len;
3158189251Ssam
3159189251Ssam	delim = os_strchr(cmd, ' ');
3160189251Ssam	if (delim)
3161189251Ssam		len = delim - cmd;
3162189251Ssam	else
3163189251Ssam		len = os_strlen(cmd);
3164189251Ssam
3165189251Ssam	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3166189251Ssam		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3167189251Ssam			return (wpa_cli_commands[n].flags &
3168189251Ssam				cli_cmd_flag_sensitive);
3169189251Ssam	}
3170189251Ssam	return 0;
3171189251Ssam}
3172189251Ssam
3173189251Ssam
3174252726Srpaulostatic char ** wpa_list_cmd_list(void)
3175252726Srpaulo{
3176252726Srpaulo	char **res;
3177252726Srpaulo	int i, count;
3178281806Srpaulo	struct cli_txt_entry *e;
3179252726Srpaulo
3180281806Srpaulo	count = ARRAY_SIZE(wpa_cli_commands);
3181281806Srpaulo	count += dl_list_len(&p2p_groups);
3182281806Srpaulo	count += dl_list_len(&ifnames);
3183281806Srpaulo	res = os_calloc(count + 1, sizeof(char *));
3184252726Srpaulo	if (res == NULL)
3185252726Srpaulo		return NULL;
3186252726Srpaulo
3187252726Srpaulo	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3188252726Srpaulo		res[i] = os_strdup(wpa_cli_commands[i].cmd);
3189252726Srpaulo		if (res[i] == NULL)
3190252726Srpaulo			break;
3191252726Srpaulo	}
3192252726Srpaulo
3193281806Srpaulo	dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3194281806Srpaulo		size_t len = 8 + os_strlen(e->txt);
3195281806Srpaulo		res[i] = os_malloc(len);
3196281806Srpaulo		if (res[i] == NULL)
3197281806Srpaulo			break;
3198281806Srpaulo		os_snprintf(res[i], len, "ifname=%s", e->txt);
3199281806Srpaulo		i++;
3200281806Srpaulo	}
3201281806Srpaulo
3202281806Srpaulo	dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3203281806Srpaulo		res[i] = os_strdup(e->txt);
3204281806Srpaulo		if (res[i] == NULL)
3205281806Srpaulo			break;
3206281806Srpaulo		i++;
3207281806Srpaulo	}
3208281806Srpaulo
3209252726Srpaulo	return res;
3210252726Srpaulo}
3211252726Srpaulo
3212252726Srpaulo
3213252726Srpaulostatic char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3214252726Srpaulo				      int pos)
3215252726Srpaulo{
3216252726Srpaulo	int i;
3217252726Srpaulo
3218252726Srpaulo	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3219252726Srpaulo		if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3220252726Srpaulo			if (wpa_cli_commands[i].completion)
3221252726Srpaulo				return wpa_cli_commands[i].completion(str,
3222252726Srpaulo								      pos);
3223252726Srpaulo			edit_clear_line();
3224252726Srpaulo			printf("\r%s\n", wpa_cli_commands[i].usage);
3225252726Srpaulo			edit_redraw();
3226252726Srpaulo			break;
3227252726Srpaulo		}
3228252726Srpaulo	}
3229252726Srpaulo
3230252726Srpaulo	return NULL;
3231252726Srpaulo}
3232252726Srpaulo
3233252726Srpaulo
3234252726Srpaulostatic char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3235252726Srpaulo{
3236252726Srpaulo	char **res;
3237252726Srpaulo	const char *end;
3238252726Srpaulo	char *cmd;
3239252726Srpaulo
3240281806Srpaulo	if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3241281806Srpaulo		end = os_strchr(str, ' ');
3242281806Srpaulo		if (end && pos > end - str) {
3243281806Srpaulo			pos -= end - str + 1;
3244281806Srpaulo			str = end + 1;
3245281806Srpaulo		}
3246281806Srpaulo	}
3247281806Srpaulo
3248252726Srpaulo	end = os_strchr(str, ' ');
3249252726Srpaulo	if (end == NULL || str + pos < end)
3250252726Srpaulo		return wpa_list_cmd_list();
3251252726Srpaulo
3252252726Srpaulo	cmd = os_malloc(pos + 1);
3253252726Srpaulo	if (cmd == NULL)
3254252726Srpaulo		return NULL;
3255252726Srpaulo	os_memcpy(cmd, str, pos);
3256252726Srpaulo	cmd[end - str] = '\0';
3257252726Srpaulo	res = wpa_cli_cmd_completion(cmd, str, pos);
3258252726Srpaulo	os_free(cmd);
3259252726Srpaulo	return res;
3260252726Srpaulo}
3261252726Srpaulo
3262252726Srpaulo
3263189251Ssamstatic int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3264189251Ssam{
3265189251Ssam	struct wpa_cli_cmd *cmd, *match = NULL;
3266189251Ssam	int count;
3267189251Ssam	int ret = 0;
3268189251Ssam
3269281806Srpaulo	if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3270281806Srpaulo		ifname_prefix = argv[0] + 7;
3271281806Srpaulo		argv = &argv[1];
3272281806Srpaulo		argc--;
3273281806Srpaulo	} else
3274281806Srpaulo		ifname_prefix = NULL;
3275281806Srpaulo
3276281806Srpaulo	if (argc == 0)
3277281806Srpaulo		return -1;
3278281806Srpaulo
3279189251Ssam	count = 0;
3280189251Ssam	cmd = wpa_cli_commands;
3281189251Ssam	while (cmd->cmd) {
3282189251Ssam		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3283189251Ssam		{
3284189251Ssam			match = cmd;
3285189251Ssam			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3286189251Ssam				/* we have an exact match */
3287189251Ssam				count = 1;
3288189251Ssam				break;
3289189251Ssam			}
3290189251Ssam			count++;
3291189251Ssam		}
3292189251Ssam		cmd++;
3293189251Ssam	}
3294189251Ssam
3295189251Ssam	if (count > 1) {
3296189251Ssam		printf("Ambiguous command '%s'; possible commands:", argv[0]);
3297189251Ssam		cmd = wpa_cli_commands;
3298189251Ssam		while (cmd->cmd) {
3299189251Ssam			if (os_strncasecmp(cmd->cmd, argv[0],
3300189251Ssam					   os_strlen(argv[0])) == 0) {
3301189251Ssam				printf(" %s", cmd->cmd);
3302189251Ssam			}
3303189251Ssam			cmd++;
3304189251Ssam		}
3305189251Ssam		printf("\n");
3306189251Ssam		ret = 1;
3307189251Ssam	} else if (count == 0) {
3308189251Ssam		printf("Unknown command '%s'\n", argv[0]);
3309189251Ssam		ret = 1;
3310189251Ssam	} else {
3311189251Ssam		ret = match->handler(ctrl, argc - 1, &argv[1]);
3312189251Ssam	}
3313189251Ssam
3314189251Ssam	return ret;
3315189251Ssam}
3316189251Ssam
3317189251Ssam
3318189251Ssamstatic int str_match(const char *a, const char *b)
3319189251Ssam{
3320189251Ssam	return os_strncmp(a, b, os_strlen(b)) == 0;
3321189251Ssam}
3322189251Ssam
3323189251Ssam
3324189251Ssamstatic int wpa_cli_exec(const char *program, const char *arg1,
3325189251Ssam			const char *arg2)
3326189251Ssam{
3327281806Srpaulo	char *arg;
3328189251Ssam	size_t len;
3329189251Ssam	int res;
3330189251Ssam
3331281806Srpaulo	len = os_strlen(arg1) + os_strlen(arg2) + 2;
3332281806Srpaulo	arg = os_malloc(len);
3333281806Srpaulo	if (arg == NULL)
3334189251Ssam		return -1;
3335281806Srpaulo	os_snprintf(arg, len, "%s %s", arg1, arg2);
3336281806Srpaulo	res = os_exec(program, arg, 1);
3337281806Srpaulo	os_free(arg);
3338189251Ssam
3339281806Srpaulo	return res;
3340189251Ssam}
3341189251Ssam
3342189251Ssam
3343189251Ssamstatic void wpa_cli_action_process(const char *msg)
3344189251Ssam{
3345189251Ssam	const char *pos;
3346189251Ssam	char *copy = NULL, *id, *pos2;
3347281806Srpaulo	const char *ifname = ctrl_ifname;
3348281806Srpaulo	char ifname_buf[100];
3349189251Ssam
3350189251Ssam	pos = msg;
3351281806Srpaulo	if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3352281806Srpaulo		const char *end;
3353281806Srpaulo		end = os_strchr(pos + 7, ' ');
3354281806Srpaulo		if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3355281806Srpaulo			pos += 7;
3356281806Srpaulo			os_memcpy(ifname_buf, pos, end - pos);
3357281806Srpaulo			ifname_buf[end - pos] = '\0';
3358281806Srpaulo			ifname = ifname_buf;
3359281806Srpaulo			pos = end + 1;
3360281806Srpaulo		}
3361281806Srpaulo	}
3362189251Ssam	if (*pos == '<') {
3363281806Srpaulo		const char *prev = pos;
3364189251Ssam		/* skip priority */
3365189251Ssam		pos = os_strchr(pos, '>');
3366189251Ssam		if (pos)
3367189251Ssam			pos++;
3368189251Ssam		else
3369281806Srpaulo			pos = prev;
3370189251Ssam	}
3371189251Ssam
3372189251Ssam	if (str_match(pos, WPA_EVENT_CONNECTED)) {
3373189251Ssam		int new_id = -1;
3374189251Ssam		os_unsetenv("WPA_ID");
3375189251Ssam		os_unsetenv("WPA_ID_STR");
3376189251Ssam		os_unsetenv("WPA_CTRL_DIR");
3377189251Ssam
3378189251Ssam		pos = os_strstr(pos, "[id=");
3379189251Ssam		if (pos)
3380189251Ssam			copy = os_strdup(pos + 4);
3381189251Ssam
3382189251Ssam		if (copy) {
3383189251Ssam			pos2 = id = copy;
3384189251Ssam			while (*pos2 && *pos2 != ' ')
3385189251Ssam				pos2++;
3386189251Ssam			*pos2++ = '\0';
3387189251Ssam			new_id = atoi(id);
3388189251Ssam			os_setenv("WPA_ID", id, 1);
3389189251Ssam			while (*pos2 && *pos2 != '=')
3390189251Ssam				pos2++;
3391189251Ssam			if (*pos2 == '=')
3392189251Ssam				pos2++;
3393189251Ssam			id = pos2;
3394189251Ssam			while (*pos2 && *pos2 != ']')
3395189251Ssam				pos2++;
3396189251Ssam			*pos2 = '\0';
3397189251Ssam			os_setenv("WPA_ID_STR", id, 1);
3398189251Ssam			os_free(copy);
3399189251Ssam		}
3400189251Ssam
3401189251Ssam		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3402189251Ssam
3403281806Srpaulo		if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3404189251Ssam			wpa_cli_connected = 1;
3405189251Ssam			wpa_cli_last_id = new_id;
3406281806Srpaulo			wpa_cli_exec(action_file, ifname, "CONNECTED");
3407189251Ssam		}
3408189251Ssam	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3409189251Ssam		if (wpa_cli_connected) {
3410189251Ssam			wpa_cli_connected = 0;
3411281806Srpaulo			wpa_cli_exec(action_file, ifname, "DISCONNECTED");
3412189251Ssam		}
3413281806Srpaulo	} else if (str_match(pos, MESH_GROUP_STARTED)) {
3414281806Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
3415281806Srpaulo	} else if (str_match(pos, MESH_GROUP_REMOVED)) {
3416281806Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
3417281806Srpaulo	} else if (str_match(pos, MESH_PEER_CONNECTED)) {
3418281806Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
3419281806Srpaulo	} else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3420281806Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
3421252726Srpaulo	} else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3422281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3423252726Srpaulo	} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3424281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3425252726Srpaulo	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3426281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3427252726Srpaulo	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3428281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3429252726Srpaulo	} else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3430281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3431252726Srpaulo	} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3432281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3433252726Srpaulo	} else if (str_match(pos, WPS_EVENT_FAIL)) {
3434281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3435252726Srpaulo	} else if (str_match(pos, AP_STA_CONNECTED)) {
3436281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3437252726Srpaulo	} else if (str_match(pos, AP_STA_DISCONNECTED)) {
3438281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3439281806Srpaulo	} else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3440281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3441281806Srpaulo	} else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3442281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3443281806Srpaulo	} else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3444281806Srpaulo		wpa_cli_exec(action_file, ifname, pos);
3445189251Ssam	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3446189251Ssam		printf("wpa_supplicant is terminating - stop monitoring\n");
3447189251Ssam		wpa_cli_quit = 1;
3448189251Ssam	}
3449189251Ssam}
3450189251Ssam
3451189251Ssam
3452189251Ssam#ifndef CONFIG_ANSI_C_EXTRA
3453189251Ssamstatic void wpa_cli_action_cb(char *msg, size_t len)
3454189251Ssam{
3455189251Ssam	wpa_cli_action_process(msg);
3456189251Ssam}
3457189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */
3458189251Ssam
3459189251Ssam
3460189251Ssamstatic void wpa_cli_reconnect(void)
3461189251Ssam{
3462189251Ssam	wpa_cli_close_connection();
3463252726Srpaulo	if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3464252726Srpaulo		return;
3465252726Srpaulo
3466252726Srpaulo	if (interactive) {
3467252726Srpaulo		edit_clear_line();
3468252726Srpaulo		printf("\rConnection to wpa_supplicant re-established\n");
3469252726Srpaulo		edit_redraw();
3470252726Srpaulo	}
3471189251Ssam}
3472189251Ssam
3473189251Ssam
3474252726Srpaulostatic void cli_event(const char *str)
3475189251Ssam{
3476252726Srpaulo	const char *start, *s;
3477252726Srpaulo
3478252726Srpaulo	start = os_strchr(str, '>');
3479252726Srpaulo	if (start == NULL)
3480252726Srpaulo		return;
3481252726Srpaulo
3482252726Srpaulo	start++;
3483252726Srpaulo
3484252726Srpaulo	if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3485252726Srpaulo		s = os_strchr(start, ' ');
3486252726Srpaulo		if (s == NULL)
3487252726Srpaulo			return;
3488252726Srpaulo		s = os_strchr(s + 1, ' ');
3489252726Srpaulo		if (s == NULL)
3490252726Srpaulo			return;
3491252726Srpaulo		cli_txt_list_add(&bsses, s + 1);
3492252726Srpaulo		return;
3493252726Srpaulo	}
3494252726Srpaulo
3495252726Srpaulo	if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3496252726Srpaulo		s = os_strchr(start, ' ');
3497252726Srpaulo		if (s == NULL)
3498252726Srpaulo			return;
3499252726Srpaulo		s = os_strchr(s + 1, ' ');
3500252726Srpaulo		if (s == NULL)
3501252726Srpaulo			return;
3502252726Srpaulo		cli_txt_list_del_addr(&bsses, s + 1);
3503252726Srpaulo		return;
3504252726Srpaulo	}
3505252726Srpaulo
3506252726Srpaulo#ifdef CONFIG_P2P
3507252726Srpaulo	if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3508252726Srpaulo		s = os_strstr(start, " p2p_dev_addr=");
3509252726Srpaulo		if (s == NULL)
3510252726Srpaulo			return;
3511252726Srpaulo		cli_txt_list_add_addr(&p2p_peers, s + 14);
3512252726Srpaulo		return;
3513252726Srpaulo	}
3514252726Srpaulo
3515252726Srpaulo	if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3516252726Srpaulo		s = os_strstr(start, " p2p_dev_addr=");
3517252726Srpaulo		if (s == NULL)
3518252726Srpaulo			return;
3519252726Srpaulo		cli_txt_list_del_addr(&p2p_peers, s + 14);
3520252726Srpaulo		return;
3521252726Srpaulo	}
3522252726Srpaulo
3523252726Srpaulo	if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3524252726Srpaulo		s = os_strchr(start, ' ');
3525252726Srpaulo		if (s == NULL)
3526252726Srpaulo			return;
3527252726Srpaulo		cli_txt_list_add_word(&p2p_groups, s + 1);
3528252726Srpaulo		return;
3529252726Srpaulo	}
3530252726Srpaulo
3531252726Srpaulo	if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3532252726Srpaulo		s = os_strchr(start, ' ');
3533252726Srpaulo		if (s == NULL)
3534252726Srpaulo			return;
3535252726Srpaulo		cli_txt_list_del_word(&p2p_groups, s + 1);
3536252726Srpaulo		return;
3537252726Srpaulo	}
3538252726Srpaulo#endif /* CONFIG_P2P */
3539252726Srpaulo}
3540252726Srpaulo
3541252726Srpaulo
3542252726Srpaulostatic int check_terminating(const char *msg)
3543252726Srpaulo{
3544252726Srpaulo	const char *pos = msg;
3545252726Srpaulo
3546252726Srpaulo	if (*pos == '<') {
3547252726Srpaulo		/* skip priority */
3548252726Srpaulo		pos = os_strchr(pos, '>');
3549252726Srpaulo		if (pos)
3550252726Srpaulo			pos++;
3551252726Srpaulo		else
3552252726Srpaulo			pos = msg;
3553252726Srpaulo	}
3554252726Srpaulo
3555252726Srpaulo	if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3556252726Srpaulo		edit_clear_line();
3557252726Srpaulo		printf("\rConnection to wpa_supplicant lost - trying to "
3558252726Srpaulo		       "reconnect\n");
3559252726Srpaulo		edit_redraw();
3560252726Srpaulo		wpa_cli_attached = 0;
3561252726Srpaulo		wpa_cli_close_connection();
3562252726Srpaulo		return 1;
3563252726Srpaulo	}
3564252726Srpaulo
3565252726Srpaulo	return 0;
3566252726Srpaulo}
3567252726Srpaulo
3568252726Srpaulo
3569252726Srpaulostatic void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3570252726Srpaulo{
3571189251Ssam	if (ctrl_conn == NULL) {
3572189251Ssam		wpa_cli_reconnect();
3573189251Ssam		return;
3574189251Ssam	}
3575189251Ssam	while (wpa_ctrl_pending(ctrl) > 0) {
3576281806Srpaulo		char buf[4096];
3577189251Ssam		size_t len = sizeof(buf) - 1;
3578189251Ssam		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3579189251Ssam			buf[len] = '\0';
3580189251Ssam			if (action_monitor)
3581189251Ssam				wpa_cli_action_process(buf);
3582189251Ssam			else {
3583252726Srpaulo				cli_event(buf);
3584252726Srpaulo				if (wpa_cli_show_event(buf)) {
3585252726Srpaulo					edit_clear_line();
3586252726Srpaulo					printf("\r%s\n", buf);
3587252726Srpaulo					edit_redraw();
3588252726Srpaulo				}
3589252726Srpaulo
3590252726Srpaulo				if (interactive && check_terminating(buf) > 0)
3591252726Srpaulo					return;
3592189251Ssam			}
3593189251Ssam		} else {
3594189251Ssam			printf("Could not read pending message.\n");
3595189251Ssam			break;
3596189251Ssam		}
3597189251Ssam	}
3598189251Ssam
3599189251Ssam	if (wpa_ctrl_pending(ctrl) < 0) {
3600189251Ssam		printf("Connection to wpa_supplicant lost - trying to "
3601189251Ssam		       "reconnect\n");
3602189251Ssam		wpa_cli_reconnect();
3603189251Ssam	}
3604189251Ssam}
3605189251Ssam
3606252726Srpaulo#define max_args 10
3607189251Ssam
3608252726Srpaulostatic int tokenize_cmd(char *cmd, char *argv[])
3609189251Ssam{
3610252726Srpaulo	char *pos;
3611252726Srpaulo	int argc = 0;
3612189251Ssam
3613252726Srpaulo	pos = cmd;
3614252726Srpaulo	for (;;) {
3615252726Srpaulo		while (*pos == ' ')
3616252726Srpaulo			pos++;
3617252726Srpaulo		if (*pos == '\0')
3618252726Srpaulo			break;
3619252726Srpaulo		argv[argc] = pos;
3620252726Srpaulo		argc++;
3621252726Srpaulo		if (argc == max_args)
3622252726Srpaulo			break;
3623252726Srpaulo		if (*pos == '"') {
3624252726Srpaulo			char *pos2 = os_strrchr(pos, '"');
3625252726Srpaulo			if (pos2)
3626252726Srpaulo				pos = pos2 + 1;
3627252726Srpaulo		}
3628252726Srpaulo		while (*pos != '\0' && *pos != ' ')
3629252726Srpaulo			pos++;
3630252726Srpaulo		if (*pos == ' ')
3631252726Srpaulo			*pos++ = '\0';
3632189251Ssam	}
3633189251Ssam
3634252726Srpaulo	return argc;
3635189251Ssam}
3636189251Ssam
3637189251Ssam
3638252726Srpaulostatic void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3639189251Ssam{
3640281806Srpaulo	if (ctrl_conn) {
3641281806Srpaulo		int res;
3642281806Srpaulo		char *prefix = ifname_prefix;
3643281806Srpaulo
3644281806Srpaulo		ifname_prefix = NULL;
3645281806Srpaulo		res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3646281806Srpaulo		ifname_prefix = prefix;
3647281806Srpaulo		if (res) {
3648281806Srpaulo			printf("Connection to wpa_supplicant lost - trying to "
3649281806Srpaulo			       "reconnect\n");
3650281806Srpaulo			wpa_cli_close_connection();
3651281806Srpaulo		}
3652214734Srpaulo	}
3653252726Srpaulo	if (!ctrl_conn)
3654252726Srpaulo		wpa_cli_reconnect();
3655252726Srpaulo	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3656189251Ssam}
3657189251Ssam
3658189251Ssam
3659252726Srpaulostatic void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3660214734Srpaulo{
3661252726Srpaulo	wpa_cli_recv_pending(mon_conn, 0);
3662252726Srpaulo}
3663214734Srpaulo
3664214734Srpaulo
3665252726Srpaulostatic void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3666252726Srpaulo{
3667252726Srpaulo	char *argv[max_args];
3668252726Srpaulo	int argc;
3669252726Srpaulo	argc = tokenize_cmd(cmd, argv);
3670252726Srpaulo	if (argc)
3671252726Srpaulo		wpa_request(ctrl_conn, argc, argv);
3672214734Srpaulo}
3673214734Srpaulo
3674214734Srpaulo
3675252726Srpaulostatic void wpa_cli_edit_eof_cb(void *ctx)
3676189251Ssam{
3677252726Srpaulo	eloop_terminate();
3678189251Ssam}
3679189251Ssam
3680189251Ssam
3681252726Srpaulostatic int warning_displayed = 0;
3682252726Srpaulostatic char *hfile = NULL;
3683252726Srpaulostatic int edit_started = 0;
3684252726Srpaulo
3685252726Srpaulostatic void start_edit(void)
3686189251Ssam{
3687252726Srpaulo	char *home;
3688252726Srpaulo	char *ps = NULL;
3689189251Ssam
3690252726Srpaulo#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3691252726Srpaulo	ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3692252726Srpaulo#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3693189251Ssam
3694189251Ssam	home = getenv("HOME");
3695189251Ssam	if (home) {
3696189251Ssam		const char *fname = ".wpa_cli_history";
3697189251Ssam		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3698189251Ssam		hfile = os_malloc(hfile_len);
3699252726Srpaulo		if (hfile)
3700252726Srpaulo			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3701189251Ssam	}
3702189251Ssam
3703252726Srpaulo	if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3704252726Srpaulo		      wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3705252726Srpaulo		eloop_terminate();
3706252726Srpaulo		return;
3707252726Srpaulo	}
3708189251Ssam
3709252726Srpaulo	edit_started = 1;
3710252726Srpaulo	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3711252726Srpaulo}
3712189251Ssam
3713252726Srpaulo
3714281806Srpaulostatic void update_bssid_list(struct wpa_ctrl *ctrl)
3715281806Srpaulo{
3716281806Srpaulo	char buf[4096];
3717281806Srpaulo	size_t len = sizeof(buf);
3718281806Srpaulo	int ret;
3719281806Srpaulo	char *cmd = "BSS RANGE=ALL MASK=0x2";
3720281806Srpaulo	char *pos, *end;
3721281806Srpaulo
3722281806Srpaulo	if (ctrl == NULL)
3723281806Srpaulo		return;
3724281806Srpaulo	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3725281806Srpaulo	if (ret < 0)
3726281806Srpaulo		return;
3727281806Srpaulo	buf[len] = '\0';
3728281806Srpaulo
3729281806Srpaulo	pos = buf;
3730281806Srpaulo	while (pos) {
3731281806Srpaulo		pos = os_strstr(pos, "bssid=");
3732281806Srpaulo		if (pos == NULL)
3733281806Srpaulo			break;
3734281806Srpaulo		pos += 6;
3735281806Srpaulo		end = os_strchr(pos, '\n');
3736281806Srpaulo		if (end == NULL)
3737281806Srpaulo			break;
3738281806Srpaulo		*end = '\0';
3739281806Srpaulo		cli_txt_list_add(&bsses, pos);
3740281806Srpaulo		pos = end + 1;
3741281806Srpaulo	}
3742281806Srpaulo}
3743281806Srpaulo
3744281806Srpaulo
3745281806Srpaulostatic void update_ifnames(struct wpa_ctrl *ctrl)
3746281806Srpaulo{
3747281806Srpaulo	char buf[4096];
3748281806Srpaulo	size_t len = sizeof(buf);
3749281806Srpaulo	int ret;
3750281806Srpaulo	char *cmd = "INTERFACES";
3751281806Srpaulo	char *pos, *end;
3752281806Srpaulo	char txt[200];
3753281806Srpaulo
3754281806Srpaulo	cli_txt_list_flush(&ifnames);
3755281806Srpaulo
3756281806Srpaulo	if (ctrl == NULL)
3757281806Srpaulo		return;
3758281806Srpaulo	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3759281806Srpaulo	if (ret < 0)
3760281806Srpaulo		return;
3761281806Srpaulo	buf[len] = '\0';
3762281806Srpaulo
3763281806Srpaulo	pos = buf;
3764281806Srpaulo	while (pos) {
3765281806Srpaulo		end = os_strchr(pos, '\n');
3766281806Srpaulo		if (end == NULL)
3767281806Srpaulo			break;
3768281806Srpaulo		*end = '\0';
3769281806Srpaulo		ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3770281806Srpaulo		if (!os_snprintf_error(sizeof(txt), ret))
3771281806Srpaulo			cli_txt_list_add(&ifnames, txt);
3772281806Srpaulo		pos = end + 1;
3773281806Srpaulo	}
3774281806Srpaulo}
3775281806Srpaulo
3776281806Srpaulo
3777252726Srpaulostatic void try_connection(void *eloop_ctx, void *timeout_ctx)
3778252726Srpaulo{
3779281806Srpaulo	if (ctrl_conn)
3780281806Srpaulo		goto done;
3781281806Srpaulo
3782252726Srpaulo	if (ctrl_ifname == NULL)
3783252726Srpaulo		ctrl_ifname = wpa_cli_get_default_ifname();
3784252726Srpaulo
3785252726Srpaulo	if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3786252726Srpaulo		if (!warning_displayed) {
3787252726Srpaulo			printf("Could not connect to wpa_supplicant: "
3788281806Srpaulo			       "%s - re-trying\n",
3789281806Srpaulo			       ctrl_ifname ? ctrl_ifname : "(nil)");
3790252726Srpaulo			warning_displayed = 1;
3791189251Ssam		}
3792252726Srpaulo		eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3793252726Srpaulo		return;
3794189251Ssam	}
3795252726Srpaulo
3796281806Srpaulo	update_bssid_list(ctrl_conn);
3797281806Srpaulo
3798252726Srpaulo	if (warning_displayed)
3799252726Srpaulo		printf("Connection established.\n");
3800252726Srpaulo
3801281806Srpaulodone:
3802252726Srpaulo	start_edit();
3803189251Ssam}
3804189251Ssam
3805189251Ssam
3806252726Srpaulostatic void wpa_cli_interactive(void)
3807252726Srpaulo{
3808252726Srpaulo	printf("\nInteractive mode\n\n");
3809252726Srpaulo
3810252726Srpaulo	eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3811252726Srpaulo	eloop_run();
3812252726Srpaulo	eloop_cancel_timeout(try_connection, NULL, NULL);
3813252726Srpaulo
3814252726Srpaulo	cli_txt_list_flush(&p2p_peers);
3815252726Srpaulo	cli_txt_list_flush(&p2p_groups);
3816252726Srpaulo	cli_txt_list_flush(&bsses);
3817281806Srpaulo	cli_txt_list_flush(&ifnames);
3818252726Srpaulo	if (edit_started)
3819252726Srpaulo		edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3820252726Srpaulo	os_free(hfile);
3821252726Srpaulo	eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3822252726Srpaulo	wpa_cli_close_connection();
3823252726Srpaulo}
3824252726Srpaulo
3825252726Srpaulo
3826189251Ssamstatic void wpa_cli_action(struct wpa_ctrl *ctrl)
3827189251Ssam{
3828189251Ssam#ifdef CONFIG_ANSI_C_EXTRA
3829189251Ssam	/* TODO: ANSI C version(?) */
3830189251Ssam	printf("Action processing not supported in ANSI C build.\n");
3831189251Ssam#else /* CONFIG_ANSI_C_EXTRA */
3832189251Ssam	fd_set rfds;
3833189251Ssam	int fd, res;
3834189251Ssam	struct timeval tv;
3835189251Ssam	char buf[256]; /* note: large enough to fit in unsolicited messages */
3836189251Ssam	size_t len;
3837189251Ssam
3838189251Ssam	fd = wpa_ctrl_get_fd(ctrl);
3839189251Ssam
3840189251Ssam	while (!wpa_cli_quit) {
3841189251Ssam		FD_ZERO(&rfds);
3842189251Ssam		FD_SET(fd, &rfds);
3843189251Ssam		tv.tv_sec = ping_interval;
3844189251Ssam		tv.tv_usec = 0;
3845189251Ssam		res = select(fd + 1, &rfds, NULL, NULL, &tv);
3846189251Ssam		if (res < 0 && errno != EINTR) {
3847189251Ssam			perror("select");
3848189251Ssam			break;
3849189251Ssam		}
3850189251Ssam
3851189251Ssam		if (FD_ISSET(fd, &rfds))
3852252726Srpaulo			wpa_cli_recv_pending(ctrl, 1);
3853189251Ssam		else {
3854189251Ssam			/* verify that connection is still working */
3855189251Ssam			len = sizeof(buf) - 1;
3856189251Ssam			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3857189251Ssam					     wpa_cli_action_cb) < 0 ||
3858189251Ssam			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3859189251Ssam				printf("wpa_supplicant did not reply to PING "
3860189251Ssam				       "command - exiting\n");
3861189251Ssam				break;
3862189251Ssam			}
3863189251Ssam		}
3864189251Ssam	}
3865189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */
3866189251Ssam}
3867189251Ssam
3868189251Ssam
3869189251Ssamstatic void wpa_cli_cleanup(void)
3870189251Ssam{
3871189251Ssam	wpa_cli_close_connection();
3872189251Ssam	if (pid_file)
3873189251Ssam		os_daemonize_terminate(pid_file);
3874189251Ssam
3875189251Ssam	os_program_deinit();
3876189251Ssam}
3877189251Ssam
3878189251Ssam
3879252726Srpaulostatic void wpa_cli_terminate(int sig, void *ctx)
3880214734Srpaulo{
3881252726Srpaulo	eloop_terminate();
3882214734Srpaulo}
3883214734Srpaulo
3884214734Srpaulo
3885189251Ssamstatic char * wpa_cli_get_default_ifname(void)
3886189251Ssam{
3887189251Ssam	char *ifname = NULL;
3888189251Ssam
3889189251Ssam#ifdef CONFIG_CTRL_IFACE_UNIX
3890189251Ssam	struct dirent *dent;
3891189251Ssam	DIR *dir = opendir(ctrl_iface_dir);
3892252726Srpaulo	if (!dir) {
3893252726Srpaulo#ifdef ANDROID
3894252726Srpaulo		char ifprop[PROPERTY_VALUE_MAX];
3895252726Srpaulo		if (property_get("wifi.interface", ifprop, NULL) != 0) {
3896252726Srpaulo			ifname = os_strdup(ifprop);
3897252726Srpaulo			printf("Using interface '%s'\n", ifname);
3898252726Srpaulo			return ifname;
3899252726Srpaulo		}
3900252726Srpaulo#endif /* ANDROID */
3901189251Ssam		return NULL;
3902252726Srpaulo	}
3903189251Ssam	while ((dent = readdir(dir))) {
3904189251Ssam#ifdef _DIRENT_HAVE_D_TYPE
3905189251Ssam		/*
3906189251Ssam		 * Skip the file if it is not a socket. Also accept
3907189251Ssam		 * DT_UNKNOWN (0) in case the C library or underlying
3908189251Ssam		 * file system does not support d_type.
3909189251Ssam		 */
3910189251Ssam		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3911189251Ssam			continue;
3912189251Ssam#endif /* _DIRENT_HAVE_D_TYPE */
3913189251Ssam		if (os_strcmp(dent->d_name, ".") == 0 ||
3914189251Ssam		    os_strcmp(dent->d_name, "..") == 0)
3915189251Ssam			continue;
3916189251Ssam		printf("Selected interface '%s'\n", dent->d_name);
3917189251Ssam		ifname = os_strdup(dent->d_name);
3918189251Ssam		break;
3919189251Ssam	}
3920189251Ssam	closedir(dir);
3921189251Ssam#endif /* CONFIG_CTRL_IFACE_UNIX */
3922189251Ssam
3923189251Ssam#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3924281806Srpaulo	char buf[4096], *pos;
3925189251Ssam	size_t len;
3926189251Ssam	struct wpa_ctrl *ctrl;
3927189251Ssam	int ret;
3928189251Ssam
3929189251Ssam	ctrl = wpa_ctrl_open(NULL);
3930189251Ssam	if (ctrl == NULL)
3931189251Ssam		return NULL;
3932189251Ssam
3933189251Ssam	len = sizeof(buf) - 1;
3934189251Ssam	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3935189251Ssam	if (ret >= 0) {
3936189251Ssam		buf[len] = '\0';
3937189251Ssam		pos = os_strchr(buf, '\n');
3938189251Ssam		if (pos)
3939189251Ssam			*pos = '\0';
3940189251Ssam		ifname = os_strdup(buf);
3941189251Ssam	}
3942189251Ssam	wpa_ctrl_close(ctrl);
3943189251Ssam#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3944189251Ssam
3945189251Ssam	return ifname;
3946189251Ssam}
3947189251Ssam
3948189251Ssam
3949189251Ssamint main(int argc, char *argv[])
3950189251Ssam{
3951189251Ssam	int c;
3952189251Ssam	int daemonize = 0;
3953189251Ssam	int ret = 0;
3954189251Ssam	const char *global = NULL;
3955189251Ssam
3956189251Ssam	if (os_program_init())
3957189251Ssam		return -1;
3958189251Ssam
3959189251Ssam	for (;;) {
3960189251Ssam		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3961189251Ssam		if (c < 0)
3962189251Ssam			break;
3963189251Ssam		switch (c) {
3964189251Ssam		case 'a':
3965189251Ssam			action_file = optarg;
3966189251Ssam			break;
3967189251Ssam		case 'B':
3968189251Ssam			daemonize = 1;
3969189251Ssam			break;
3970189251Ssam		case 'g':
3971189251Ssam			global = optarg;
3972189251Ssam			break;
3973189251Ssam		case 'G':
3974189251Ssam			ping_interval = atoi(optarg);
3975189251Ssam			break;
3976189251Ssam		case 'h':
3977189251Ssam			usage();
3978189251Ssam			return 0;
3979189251Ssam		case 'v':
3980189251Ssam			printf("%s\n", wpa_cli_version);
3981189251Ssam			return 0;
3982189251Ssam		case 'i':
3983189251Ssam			os_free(ctrl_ifname);
3984189251Ssam			ctrl_ifname = os_strdup(optarg);
3985189251Ssam			break;
3986189251Ssam		case 'p':
3987189251Ssam			ctrl_iface_dir = optarg;
3988189251Ssam			break;
3989189251Ssam		case 'P':
3990189251Ssam			pid_file = optarg;
3991189251Ssam			break;
3992189251Ssam		default:
3993189251Ssam			usage();
3994189251Ssam			return -1;
3995189251Ssam		}
3996189251Ssam	}
3997189251Ssam
3998189251Ssam	interactive = (argc == optind) && (action_file == NULL);
3999189251Ssam
4000189251Ssam	if (interactive)
4001189251Ssam		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4002189251Ssam
4003252726Srpaulo	if (eloop_init())
4004252726Srpaulo		return -1;
4005252726Srpaulo
4006189251Ssam	if (global) {
4007189251Ssam#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4008189251Ssam		ctrl_conn = wpa_ctrl_open(NULL);
4009189251Ssam#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4010189251Ssam		ctrl_conn = wpa_ctrl_open(global);
4011189251Ssam#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4012189251Ssam		if (ctrl_conn == NULL) {
4013252726Srpaulo			fprintf(stderr, "Failed to connect to wpa_supplicant "
4014252726Srpaulo				"global interface: %s  error: %s\n",
4015252726Srpaulo				global, strerror(errno));
4016189251Ssam			return -1;
4017189251Ssam		}
4018281806Srpaulo
4019281806Srpaulo		if (interactive) {
4020281806Srpaulo			update_ifnames(ctrl_conn);
4021281806Srpaulo			mon_conn = wpa_ctrl_open(global);
4022281806Srpaulo			if (mon_conn) {
4023281806Srpaulo				if (wpa_ctrl_attach(mon_conn) == 0) {
4024281806Srpaulo					wpa_cli_attached = 1;
4025281806Srpaulo					eloop_register_read_sock(
4026281806Srpaulo						wpa_ctrl_get_fd(mon_conn),
4027281806Srpaulo						wpa_cli_mon_receive,
4028281806Srpaulo						NULL, NULL);
4029281806Srpaulo				} else {
4030281806Srpaulo					printf("Failed to open monitor "
4031281806Srpaulo					       "connection through global "
4032281806Srpaulo					       "control interface\n");
4033281806Srpaulo				}
4034281806Srpaulo			}
4035281806Srpaulo		}
4036189251Ssam	}
4037189251Ssam
4038252726Srpaulo	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
4039189251Ssam
4040214734Srpaulo	if (ctrl_ifname == NULL)
4041214734Srpaulo		ctrl_ifname = wpa_cli_get_default_ifname();
4042214734Srpaulo
4043214734Srpaulo	if (interactive) {
4044252726Srpaulo		wpa_cli_interactive();
4045214734Srpaulo	} else {
4046214734Srpaulo		if (!global &&
4047214734Srpaulo		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4048252726Srpaulo			fprintf(stderr, "Failed to connect to non-global "
4049252726Srpaulo				"ctrl_ifname: %s  error: %s\n",
4050281806Srpaulo				ctrl_ifname ? ctrl_ifname : "(nil)",
4051281806Srpaulo				strerror(errno));
4052214734Srpaulo			return -1;
4053214734Srpaulo		}
4054214734Srpaulo
4055214734Srpaulo		if (action_file) {
4056214734Srpaulo			if (wpa_ctrl_attach(ctrl_conn) == 0) {
4057214734Srpaulo				wpa_cli_attached = 1;
4058214734Srpaulo			} else {
4059214734Srpaulo				printf("Warning: Failed to attach to "
4060214734Srpaulo				       "wpa_supplicant.\n");
4061189251Ssam				return -1;
4062214734Srpaulo			}
4063189251Ssam		}
4064189251Ssam
4065252726Srpaulo		if (daemonize && os_daemonize(pid_file))
4066252726Srpaulo			return -1;
4067189251Ssam
4068252726Srpaulo		if (action_file)
4069252726Srpaulo			wpa_cli_action(ctrl_conn);
4070252726Srpaulo		else
4071252726Srpaulo			ret = wpa_request(ctrl_conn, argc - optind,
4072252726Srpaulo					  &argv[optind]);
4073252726Srpaulo	}
4074189251Ssam
4075189251Ssam	os_free(ctrl_ifname);
4076252726Srpaulo	eloop_destroy();
4077189251Ssam	wpa_cli_cleanup();
4078189251Ssam
4079189251Ssam	return ret;
4080189251Ssam}
4081189251Ssam
4082189251Ssam#else /* CONFIG_CTRL_IFACE */
4083189251Ssamint main(int argc, char *argv[])
4084189251Ssam{
4085189251Ssam	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4086189251Ssam	return -1;
4087189251Ssam}
4088189251Ssam#endif /* CONFIG_CTRL_IFACE */
4089