wpa_cli.c revision 252726
1189251Ssam/*
2189251Ssam * WPA Supplicant - command line interface for wpa_supplicant daemon
3252726Srpaulo * Copyright (c) 2004-2012, 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"
31252726Srpaulo"Copyright (c) 2004-2012, 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;
73189251Ssamstatic int wpa_cli_connected = 0;
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;
84189251Ssam
85252726Srpaulostruct cli_txt_entry {
86252726Srpaulo	struct dl_list list;
87252726Srpaulo	char *txt;
88252726Srpaulo};
89189251Ssam
90252726Srpaulostatic DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
91252726Srpaulostatic DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
92252726Srpaulostatic DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
93189251Ssam
94189251Ssam
95252726Srpaulostatic void print_help(const char *cmd);
96252726Srpaulostatic void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
97252726Srpaulostatic void wpa_cli_close_connection(void);
98252726Srpaulostatic char * wpa_cli_get_default_ifname(void);
99252726Srpaulostatic char ** wpa_list_cmd_list(void);
100252726Srpaulo
101252726Srpaulo
102189251Ssamstatic void usage(void)
103189251Ssam{
104189251Ssam	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
105189251Ssam	       "[-a<action file>] \\\n"
106189251Ssam	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  "
107189251Ssam	       "[command..]\n"
108189251Ssam	       "  -h = help (show this usage text)\n"
109189251Ssam	       "  -v = shown version information\n"
110189251Ssam	       "  -a = run in daemon mode executing the action file based on "
111189251Ssam	       "events from\n"
112189251Ssam	       "       wpa_supplicant\n"
113189251Ssam	       "  -B = run a daemon in the background\n"
114252726Srpaulo	       "  default path: " CONFIG_CTRL_IFACE_DIR "\n"
115189251Ssam	       "  default interface: first interface found in socket path\n");
116252726Srpaulo	print_help(NULL);
117189251Ssam}
118189251Ssam
119189251Ssam
120252726Srpaulostatic void cli_txt_list_free(struct cli_txt_entry *e)
121252726Srpaulo{
122252726Srpaulo	dl_list_del(&e->list);
123252726Srpaulo	os_free(e->txt);
124252726Srpaulo	os_free(e);
125252726Srpaulo}
126214734Srpaulo
127252726Srpaulo
128252726Srpaulostatic void cli_txt_list_flush(struct dl_list *list)
129189251Ssam{
130252726Srpaulo	struct cli_txt_entry *e;
131252726Srpaulo	while ((e = dl_list_first(list, struct cli_txt_entry, list)))
132252726Srpaulo		cli_txt_list_free(e);
133214734Srpaulo}
134214734Srpaulo
135252726Srpaulo
136252726Srpaulostatic struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
137252726Srpaulo					       const char *txt)
138214734Srpaulo{
139252726Srpaulo	struct cli_txt_entry *e;
140252726Srpaulo	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
141252726Srpaulo		if (os_strcmp(e->txt, txt) == 0)
142252726Srpaulo			return e;
143252726Srpaulo	}
144252726Srpaulo	return NULL;
145252726Srpaulo}
146214734Srpaulo
147214734Srpaulo
148252726Srpaulostatic void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
149252726Srpaulo{
150252726Srpaulo	struct cli_txt_entry *e;
151252726Srpaulo	e = cli_txt_list_get(txt_list, txt);
152252726Srpaulo	if (e)
153252726Srpaulo		cli_txt_list_free(e);
154252726Srpaulo}
155252726Srpaulo
156252726Srpaulo
157252726Srpaulostatic void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
158252726Srpaulo{
159252726Srpaulo	u8 addr[ETH_ALEN];
160252726Srpaulo	char buf[18];
161252726Srpaulo	if (hwaddr_aton(txt, addr) < 0)
162252726Srpaulo		return;
163252726Srpaulo	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
164252726Srpaulo	cli_txt_list_del(txt_list, buf);
165252726Srpaulo}
166252726Srpaulo
167252726Srpaulo
168252726Srpaulo#ifdef CONFIG_P2P
169252726Srpaulostatic void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
170252726Srpaulo{
171252726Srpaulo	const char *end;
172252726Srpaulo	char *buf;
173252726Srpaulo	end = os_strchr(txt, ' ');
174252726Srpaulo	if (end == NULL)
175252726Srpaulo		end = txt + os_strlen(txt);
176252726Srpaulo	buf = os_malloc(end - txt + 1);
177252726Srpaulo	if (buf == NULL)
178252726Srpaulo		return;
179252726Srpaulo	os_memcpy(buf, txt, end - txt);
180252726Srpaulo	buf[end - txt] = '\0';
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);
226252726Srpaulo	buf = os_malloc(end - txt + 1);
227252726Srpaulo	if (buf == NULL)
228252726Srpaulo		return -1;
229252726Srpaulo	os_memcpy(buf, txt, end - txt);
230252726Srpaulo	buf[end - txt] = '\0';
231252726Srpaulo	ret = cli_txt_list_add(txt_list, buf);
232252726Srpaulo	os_free(buf);
233252726Srpaulo	return ret;
234252726Srpaulo}
235252726Srpaulo#endif /* CONFIG_P2P */
236252726Srpaulo
237252726Srpaulo
238252726Srpaulostatic char ** cli_txt_list_array(struct dl_list *txt_list)
239252726Srpaulo{
240252726Srpaulo	unsigned int i, count = dl_list_len(txt_list);
241252726Srpaulo	char **res;
242252726Srpaulo	struct cli_txt_entry *e;
243252726Srpaulo
244252726Srpaulo	res = os_calloc(count + 1, sizeof(char *));
245252726Srpaulo	if (res == NULL)
246252726Srpaulo		return NULL;
247252726Srpaulo
248252726Srpaulo	i = 0;
249252726Srpaulo	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
250252726Srpaulo		res[i] = os_strdup(e->txt);
251252726Srpaulo		if (res[i] == NULL)
252214734Srpaulo			break;
253252726Srpaulo		i++;
254252726Srpaulo	}
255252726Srpaulo
256252726Srpaulo	return res;
257252726Srpaulo}
258252726Srpaulo
259252726Srpaulo
260252726Srpaulostatic int get_cmd_arg_num(const char *str, int pos)
261252726Srpaulo{
262252726Srpaulo	int arg = 0, i;
263252726Srpaulo
264252726Srpaulo	for (i = 0; i <= pos; i++) {
265252726Srpaulo		if (str[i] != ' ') {
266252726Srpaulo			arg++;
267252726Srpaulo			while (i <= pos && str[i] != ' ')
268252726Srpaulo				i++;
269214734Srpaulo		}
270214734Srpaulo	}
271252726Srpaulo
272252726Srpaulo	if (arg > 0)
273252726Srpaulo		arg--;
274252726Srpaulo	return arg;
275214734Srpaulo}
276214734Srpaulo
277214734Srpaulo
278252726Srpaulostatic int str_starts(const char *src, const char *match)
279252726Srpaulo{
280252726Srpaulo	return os_strncmp(src, match, os_strlen(match)) == 0;
281252726Srpaulo}
282252726Srpaulo
283252726Srpaulo
284252726Srpaulostatic int wpa_cli_show_event(const char *event)
285252726Srpaulo{
286252726Srpaulo	const char *start;
287252726Srpaulo
288252726Srpaulo	start = os_strchr(event, '>');
289252726Srpaulo	if (start == NULL)
290252726Srpaulo		return 1;
291252726Srpaulo
292252726Srpaulo	start++;
293252726Srpaulo	/*
294252726Srpaulo	 * Skip BSS added/removed events since they can be relatively frequent
295252726Srpaulo	 * and are likely of not much use for an interactive user.
296252726Srpaulo	 */
297252726Srpaulo	if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
298252726Srpaulo	    str_starts(start, WPA_EVENT_BSS_REMOVED))
299252726Srpaulo		return 0;
300252726Srpaulo
301252726Srpaulo	return 1;
302252726Srpaulo}
303252726Srpaulo
304252726Srpaulo
305214734Srpaulostatic int wpa_cli_open_connection(const char *ifname, int attach)
306214734Srpaulo{
307189251Ssam#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
308189251Ssam	ctrl_conn = wpa_ctrl_open(ifname);
309214734Srpaulo	if (ctrl_conn == NULL)
310214734Srpaulo		return -1;
311214734Srpaulo
312214734Srpaulo	if (attach && interactive)
313214734Srpaulo		mon_conn = wpa_ctrl_open(ifname);
314214734Srpaulo	else
315214734Srpaulo		mon_conn = NULL;
316189251Ssam#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
317252726Srpaulo	char *cfile = NULL;
318189251Ssam	int flen, res;
319189251Ssam
320189251Ssam	if (ifname == NULL)
321214734Srpaulo		return -1;
322189251Ssam
323252726Srpaulo#ifdef ANDROID
324252726Srpaulo	if (access(ctrl_iface_dir, F_OK) < 0) {
325252726Srpaulo		cfile = os_strdup(ifname);
326252726Srpaulo		if (cfile == NULL)
327252726Srpaulo			return -1;
328189251Ssam	}
329252726Srpaulo#endif /* ANDROID */
330189251Ssam
331252726Srpaulo	if (cfile == NULL) {
332252726Srpaulo		flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
333252726Srpaulo		cfile = os_malloc(flen);
334252726Srpaulo		if (cfile == NULL)
335252726Srpaulo			return -1;
336252726Srpaulo		res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
337252726Srpaulo				  ifname);
338252726Srpaulo		if (res < 0 || res >= flen) {
339252726Srpaulo			os_free(cfile);
340252726Srpaulo			return -1;
341252726Srpaulo		}
342252726Srpaulo	}
343252726Srpaulo
344189251Ssam	ctrl_conn = wpa_ctrl_open(cfile);
345214734Srpaulo	if (ctrl_conn == NULL) {
346214734Srpaulo		os_free(cfile);
347214734Srpaulo		return -1;
348214734Srpaulo	}
349214734Srpaulo
350214734Srpaulo	if (attach && interactive)
351214734Srpaulo		mon_conn = wpa_ctrl_open(cfile);
352214734Srpaulo	else
353214734Srpaulo		mon_conn = NULL;
354189251Ssam	os_free(cfile);
355189251Ssam#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
356214734Srpaulo
357214734Srpaulo	if (mon_conn) {
358214734Srpaulo		if (wpa_ctrl_attach(mon_conn) == 0) {
359214734Srpaulo			wpa_cli_attached = 1;
360252726Srpaulo			if (interactive)
361252726Srpaulo				eloop_register_read_sock(
362252726Srpaulo					wpa_ctrl_get_fd(mon_conn),
363252726Srpaulo					wpa_cli_mon_receive, NULL, NULL);
364214734Srpaulo		} else {
365214734Srpaulo			printf("Warning: Failed to attach to "
366214734Srpaulo			       "wpa_supplicant.\n");
367252726Srpaulo			wpa_cli_close_connection();
368214734Srpaulo			return -1;
369214734Srpaulo		}
370214734Srpaulo	}
371214734Srpaulo
372214734Srpaulo	return 0;
373189251Ssam}
374189251Ssam
375189251Ssam
376189251Ssamstatic void wpa_cli_close_connection(void)
377189251Ssam{
378189251Ssam	if (ctrl_conn == NULL)
379189251Ssam		return;
380189251Ssam
381189251Ssam	if (wpa_cli_attached) {
382214734Srpaulo		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
383189251Ssam		wpa_cli_attached = 0;
384189251Ssam	}
385189251Ssam	wpa_ctrl_close(ctrl_conn);
386189251Ssam	ctrl_conn = NULL;
387214734Srpaulo	if (mon_conn) {
388252726Srpaulo		eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
389214734Srpaulo		wpa_ctrl_close(mon_conn);
390214734Srpaulo		mon_conn = NULL;
391214734Srpaulo	}
392189251Ssam}
393189251Ssam
394189251Ssam
395189251Ssamstatic void wpa_cli_msg_cb(char *msg, size_t len)
396189251Ssam{
397189251Ssam	printf("%s\n", msg);
398189251Ssam}
399189251Ssam
400189251Ssam
401189251Ssamstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
402189251Ssam{
403189251Ssam	char buf[2048];
404189251Ssam	size_t len;
405189251Ssam	int ret;
406189251Ssam
407189251Ssam	if (ctrl_conn == NULL) {
408189251Ssam		printf("Not connected to wpa_supplicant - command dropped.\n");
409189251Ssam		return -1;
410189251Ssam	}
411189251Ssam	len = sizeof(buf) - 1;
412189251Ssam	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
413189251Ssam			       wpa_cli_msg_cb);
414189251Ssam	if (ret == -2) {
415189251Ssam		printf("'%s' command timed out.\n", cmd);
416189251Ssam		return -2;
417189251Ssam	} else if (ret < 0) {
418189251Ssam		printf("'%s' command failed.\n", cmd);
419189251Ssam		return -1;
420189251Ssam	}
421189251Ssam	if (print) {
422189251Ssam		buf[len] = '\0';
423189251Ssam		printf("%s", buf);
424252726Srpaulo		if (interactive && len > 0 && buf[len - 1] != '\n')
425252726Srpaulo			printf("\n");
426189251Ssam	}
427189251Ssam	return 0;
428189251Ssam}
429189251Ssam
430189251Ssam
431189251Ssamstatic int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
432189251Ssam{
433189251Ssam	return _wpa_ctrl_command(ctrl, cmd, 1);
434189251Ssam}
435189251Ssam
436189251Ssam
437252726Srpaulostatic int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
438252726Srpaulo		     char *argv[])
439252726Srpaulo{
440252726Srpaulo	int i, res;
441252726Srpaulo	char *pos, *end;
442252726Srpaulo
443252726Srpaulo	pos = buf;
444252726Srpaulo	end = buf + buflen;
445252726Srpaulo
446252726Srpaulo	res = os_snprintf(pos, end - pos, "%s", cmd);
447252726Srpaulo	if (res < 0 || res >= end - pos)
448252726Srpaulo		goto fail;
449252726Srpaulo	pos += res;
450252726Srpaulo
451252726Srpaulo	for (i = 0; i < argc; i++) {
452252726Srpaulo		res = os_snprintf(pos, end - pos, " %s", argv[i]);
453252726Srpaulo		if (res < 0 || res >= end - pos)
454252726Srpaulo			goto fail;
455252726Srpaulo		pos += res;
456252726Srpaulo	}
457252726Srpaulo
458252726Srpaulo	buf[buflen - 1] = '\0';
459252726Srpaulo	return 0;
460252726Srpaulo
461252726Srpaulofail:
462252726Srpaulo	printf("Too long command\n");
463252726Srpaulo	return -1;
464252726Srpaulo}
465252726Srpaulo
466252726Srpaulo
467252726Srpaulostatic int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
468252726Srpaulo		       int argc, char *argv[])
469252726Srpaulo{
470252726Srpaulo	char buf[256];
471252726Srpaulo	if (argc < min_args) {
472252726Srpaulo		printf("Invalid %s command - at least %d argument%s "
473252726Srpaulo		       "required.\n", cmd, min_args,
474252726Srpaulo		       min_args > 1 ? "s are" : " is");
475252726Srpaulo		return -1;
476252726Srpaulo	}
477252726Srpaulo	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
478252726Srpaulo		return -1;
479252726Srpaulo	return wpa_ctrl_command(ctrl, buf);
480252726Srpaulo}
481252726Srpaulo
482252726Srpaulo
483252726Srpaulostatic int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
484252726Srpaulo{
485252726Srpaulo	return wpa_ctrl_command(ctrl, "IFNAME");
486252726Srpaulo}
487252726Srpaulo
488252726Srpaulo
489189251Ssamstatic int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
490189251Ssam{
491252726Srpaulo	if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
492252726Srpaulo		return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
493252726Srpaulo	if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
494252726Srpaulo		return wpa_ctrl_command(ctrl, "STATUS-WPS");
495252726Srpaulo	return wpa_ctrl_command(ctrl, "STATUS");
496189251Ssam}
497189251Ssam
498189251Ssam
499189251Ssamstatic int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
500189251Ssam{
501189251Ssam	return wpa_ctrl_command(ctrl, "PING");
502189251Ssam}
503189251Ssam
504189251Ssam
505252726Srpaulostatic int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
506252726Srpaulo{
507252726Srpaulo	return wpa_ctrl_command(ctrl, "RELOG");
508252726Srpaulo}
509252726Srpaulo
510252726Srpaulo
511252726Srpaulostatic int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
512252726Srpaulo{
513252726Srpaulo	return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
514252726Srpaulo}
515252726Srpaulo
516252726Srpaulo
517189251Ssamstatic int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
518189251Ssam{
519189251Ssam	return wpa_ctrl_command(ctrl, "MIB");
520189251Ssam}
521189251Ssam
522189251Ssam
523189251Ssamstatic int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
524189251Ssam{
525189251Ssam	return wpa_ctrl_command(ctrl, "PMKSA");
526189251Ssam}
527189251Ssam
528189251Ssam
529189251Ssamstatic int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
530189251Ssam{
531252726Srpaulo	print_help(argc > 0 ? argv[0] : NULL);
532189251Ssam	return 0;
533189251Ssam}
534189251Ssam
535189251Ssam
536252726Srpaulostatic char ** wpa_cli_complete_help(const char *str, int pos)
537252726Srpaulo{
538252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
539252726Srpaulo	char **res = NULL;
540252726Srpaulo
541252726Srpaulo	switch (arg) {
542252726Srpaulo	case 1:
543252726Srpaulo		res = wpa_list_cmd_list();
544252726Srpaulo		break;
545252726Srpaulo	}
546252726Srpaulo
547252726Srpaulo	return res;
548252726Srpaulo}
549252726Srpaulo
550252726Srpaulo
551189251Ssamstatic int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
552189251Ssam{
553189251Ssam	printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
554189251Ssam	return 0;
555189251Ssam}
556189251Ssam
557189251Ssam
558189251Ssamstatic int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
559189251Ssam{
560189251Ssam	wpa_cli_quit = 1;
561252726Srpaulo	if (interactive)
562252726Srpaulo		eloop_terminate();
563189251Ssam	return 0;
564189251Ssam}
565189251Ssam
566189251Ssam
567189251Ssamstatic void wpa_cli_show_variables(void)
568189251Ssam{
569189251Ssam	printf("set variables:\n"
570189251Ssam	       "  EAPOL::heldPeriod (EAPOL state machine held period, "
571189251Ssam	       "in seconds)\n"
572189251Ssam	       "  EAPOL::authPeriod (EAPOL state machine authentication "
573189251Ssam	       "period, in seconds)\n"
574189251Ssam	       "  EAPOL::startPeriod (EAPOL state machine start period, in "
575189251Ssam	       "seconds)\n"
576189251Ssam	       "  EAPOL::maxStart (EAPOL state machine maximum start "
577189251Ssam	       "attempts)\n");
578189251Ssam	printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
579189251Ssam	       "seconds)\n"
580189251Ssam	       "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
581189251Ssam	       " threshold\n\tpercentage)\n"
582189251Ssam	       "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
583189251Ssam	       "security\n\tassociation in seconds)\n");
584189251Ssam}
585189251Ssam
586189251Ssam
587189251Ssamstatic int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
588189251Ssam{
589189251Ssam	char cmd[256];
590189251Ssam	int res;
591189251Ssam
592189251Ssam	if (argc == 0) {
593189251Ssam		wpa_cli_show_variables();
594189251Ssam		return 0;
595189251Ssam	}
596189251Ssam
597252726Srpaulo	if (argc != 1 && argc != 2) {
598189251Ssam		printf("Invalid SET command: needs two arguments (variable "
599189251Ssam		       "name and value)\n");
600189251Ssam		return -1;
601189251Ssam	}
602189251Ssam
603252726Srpaulo	if (argc == 1)
604252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
605252726Srpaulo	else
606252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
607252726Srpaulo				  argv[0], argv[1]);
608189251Ssam	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
609189251Ssam		printf("Too long SET command.\n");
610189251Ssam		return -1;
611189251Ssam	}
612189251Ssam	return wpa_ctrl_command(ctrl, cmd);
613189251Ssam}
614189251Ssam
615189251Ssam
616252726Srpaulostatic int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
617252726Srpaulo{
618252726Srpaulo	return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
619252726Srpaulo}
620252726Srpaulo
621252726Srpaulo
622189251Ssamstatic int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
623189251Ssam{
624189251Ssam	return wpa_ctrl_command(ctrl, "LOGOFF");
625189251Ssam}
626189251Ssam
627189251Ssam
628189251Ssamstatic int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
629189251Ssam{
630189251Ssam	return wpa_ctrl_command(ctrl, "LOGON");
631189251Ssam}
632189251Ssam
633189251Ssam
634189251Ssamstatic int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
635189251Ssam				   char *argv[])
636189251Ssam{
637189251Ssam	return wpa_ctrl_command(ctrl, "REASSOCIATE");
638189251Ssam}
639189251Ssam
640189251Ssam
641189251Ssamstatic int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
642189251Ssam				       char *argv[])
643189251Ssam{
644252726Srpaulo	return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
645252726Srpaulo}
646189251Ssam
647189251Ssam
648252726Srpaulostatic int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
649252726Srpaulo{
650252726Srpaulo	return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
651189251Ssam}
652189251Ssam
653189251Ssam
654252726Srpaulostatic int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
655252726Srpaulo				     char *argv[])
656189251Ssam{
657252726Srpaulo	return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
658252726Srpaulo}
659252726Srpaulo
660252726Srpaulo
661252726Srpaulostatic int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
662252726Srpaulo				      char *argv[])
663252726Srpaulo{
664252726Srpaulo	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
665252726Srpaulo}
666252726Srpaulo
667252726Srpaulo
668252726Srpaulostatic int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
669252726Srpaulo				        char *argv[])
670252726Srpaulo{
671252726Srpaulo	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
672252726Srpaulo}
673252726Srpaulo
674252726Srpaulo
675252726Srpaulostatic int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
676252726Srpaulo{
677189251Ssam	char cmd[256];
678189251Ssam	int res;
679189251Ssam
680252726Srpaulo	if (argc < 1)
681252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
682252726Srpaulo	else
683252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
684189251Ssam	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
685252726Srpaulo		printf("Too long BSS_FLUSH command.\n");
686189251Ssam		return -1;
687189251Ssam	}
688189251Ssam	return wpa_ctrl_command(ctrl, cmd);
689189251Ssam}
690189251Ssam
691189251Ssam
692189251Ssamstatic int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
693189251Ssam				char *argv[])
694189251Ssam{
695252726Srpaulo	return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
696252726Srpaulo}
697189251Ssam
698252726Srpaulo
699252726Srpaulostatic int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
700252726Srpaulo{
701252726Srpaulo	return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
702252726Srpaulo}
703252726Srpaulo
704252726Srpaulo
705252726Srpaulostatic int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
706252726Srpaulo{
707252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
708252726Srpaulo}
709252726Srpaulo
710252726Srpaulo
711252726Srpaulostatic int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
712252726Srpaulo{
713252726Srpaulo	if (argc == 0) {
714252726Srpaulo		printf("Invalid WPS_PIN command: need one or two arguments:\n"
715252726Srpaulo		       "- BSSID: use 'any' to select any\n"
716252726Srpaulo		       "- PIN: optional, used only with devices that have no "
717252726Srpaulo		       "display\n");
718189251Ssam		return -1;
719189251Ssam	}
720189251Ssam
721252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
722189251Ssam}
723189251Ssam
724189251Ssam
725252726Srpaulostatic int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
726252726Srpaulo				     char *argv[])
727189251Ssam{
728252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
729252726Srpaulo}
730189251Ssam
731252726Srpaulo
732252726Srpaulostatic int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
733252726Srpaulo				  char *argv[])
734252726Srpaulo{
735252726Srpaulo	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
736252726Srpaulo}
737252726Srpaulo
738252726Srpaulo
739252726Srpaulo#ifdef CONFIG_WPS_NFC
740252726Srpaulo
741252726Srpaulostatic int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
742252726Srpaulo{
743252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
744252726Srpaulo}
745252726Srpaulo
746252726Srpaulo
747252726Srpaulostatic int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
748252726Srpaulo				     char *argv[])
749252726Srpaulo{
750252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
751252726Srpaulo}
752252726Srpaulo
753252726Srpaulo
754252726Srpaulostatic int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
755252726Srpaulo					char *argv[])
756252726Srpaulo{
757252726Srpaulo	int ret;
758252726Srpaulo	char *buf;
759252726Srpaulo	size_t buflen;
760252726Srpaulo
761189251Ssam	if (argc != 1) {
762252726Srpaulo		printf("Invalid 'wps_nfc_tag_read' command - one argument "
763252726Srpaulo		       "is required.\n");
764189251Ssam		return -1;
765189251Ssam	}
766189251Ssam
767252726Srpaulo	buflen = 18 + os_strlen(argv[0]);
768252726Srpaulo	buf = os_malloc(buflen);
769252726Srpaulo	if (buf == NULL)
770189251Ssam		return -1;
771252726Srpaulo	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
772252726Srpaulo
773252726Srpaulo	ret = wpa_ctrl_command(ctrl, buf);
774252726Srpaulo	os_free(buf);
775252726Srpaulo
776252726Srpaulo	return ret;
777189251Ssam}
778189251Ssam
779189251Ssam
780252726Srpaulostatic int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
781252726Srpaulo					    char *argv[])
782189251Ssam{
783252726Srpaulo	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
784252726Srpaulo}
785189251Ssam
786189251Ssam
787252726Srpaulostatic int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
788252726Srpaulo					    char *argv[])
789252726Srpaulo{
790252726Srpaulo	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
791189251Ssam}
792189251Ssam
793189251Ssam
794252726Srpaulostatic int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
795252726Srpaulo					   char *argv[])
796189251Ssam{
797252726Srpaulo	int ret;
798252726Srpaulo	char *buf;
799252726Srpaulo	size_t buflen;
800189251Ssam
801252726Srpaulo	if (argc != 1) {
802252726Srpaulo		printf("Invalid 'nfc_rx_handover_req' command - one argument "
803252726Srpaulo		       "is required.\n");
804189251Ssam		return -1;
805189251Ssam	}
806189251Ssam
807252726Srpaulo	buflen = 21 + os_strlen(argv[0]);
808252726Srpaulo	buf = os_malloc(buflen);
809252726Srpaulo	if (buf == NULL)
810252726Srpaulo		return -1;
811252726Srpaulo	os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
812189251Ssam
813252726Srpaulo	ret = wpa_ctrl_command(ctrl, buf);
814252726Srpaulo	os_free(buf);
815252726Srpaulo
816252726Srpaulo	return ret;
817189251Ssam}
818189251Ssam
819189251Ssam
820252726Srpaulostatic int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
821252726Srpaulo					   char *argv[])
822214734Srpaulo{
823252726Srpaulo	int ret;
824252726Srpaulo	char *buf;
825252726Srpaulo	size_t buflen;
826214734Srpaulo
827252726Srpaulo	if (argc != 1) {
828252726Srpaulo		printf("Invalid 'nfc_rx_handover_sel' command - one argument "
829252726Srpaulo		       "is required.\n");
830214734Srpaulo		return -1;
831214734Srpaulo	}
832214734Srpaulo
833252726Srpaulo	buflen = 21 + os_strlen(argv[0]);
834252726Srpaulo	buf = os_malloc(buflen);
835252726Srpaulo	if (buf == NULL)
836214734Srpaulo		return -1;
837252726Srpaulo	os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
838252726Srpaulo
839252726Srpaulo	ret = wpa_ctrl_command(ctrl, buf);
840252726Srpaulo	os_free(buf);
841252726Srpaulo
842252726Srpaulo	return ret;
843214734Srpaulo}
844214734Srpaulo
845252726Srpaulo#endif /* CONFIG_WPS_NFC */
846214734Srpaulo
847252726Srpaulo
848189251Ssamstatic int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
849189251Ssam{
850189251Ssam	char cmd[256];
851189251Ssam	int res;
852189251Ssam
853214734Srpaulo	if (argc == 2)
854214734Srpaulo		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
855214734Srpaulo				  argv[0], argv[1]);
856252726Srpaulo	else if (argc == 5 || argc == 6) {
857214734Srpaulo		char ssid_hex[2 * 32 + 1];
858214734Srpaulo		char key_hex[2 * 64 + 1];
859214734Srpaulo		int i;
860214734Srpaulo
861214734Srpaulo		ssid_hex[0] = '\0';
862214734Srpaulo		for (i = 0; i < 32; i++) {
863214734Srpaulo			if (argv[2][i] == '\0')
864214734Srpaulo				break;
865214734Srpaulo			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
866214734Srpaulo		}
867214734Srpaulo
868214734Srpaulo		key_hex[0] = '\0';
869252726Srpaulo		if (argc == 6) {
870252726Srpaulo			for (i = 0; i < 64; i++) {
871252726Srpaulo				if (argv[5][i] == '\0')
872252726Srpaulo					break;
873252726Srpaulo				os_snprintf(&key_hex[i * 2], 3, "%02x",
874252726Srpaulo					    argv[5][i]);
875252726Srpaulo			}
876214734Srpaulo		}
877214734Srpaulo
878214734Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
879214734Srpaulo				  "WPS_REG %s %s %s %s %s %s",
880214734Srpaulo				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
881214734Srpaulo				  key_hex);
882214734Srpaulo	} else {
883189251Ssam		printf("Invalid WPS_REG command: need two arguments:\n"
884252726Srpaulo		       "- BSSID of the target AP\n"
885189251Ssam		       "- AP PIN\n");
886214734Srpaulo		printf("Alternatively, six arguments can be used to "
887214734Srpaulo		       "reconfigure the AP:\n"
888252726Srpaulo		       "- BSSID of the target AP\n"
889214734Srpaulo		       "- AP PIN\n"
890214734Srpaulo		       "- new SSID\n"
891214734Srpaulo		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
892214734Srpaulo		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
893214734Srpaulo		       "- new key\n");
894189251Ssam		return -1;
895189251Ssam	}
896189251Ssam
897189251Ssam	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
898189251Ssam		printf("Too long WPS_REG command.\n");
899189251Ssam		return -1;
900189251Ssam	}
901189251Ssam	return wpa_ctrl_command(ctrl, cmd);
902189251Ssam}
903189251Ssam
904189251Ssam
905252726Srpaulostatic int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
906252726Srpaulo				  char *argv[])
907252726Srpaulo{
908252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
909252726Srpaulo}
910252726Srpaulo
911252726Srpaulo
912214734Srpaulostatic int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
913214734Srpaulo				    char *argv[])
914214734Srpaulo{
915252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
916214734Srpaulo}
917214734Srpaulo
918214734Srpaulo
919214734Srpaulostatic int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
920214734Srpaulo				   char *argv[])
921214734Srpaulo{
922214734Srpaulo	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
923214734Srpaulo
924214734Srpaulo}
925214734Srpaulo
926214734Srpaulo
927214734Srpaulostatic int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
928214734Srpaulo				  char *argv[])
929214734Srpaulo{
930252726Srpaulo	if (argc < 2) {
931252726Srpaulo		printf("Invalid WPS_ER_PIN command: need at least two "
932252726Srpaulo		       "arguments:\n"
933214734Srpaulo		       "- UUID: use 'any' to select any\n"
934252726Srpaulo		       "- PIN: Enrollee PIN\n"
935252726Srpaulo		       "optional: - Enrollee MAC address\n");
936214734Srpaulo		return -1;
937214734Srpaulo	}
938214734Srpaulo
939252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
940214734Srpaulo}
941214734Srpaulo
942214734Srpaulo
943214734Srpaulostatic int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
944214734Srpaulo				  char *argv[])
945214734Srpaulo{
946252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
947214734Srpaulo}
948214734Srpaulo
949214734Srpaulo
950214734Srpaulostatic int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
951214734Srpaulo				    char *argv[])
952214734Srpaulo{
953214734Srpaulo	if (argc != 2) {
954214734Srpaulo		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
955214734Srpaulo		       "- UUID: specify which AP to use\n"
956214734Srpaulo		       "- PIN: AP PIN\n");
957214734Srpaulo		return -1;
958214734Srpaulo	}
959214734Srpaulo
960252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
961252726Srpaulo}
962252726Srpaulo
963252726Srpaulo
964252726Srpaulostatic int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
965252726Srpaulo					 char *argv[])
966252726Srpaulo{
967252726Srpaulo	if (argc != 2) {
968252726Srpaulo		printf("Invalid WPS_ER_SET_CONFIG command: need two "
969252726Srpaulo		       "arguments:\n"
970252726Srpaulo		       "- UUID: specify which AP to use\n"
971252726Srpaulo		       "- Network configuration id\n");
972214734Srpaulo		return -1;
973214734Srpaulo	}
974252726Srpaulo
975252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
976214734Srpaulo}
977214734Srpaulo
978214734Srpaulo
979252726Srpaulostatic int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
980252726Srpaulo				     char *argv[])
981214734Srpaulo{
982214734Srpaulo	char cmd[256];
983214734Srpaulo	int res;
984214734Srpaulo
985252726Srpaulo	if (argc == 5 || argc == 6) {
986252726Srpaulo		char ssid_hex[2 * 32 + 1];
987252726Srpaulo		char key_hex[2 * 64 + 1];
988252726Srpaulo		int i;
989252726Srpaulo
990252726Srpaulo		ssid_hex[0] = '\0';
991252726Srpaulo		for (i = 0; i < 32; i++) {
992252726Srpaulo			if (argv[2][i] == '\0')
993252726Srpaulo				break;
994252726Srpaulo			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
995252726Srpaulo		}
996252726Srpaulo
997252726Srpaulo		key_hex[0] = '\0';
998252726Srpaulo		if (argc == 6) {
999252726Srpaulo			for (i = 0; i < 64; i++) {
1000252726Srpaulo				if (argv[5][i] == '\0')
1001252726Srpaulo					break;
1002252726Srpaulo				os_snprintf(&key_hex[i * 2], 3, "%02x",
1003252726Srpaulo					    argv[5][i]);
1004252726Srpaulo			}
1005252726Srpaulo		}
1006252726Srpaulo
1007252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
1008252726Srpaulo				  "WPS_ER_CONFIG %s %s %s %s %s %s",
1009252726Srpaulo				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
1010252726Srpaulo				  key_hex);
1011252726Srpaulo	} else {
1012252726Srpaulo		printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1013252726Srpaulo		       "- AP UUID\n"
1014252726Srpaulo		       "- AP PIN\n"
1015252726Srpaulo		       "- new SSID\n"
1016252726Srpaulo		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1017252726Srpaulo		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
1018252726Srpaulo		       "- new key\n");
1019214734Srpaulo		return -1;
1020214734Srpaulo	}
1021214734Srpaulo
1022214734Srpaulo	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1023252726Srpaulo		printf("Too long WPS_ER_CONFIG command.\n");
1024214734Srpaulo		return -1;
1025214734Srpaulo	}
1026214734Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1027214734Srpaulo}
1028214734Srpaulo
1029214734Srpaulo
1030252726Srpaulo#ifdef CONFIG_WPS_NFC
1031252726Srpaulostatic int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1032252726Srpaulo					       char *argv[])
1033189251Ssam{
1034252726Srpaulo	if (argc != 2) {
1035252726Srpaulo		printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1036252726Srpaulo		       "arguments:\n"
1037252726Srpaulo		       "- WPS/NDEF: token format\n"
1038252726Srpaulo		       "- UUID: specify which AP to use\n");
1039189251Ssam		return -1;
1040189251Ssam	}
1041252726Srpaulo
1042252726Srpaulo	return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1043189251Ssam}
1044252726Srpaulo#endif /* CONFIG_WPS_NFC */
1045189251Ssam
1046189251Ssam
1047252726Srpaulostatic int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1048252726Srpaulo{
1049252726Srpaulo	return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
1050252726Srpaulo}
1051252726Srpaulo
1052252726Srpaulo
1053252726Srpaulostatic int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1054252726Srpaulo{
1055252726Srpaulo	return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
1056252726Srpaulo}
1057252726Srpaulo
1058252726Srpaulo
1059189251Ssamstatic int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1060189251Ssam{
1061189251Ssam	char cmd[256], *pos, *end;
1062189251Ssam	int i, ret;
1063189251Ssam
1064189251Ssam	if (argc < 2) {
1065189251Ssam		printf("Invalid IDENTITY command: needs two arguments "
1066189251Ssam		       "(network id and identity)\n");
1067189251Ssam		return -1;
1068189251Ssam	}
1069189251Ssam
1070189251Ssam	end = cmd + sizeof(cmd);
1071189251Ssam	pos = cmd;
1072189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1073189251Ssam			  argv[0], argv[1]);
1074189251Ssam	if (ret < 0 || ret >= end - pos) {
1075189251Ssam		printf("Too long IDENTITY command.\n");
1076189251Ssam		return -1;
1077189251Ssam	}
1078189251Ssam	pos += ret;
1079189251Ssam	for (i = 2; i < argc; i++) {
1080189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1081189251Ssam		if (ret < 0 || ret >= end - pos) {
1082189251Ssam			printf("Too long IDENTITY command.\n");
1083189251Ssam			return -1;
1084189251Ssam		}
1085189251Ssam		pos += ret;
1086189251Ssam	}
1087189251Ssam
1088189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1089189251Ssam}
1090189251Ssam
1091189251Ssam
1092189251Ssamstatic int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1093189251Ssam{
1094189251Ssam	char cmd[256], *pos, *end;
1095189251Ssam	int i, ret;
1096189251Ssam
1097189251Ssam	if (argc < 2) {
1098189251Ssam		printf("Invalid PASSWORD command: needs two arguments "
1099189251Ssam		       "(network id and password)\n");
1100189251Ssam		return -1;
1101189251Ssam	}
1102189251Ssam
1103189251Ssam	end = cmd + sizeof(cmd);
1104189251Ssam	pos = cmd;
1105189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1106189251Ssam			  argv[0], argv[1]);
1107189251Ssam	if (ret < 0 || ret >= end - pos) {
1108189251Ssam		printf("Too long PASSWORD command.\n");
1109189251Ssam		return -1;
1110189251Ssam	}
1111189251Ssam	pos += ret;
1112189251Ssam	for (i = 2; i < argc; i++) {
1113189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1114189251Ssam		if (ret < 0 || ret >= end - pos) {
1115189251Ssam			printf("Too long PASSWORD command.\n");
1116189251Ssam			return -1;
1117189251Ssam		}
1118189251Ssam		pos += ret;
1119189251Ssam	}
1120189251Ssam
1121189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1122189251Ssam}
1123189251Ssam
1124189251Ssam
1125189251Ssamstatic int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1126189251Ssam				    char *argv[])
1127189251Ssam{
1128189251Ssam	char cmd[256], *pos, *end;
1129189251Ssam	int i, ret;
1130189251Ssam
1131189251Ssam	if (argc < 2) {
1132189251Ssam		printf("Invalid NEW_PASSWORD command: needs two arguments "
1133189251Ssam		       "(network id and password)\n");
1134189251Ssam		return -1;
1135189251Ssam	}
1136189251Ssam
1137189251Ssam	end = cmd + sizeof(cmd);
1138189251Ssam	pos = cmd;
1139189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1140189251Ssam			  argv[0], argv[1]);
1141189251Ssam	if (ret < 0 || ret >= end - pos) {
1142189251Ssam		printf("Too long NEW_PASSWORD command.\n");
1143189251Ssam		return -1;
1144189251Ssam	}
1145189251Ssam	pos += ret;
1146189251Ssam	for (i = 2; i < argc; i++) {
1147189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1148189251Ssam		if (ret < 0 || ret >= end - pos) {
1149189251Ssam			printf("Too long NEW_PASSWORD command.\n");
1150189251Ssam			return -1;
1151189251Ssam		}
1152189251Ssam		pos += ret;
1153189251Ssam	}
1154189251Ssam
1155189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1156189251Ssam}
1157189251Ssam
1158189251Ssam
1159189251Ssamstatic int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1160189251Ssam{
1161189251Ssam	char cmd[256], *pos, *end;
1162189251Ssam	int i, ret;
1163189251Ssam
1164189251Ssam	if (argc < 2) {
1165189251Ssam		printf("Invalid PIN command: needs two arguments "
1166189251Ssam		       "(network id and pin)\n");
1167189251Ssam		return -1;
1168189251Ssam	}
1169189251Ssam
1170189251Ssam	end = cmd + sizeof(cmd);
1171189251Ssam	pos = cmd;
1172189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1173189251Ssam			  argv[0], argv[1]);
1174189251Ssam	if (ret < 0 || ret >= end - pos) {
1175189251Ssam		printf("Too long PIN command.\n");
1176189251Ssam		return -1;
1177189251Ssam	}
1178189251Ssam	pos += ret;
1179189251Ssam	for (i = 2; i < argc; i++) {
1180189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1181189251Ssam		if (ret < 0 || ret >= end - pos) {
1182189251Ssam			printf("Too long PIN command.\n");
1183189251Ssam			return -1;
1184189251Ssam		}
1185189251Ssam		pos += ret;
1186189251Ssam	}
1187189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1188189251Ssam}
1189189251Ssam
1190189251Ssam
1191189251Ssamstatic int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1192189251Ssam{
1193189251Ssam	char cmd[256], *pos, *end;
1194189251Ssam	int i, ret;
1195189251Ssam
1196189251Ssam	if (argc < 2) {
1197189251Ssam		printf("Invalid OTP command: needs two arguments (network "
1198189251Ssam		       "id and password)\n");
1199189251Ssam		return -1;
1200189251Ssam	}
1201189251Ssam
1202189251Ssam	end = cmd + sizeof(cmd);
1203189251Ssam	pos = cmd;
1204189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1205189251Ssam			  argv[0], argv[1]);
1206189251Ssam	if (ret < 0 || ret >= end - pos) {
1207189251Ssam		printf("Too long OTP command.\n");
1208189251Ssam		return -1;
1209189251Ssam	}
1210189251Ssam	pos += ret;
1211189251Ssam	for (i = 2; i < argc; i++) {
1212189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1213189251Ssam		if (ret < 0 || ret >= end - pos) {
1214189251Ssam			printf("Too long OTP command.\n");
1215189251Ssam			return -1;
1216189251Ssam		}
1217189251Ssam		pos += ret;
1218189251Ssam	}
1219189251Ssam
1220189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1221189251Ssam}
1222189251Ssam
1223189251Ssam
1224189251Ssamstatic int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1225189251Ssam				  char *argv[])
1226189251Ssam{
1227189251Ssam	char cmd[256], *pos, *end;
1228189251Ssam	int i, ret;
1229189251Ssam
1230189251Ssam	if (argc < 2) {
1231189251Ssam		printf("Invalid PASSPHRASE command: needs two arguments "
1232189251Ssam		       "(network id and passphrase)\n");
1233189251Ssam		return -1;
1234189251Ssam	}
1235189251Ssam
1236189251Ssam	end = cmd + sizeof(cmd);
1237189251Ssam	pos = cmd;
1238189251Ssam	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1239189251Ssam			  argv[0], argv[1]);
1240189251Ssam	if (ret < 0 || ret >= end - pos) {
1241189251Ssam		printf("Too long PASSPHRASE command.\n");
1242189251Ssam		return -1;
1243189251Ssam	}
1244189251Ssam	pos += ret;
1245189251Ssam	for (i = 2; i < argc; i++) {
1246189251Ssam		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1247189251Ssam		if (ret < 0 || ret >= end - pos) {
1248189251Ssam			printf("Too long PASSPHRASE command.\n");
1249189251Ssam			return -1;
1250189251Ssam		}
1251189251Ssam		pos += ret;
1252189251Ssam	}
1253189251Ssam
1254189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1255189251Ssam}
1256189251Ssam
1257189251Ssam
1258189251Ssamstatic int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1259189251Ssam{
1260189251Ssam	if (argc < 2) {
1261189251Ssam		printf("Invalid BSSID command: needs two arguments (network "
1262189251Ssam		       "id and BSSID)\n");
1263189251Ssam		return -1;
1264189251Ssam	}
1265189251Ssam
1266252726Srpaulo	return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
1267252726Srpaulo}
1268189251Ssam
1269252726Srpaulo
1270252726Srpaulostatic int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1271252726Srpaulo{
1272252726Srpaulo	return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1273189251Ssam}
1274189251Ssam
1275189251Ssam
1276252726Srpaulostatic int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1277252726Srpaulo{
1278252726Srpaulo	return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
1279252726Srpaulo}
1280252726Srpaulo
1281252726Srpaulo
1282189251Ssamstatic int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1283189251Ssam				     char *argv[])
1284189251Ssam{
1285189251Ssam	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1286189251Ssam}
1287189251Ssam
1288189251Ssam
1289189251Ssamstatic int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1290189251Ssam				      char *argv[])
1291189251Ssam{
1292252726Srpaulo	return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
1293189251Ssam}
1294189251Ssam
1295189251Ssam
1296189251Ssamstatic int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1297189251Ssam				      char *argv[])
1298189251Ssam{
1299252726Srpaulo	return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
1300189251Ssam}
1301189251Ssam
1302189251Ssam
1303189251Ssamstatic int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1304189251Ssam				       char *argv[])
1305189251Ssam{
1306252726Srpaulo	return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
1307189251Ssam}
1308189251Ssam
1309189251Ssam
1310189251Ssamstatic int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1311189251Ssam				   char *argv[])
1312189251Ssam{
1313189251Ssam	return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1314189251Ssam}
1315189251Ssam
1316189251Ssam
1317189251Ssamstatic int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1318189251Ssam				      char *argv[])
1319189251Ssam{
1320252726Srpaulo	return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1321189251Ssam}
1322189251Ssam
1323189251Ssam
1324189251Ssamstatic void wpa_cli_show_network_variables(void)
1325189251Ssam{
1326189251Ssam	printf("set_network variables:\n"
1327189251Ssam	       "  ssid (network name, SSID)\n"
1328189251Ssam	       "  psk (WPA passphrase or pre-shared key)\n"
1329189251Ssam	       "  key_mgmt (key management protocol)\n"
1330189251Ssam	       "  identity (EAP identity)\n"
1331189251Ssam	       "  password (EAP password)\n"
1332189251Ssam	       "  ...\n"
1333189251Ssam	       "\n"
1334189251Ssam	       "Note: Values are entered in the same format as the "
1335189251Ssam	       "configuration file is using,\n"
1336189251Ssam	       "i.e., strings values need to be inside double quotation "
1337189251Ssam	       "marks.\n"
1338189251Ssam	       "For example: set_network 1 ssid \"network name\"\n"
1339189251Ssam	       "\n"
1340189251Ssam	       "Please see wpa_supplicant.conf documentation for full list "
1341189251Ssam	       "of\navailable variables.\n");
1342189251Ssam}
1343189251Ssam
1344189251Ssam
1345189251Ssamstatic int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1346189251Ssam				   char *argv[])
1347189251Ssam{
1348189251Ssam	if (argc == 0) {
1349189251Ssam		wpa_cli_show_network_variables();
1350189251Ssam		return 0;
1351189251Ssam	}
1352189251Ssam
1353252726Srpaulo	if (argc < 3) {
1354189251Ssam		printf("Invalid SET_NETWORK command: needs three arguments\n"
1355189251Ssam		       "(network id, variable name, and value)\n");
1356189251Ssam		return -1;
1357189251Ssam	}
1358189251Ssam
1359252726Srpaulo	return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
1360189251Ssam}
1361189251Ssam
1362189251Ssam
1363189251Ssamstatic int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1364189251Ssam				   char *argv[])
1365189251Ssam{
1366189251Ssam	if (argc == 0) {
1367189251Ssam		wpa_cli_show_network_variables();
1368189251Ssam		return 0;
1369189251Ssam	}
1370189251Ssam
1371189251Ssam	if (argc != 2) {
1372189251Ssam		printf("Invalid GET_NETWORK command: needs two arguments\n"
1373189251Ssam		       "(network id and variable name)\n");
1374189251Ssam		return -1;
1375189251Ssam	}
1376189251Ssam
1377252726Srpaulo	return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1378252726Srpaulo}
1379252726Srpaulo
1380252726Srpaulo
1381252726Srpaulostatic int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1382252726Srpaulo				  char *argv[])
1383252726Srpaulo{
1384252726Srpaulo	return wpa_ctrl_command(ctrl, "LIST_CREDS");
1385252726Srpaulo}
1386252726Srpaulo
1387252726Srpaulo
1388252726Srpaulostatic int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1389252726Srpaulo{
1390252726Srpaulo	return wpa_ctrl_command(ctrl, "ADD_CRED");
1391252726Srpaulo}
1392252726Srpaulo
1393252726Srpaulo
1394252726Srpaulostatic int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1395252726Srpaulo				   char *argv[])
1396252726Srpaulo{
1397252726Srpaulo	return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1398252726Srpaulo}
1399252726Srpaulo
1400252726Srpaulo
1401252726Srpaulostatic int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1402252726Srpaulo{
1403252726Srpaulo	if (argc != 3) {
1404252726Srpaulo		printf("Invalid SET_CRED command: needs three arguments\n"
1405252726Srpaulo		       "(cred id, variable name, and value)\n");
1406189251Ssam		return -1;
1407189251Ssam	}
1408252726Srpaulo
1409252726Srpaulo	return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
1410189251Ssam}
1411189251Ssam
1412189251Ssam
1413189251Ssamstatic int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1414189251Ssam				  char *argv[])
1415189251Ssam{
1416189251Ssam	return wpa_ctrl_command(ctrl, "DISCONNECT");
1417189251Ssam}
1418189251Ssam
1419189251Ssam
1420189251Ssamstatic int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1421189251Ssam				  char *argv[])
1422189251Ssam{
1423189251Ssam	return wpa_ctrl_command(ctrl, "RECONNECT");
1424189251Ssam}
1425189251Ssam
1426189251Ssam
1427189251Ssamstatic int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1428189251Ssam				   char *argv[])
1429189251Ssam{
1430189251Ssam	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1431189251Ssam}
1432189251Ssam
1433189251Ssam
1434189251Ssamstatic int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1435189251Ssam{
1436189251Ssam	return wpa_ctrl_command(ctrl, "SCAN");
1437189251Ssam}
1438189251Ssam
1439189251Ssam
1440189251Ssamstatic int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1441189251Ssam				    char *argv[])
1442189251Ssam{
1443189251Ssam	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1444189251Ssam}
1445189251Ssam
1446189251Ssam
1447189251Ssamstatic int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1448189251Ssam{
1449252726Srpaulo	return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1450252726Srpaulo}
1451189251Ssam
1452252726Srpaulo
1453252726Srpaulostatic char ** wpa_cli_complete_bss(const char *str, int pos)
1454252726Srpaulo{
1455252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1456252726Srpaulo	char **res = NULL;
1457252726Srpaulo
1458252726Srpaulo	switch (arg) {
1459252726Srpaulo	case 1:
1460252726Srpaulo		res = cli_txt_list_array(&bsses);
1461252726Srpaulo		break;
1462189251Ssam	}
1463189251Ssam
1464252726Srpaulo	return res;
1465189251Ssam}
1466189251Ssam
1467189251Ssam
1468189251Ssamstatic int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1469189251Ssam				      char *argv[])
1470189251Ssam{
1471189251Ssam	if (argc < 1 || argc > 2) {
1472189251Ssam		printf("Invalid GET_CAPABILITY command: need either one or "
1473189251Ssam		       "two arguments\n");
1474189251Ssam		return -1;
1475189251Ssam	}
1476189251Ssam
1477189251Ssam	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1478189251Ssam		printf("Invalid GET_CAPABILITY command: second argument, "
1479189251Ssam		       "if any, must be 'strict'\n");
1480189251Ssam		return -1;
1481189251Ssam	}
1482189251Ssam
1483252726Srpaulo	return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1484189251Ssam}
1485189251Ssam
1486189251Ssam
1487189251Ssamstatic int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1488189251Ssam{
1489189251Ssam	printf("Available interfaces:\n");
1490189251Ssam	return wpa_ctrl_command(ctrl, "INTERFACES");
1491189251Ssam}
1492189251Ssam
1493189251Ssam
1494189251Ssamstatic int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1495189251Ssam{
1496189251Ssam	if (argc < 1) {
1497189251Ssam		wpa_cli_list_interfaces(ctrl);
1498189251Ssam		return 0;
1499189251Ssam	}
1500189251Ssam
1501189251Ssam	wpa_cli_close_connection();
1502189251Ssam	os_free(ctrl_ifname);
1503189251Ssam	ctrl_ifname = os_strdup(argv[0]);
1504189251Ssam
1505214734Srpaulo	if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1506189251Ssam		printf("Connected to interface '%s.\n", ctrl_ifname);
1507189251Ssam	} else {
1508189251Ssam		printf("Could not connect to interface '%s' - re-trying\n",
1509189251Ssam		       ctrl_ifname);
1510189251Ssam	}
1511189251Ssam	return 0;
1512189251Ssam}
1513189251Ssam
1514189251Ssam
1515189251Ssamstatic int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1516189251Ssam				   char *argv[])
1517189251Ssam{
1518189251Ssam	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1519189251Ssam}
1520189251Ssam
1521189251Ssam
1522189251Ssamstatic int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1523189251Ssam				 char *argv[])
1524189251Ssam{
1525189251Ssam	return wpa_ctrl_command(ctrl, "TERMINATE");
1526189251Ssam}
1527189251Ssam
1528189251Ssam
1529189251Ssamstatic int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1530189251Ssam				     char *argv[])
1531189251Ssam{
1532189251Ssam	char cmd[256];
1533189251Ssam	int res;
1534189251Ssam
1535189251Ssam	if (argc < 1) {
1536189251Ssam		printf("Invalid INTERFACE_ADD command: needs at least one "
1537189251Ssam		       "argument (interface name)\n"
1538189251Ssam		       "All arguments: ifname confname driver ctrl_interface "
1539189251Ssam		       "driver_param bridge_name\n");
1540189251Ssam		return -1;
1541189251Ssam	}
1542189251Ssam
1543189251Ssam	/*
1544189251Ssam	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1545189251Ssam	 * <driver_param>TAB<bridge_name>
1546189251Ssam	 */
1547189251Ssam	res = os_snprintf(cmd, sizeof(cmd),
1548189251Ssam			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1549189251Ssam			  argv[0],
1550189251Ssam			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1551189251Ssam			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1552189251Ssam			  argc > 5 ? argv[5] : "");
1553189251Ssam	if (res < 0 || (size_t) res >= sizeof(cmd))
1554189251Ssam		return -1;
1555189251Ssam	cmd[sizeof(cmd) - 1] = '\0';
1556189251Ssam	return wpa_ctrl_command(ctrl, cmd);
1557189251Ssam}
1558189251Ssam
1559189251Ssam
1560189251Ssamstatic int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1561189251Ssam					char *argv[])
1562189251Ssam{
1563252726Srpaulo	return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1564189251Ssam}
1565189251Ssam
1566189251Ssam
1567189251Ssamstatic int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1568189251Ssam				      char *argv[])
1569189251Ssam{
1570189251Ssam	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1571189251Ssam}
1572189251Ssam
1573189251Ssam
1574214734Srpaulo#ifdef CONFIG_AP
1575214734Srpaulostatic int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1576214734Srpaulo{
1577252726Srpaulo	return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1578214734Srpaulo}
1579214734Srpaulo
1580214734Srpaulo
1581214734Srpaulostatic int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1582214734Srpaulo				char *addr, size_t addr_len)
1583214734Srpaulo{
1584214734Srpaulo	char buf[4096], *pos;
1585214734Srpaulo	size_t len;
1586214734Srpaulo	int ret;
1587214734Srpaulo
1588214734Srpaulo	if (ctrl_conn == NULL) {
1589214734Srpaulo		printf("Not connected to hostapd - command dropped.\n");
1590214734Srpaulo		return -1;
1591214734Srpaulo	}
1592214734Srpaulo	len = sizeof(buf) - 1;
1593252726Srpaulo	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1594214734Srpaulo			       wpa_cli_msg_cb);
1595214734Srpaulo	if (ret == -2) {
1596214734Srpaulo		printf("'%s' command timed out.\n", cmd);
1597214734Srpaulo		return -2;
1598214734Srpaulo	} else if (ret < 0) {
1599214734Srpaulo		printf("'%s' command failed.\n", cmd);
1600214734Srpaulo		return -1;
1601214734Srpaulo	}
1602214734Srpaulo
1603214734Srpaulo	buf[len] = '\0';
1604252726Srpaulo	if (os_memcmp(buf, "FAIL", 4) == 0)
1605214734Srpaulo		return -1;
1606214734Srpaulo	printf("%s", buf);
1607214734Srpaulo
1608214734Srpaulo	pos = buf;
1609214734Srpaulo	while (*pos != '\0' && *pos != '\n')
1610214734Srpaulo		pos++;
1611214734Srpaulo	*pos = '\0';
1612214734Srpaulo	os_strlcpy(addr, buf, addr_len);
1613214734Srpaulo	return 0;
1614214734Srpaulo}
1615214734Srpaulo
1616214734Srpaulo
1617214734Srpaulostatic int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1618214734Srpaulo{
1619214734Srpaulo	char addr[32], cmd[64];
1620214734Srpaulo
1621214734Srpaulo	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1622214734Srpaulo		return 0;
1623214734Srpaulo	do {
1624214734Srpaulo		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1625214734Srpaulo	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1626214734Srpaulo
1627214734Srpaulo	return -1;
1628214734Srpaulo}
1629252726Srpaulo
1630252726Srpaulo
1631252726Srpaulostatic int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1632252726Srpaulo				      char *argv[])
1633252726Srpaulo{
1634252726Srpaulo	return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1635252726Srpaulo}
1636252726Srpaulo
1637252726Srpaulo
1638252726Srpaulostatic int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1639252726Srpaulo				    char *argv[])
1640252726Srpaulo{
1641252726Srpaulo	return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1642252726Srpaulo}
1643214734Srpaulo#endif /* CONFIG_AP */
1644214734Srpaulo
1645214734Srpaulo
1646214734Srpaulostatic int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1647214734Srpaulo{
1648214734Srpaulo	return wpa_ctrl_command(ctrl, "SUSPEND");
1649214734Srpaulo}
1650214734Srpaulo
1651214734Srpaulo
1652214734Srpaulostatic int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1653214734Srpaulo{
1654214734Srpaulo	return wpa_ctrl_command(ctrl, "RESUME");
1655214734Srpaulo}
1656214734Srpaulo
1657214734Srpaulo
1658214734Srpaulostatic int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1659214734Srpaulo{
1660214734Srpaulo	return wpa_ctrl_command(ctrl, "DROP_SA");
1661214734Srpaulo}
1662214734Srpaulo
1663214734Srpaulo
1664214734Srpaulostatic int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1665214734Srpaulo{
1666252726Srpaulo	return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
1667252726Srpaulo}
1668252726Srpaulo
1669252726Srpaulo
1670252726Srpaulo#ifdef CONFIG_P2P
1671252726Srpaulo
1672252726Srpaulostatic int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1673252726Srpaulo{
1674252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1675252726Srpaulo}
1676252726Srpaulo
1677252726Srpaulo
1678252726Srpaulostatic char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1679252726Srpaulo{
1680252726Srpaulo	char **res = NULL;
1681252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1682252726Srpaulo
1683252726Srpaulo	res = os_calloc(6, sizeof(char *));
1684252726Srpaulo	if (res == NULL)
1685252726Srpaulo		return NULL;
1686252726Srpaulo	res[0] = os_strdup("type=social");
1687252726Srpaulo	if (res[0] == NULL) {
1688252726Srpaulo		os_free(res);
1689252726Srpaulo		return NULL;
1690252726Srpaulo	}
1691252726Srpaulo	res[1] = os_strdup("type=progressive");
1692252726Srpaulo	if (res[1] == NULL)
1693252726Srpaulo		return res;
1694252726Srpaulo	res[2] = os_strdup("delay=");
1695252726Srpaulo	if (res[2] == NULL)
1696252726Srpaulo		return res;
1697252726Srpaulo	res[3] = os_strdup("dev_id=");
1698252726Srpaulo	if (res[3] == NULL)
1699252726Srpaulo		return res;
1700252726Srpaulo	if (arg == 1)
1701252726Srpaulo		res[4] = os_strdup("[timeout]");
1702252726Srpaulo
1703252726Srpaulo	return res;
1704252726Srpaulo}
1705252726Srpaulo
1706252726Srpaulo
1707252726Srpaulostatic int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1708252726Srpaulo				     char *argv[])
1709252726Srpaulo{
1710252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1711252726Srpaulo}
1712252726Srpaulo
1713252726Srpaulo
1714252726Srpaulostatic int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1715252726Srpaulo				   char *argv[])
1716252726Srpaulo{
1717252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
1718252726Srpaulo}
1719252726Srpaulo
1720252726Srpaulo
1721252726Srpaulostatic char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1722252726Srpaulo{
1723252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1724252726Srpaulo	char **res = NULL;
1725252726Srpaulo
1726252726Srpaulo	switch (arg) {
1727252726Srpaulo	case 1:
1728252726Srpaulo		res = cli_txt_list_array(&p2p_peers);
1729252726Srpaulo		break;
1730252726Srpaulo	}
1731252726Srpaulo
1732252726Srpaulo	return res;
1733252726Srpaulo}
1734252726Srpaulo
1735252726Srpaulo
1736252726Srpaulostatic int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1737252726Srpaulo				  char *argv[])
1738252726Srpaulo{
1739252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
1740252726Srpaulo}
1741252726Srpaulo
1742252726Srpaulo
1743252726Srpaulostatic int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1744252726Srpaulo					char *argv[])
1745252726Srpaulo{
1746252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
1747252726Srpaulo}
1748252726Srpaulo
1749252726Srpaulo
1750252726Srpaulostatic char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1751252726Srpaulo{
1752252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1753252726Srpaulo	char **res = NULL;
1754252726Srpaulo
1755252726Srpaulo	switch (arg) {
1756252726Srpaulo	case 1:
1757252726Srpaulo		res = cli_txt_list_array(&p2p_groups);
1758252726Srpaulo		break;
1759252726Srpaulo	}
1760252726Srpaulo
1761252726Srpaulo	return res;
1762252726Srpaulo}
1763252726Srpaulo
1764252726Srpaulo
1765252726Srpaulostatic int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1766252726Srpaulo					char *argv[])
1767252726Srpaulo{
1768252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
1769252726Srpaulo}
1770252726Srpaulo
1771252726Srpaulo
1772252726Srpaulostatic int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1773252726Srpaulo				     char *argv[])
1774252726Srpaulo{
1775252726Srpaulo	if (argc != 2 && argc != 3) {
1776252726Srpaulo		printf("Invalid P2P_PROV_DISC command: needs at least "
1777252726Srpaulo		       "two arguments, address and config method\n"
1778252726Srpaulo		       "(display, keypad, or pbc) and an optional join\n");
1779252726Srpaulo		return -1;
1780252726Srpaulo	}
1781252726Srpaulo
1782252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
1783252726Srpaulo}
1784252726Srpaulo
1785252726Srpaulo
1786252726Srpaulostatic int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1787252726Srpaulo					  char *argv[])
1788252726Srpaulo{
1789252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1790252726Srpaulo}
1791252726Srpaulo
1792252726Srpaulo
1793252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1794252726Srpaulo					 char *argv[])
1795252726Srpaulo{
1796252726Srpaulo	char cmd[4096];
1797252726Srpaulo
1798252726Srpaulo	if (argc != 2 && argc != 4) {
1799252726Srpaulo		printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1800252726Srpaulo		       "arguments (address and TLVs) or four arguments "
1801252726Srpaulo		       "(address, \"upnp\", version, search target "
1802252726Srpaulo		       "(SSDP ST:)\n");
1803252726Srpaulo		return -1;
1804252726Srpaulo	}
1805252726Srpaulo
1806252726Srpaulo	if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
1807252726Srpaulo		return -1;
1808252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1809252726Srpaulo}
1810252726Srpaulo
1811252726Srpaulo
1812252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1813252726Srpaulo						int argc, char *argv[])
1814252726Srpaulo{
1815252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
1816252726Srpaulo}
1817252726Srpaulo
1818252726Srpaulo
1819252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1820252726Srpaulo					  char *argv[])
1821252726Srpaulo{
1822252726Srpaulo	char cmd[4096];
1823214734Srpaulo	int res;
1824214734Srpaulo
1825252726Srpaulo	if (argc != 4) {
1826252726Srpaulo		printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1827252726Srpaulo		       "arguments (freq, address, dialog token, and TLVs)\n");
1828252726Srpaulo		return -1;
1829252726Srpaulo	}
1830252726Srpaulo
1831252726Srpaulo	res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1832252726Srpaulo			  argv[0], argv[1], argv[2], argv[3]);
1833252726Srpaulo	if (res < 0 || (size_t) res >= sizeof(cmd))
1834252726Srpaulo		return -1;
1835252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
1836252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1837252726Srpaulo}
1838252726Srpaulo
1839252726Srpaulo
1840252726Srpaulostatic int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1841252726Srpaulo					  char *argv[])
1842252726Srpaulo{
1843252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1844252726Srpaulo}
1845252726Srpaulo
1846252726Srpaulo
1847252726Srpaulostatic int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1848252726Srpaulo					      int argc, char *argv[])
1849252726Srpaulo{
1850252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
1851252726Srpaulo}
1852252726Srpaulo
1853252726Srpaulo
1854252726Srpaulostatic int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1855252726Srpaulo					 char *argv[])
1856252726Srpaulo{
1857252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1858252726Srpaulo}
1859252726Srpaulo
1860252726Srpaulo
1861252726Srpaulostatic int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1862252726Srpaulo				       char *argv[])
1863252726Srpaulo{
1864252726Srpaulo	char cmd[4096];
1865252726Srpaulo	int res;
1866252726Srpaulo
1867252726Srpaulo	if (argc != 3 && argc != 4) {
1868252726Srpaulo		printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1869252726Srpaulo		       "arguments\n");
1870252726Srpaulo		return -1;
1871252726Srpaulo	}
1872252726Srpaulo
1873252726Srpaulo	if (argc == 4)
1874252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
1875252726Srpaulo				  "P2P_SERVICE_ADD %s %s %s %s",
1876252726Srpaulo				  argv[0], argv[1], argv[2], argv[3]);
1877252726Srpaulo	else
1878252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
1879252726Srpaulo				  "P2P_SERVICE_ADD %s %s %s",
1880252726Srpaulo				  argv[0], argv[1], argv[2]);
1881252726Srpaulo	if (res < 0 || (size_t) res >= sizeof(cmd))
1882252726Srpaulo		return -1;
1883252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
1884252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1885252726Srpaulo}
1886252726Srpaulo
1887252726Srpaulo
1888252726Srpaulostatic int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1889252726Srpaulo				       char *argv[])
1890252726Srpaulo{
1891252726Srpaulo	char cmd[4096];
1892252726Srpaulo	int res;
1893252726Srpaulo
1894252726Srpaulo	if (argc != 2 && argc != 3) {
1895252726Srpaulo		printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1896252726Srpaulo		       "arguments\n");
1897252726Srpaulo		return -1;
1898252726Srpaulo	}
1899252726Srpaulo
1900252726Srpaulo	if (argc == 3)
1901252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
1902252726Srpaulo				  "P2P_SERVICE_DEL %s %s %s",
1903252726Srpaulo				  argv[0], argv[1], argv[2]);
1904252726Srpaulo	else
1905252726Srpaulo		res = os_snprintf(cmd, sizeof(cmd),
1906252726Srpaulo				  "P2P_SERVICE_DEL %s %s",
1907252726Srpaulo				  argv[0], argv[1]);
1908252726Srpaulo	if (res < 0 || (size_t) res >= sizeof(cmd))
1909252726Srpaulo		return -1;
1910252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
1911252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
1912252726Srpaulo}
1913252726Srpaulo
1914252726Srpaulo
1915252726Srpaulostatic int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1916252726Srpaulo				  int argc, char *argv[])
1917252726Srpaulo{
1918252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
1919252726Srpaulo}
1920252726Srpaulo
1921252726Srpaulo
1922252726Srpaulostatic int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1923252726Srpaulo				  int argc, char *argv[])
1924252726Srpaulo{
1925252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
1926252726Srpaulo}
1927252726Srpaulo
1928252726Srpaulo
1929252726Srpaulostatic int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1930252726Srpaulo{
1931252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
1932252726Srpaulo}
1933252726Srpaulo
1934252726Srpaulo
1935252726Srpaulostatic char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1936252726Srpaulo{
1937252726Srpaulo	int arg = get_cmd_arg_num(str, pos);
1938252726Srpaulo	char **res = NULL;
1939252726Srpaulo
1940252726Srpaulo	switch (arg) {
1941252726Srpaulo	case 1:
1942252726Srpaulo		res = cli_txt_list_array(&p2p_peers);
1943252726Srpaulo		break;
1944252726Srpaulo	}
1945252726Srpaulo
1946252726Srpaulo	return res;
1947252726Srpaulo}
1948252726Srpaulo
1949252726Srpaulo
1950252726Srpaulostatic int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1951252726Srpaulo				     char *addr, size_t addr_len,
1952252726Srpaulo				     int discovered)
1953252726Srpaulo{
1954252726Srpaulo	char buf[4096], *pos;
1955252726Srpaulo	size_t len;
1956252726Srpaulo	int ret;
1957252726Srpaulo
1958252726Srpaulo	if (ctrl_conn == NULL)
1959252726Srpaulo		return -1;
1960252726Srpaulo	len = sizeof(buf) - 1;
1961252726Srpaulo	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1962252726Srpaulo			       wpa_cli_msg_cb);
1963252726Srpaulo	if (ret == -2) {
1964252726Srpaulo		printf("'%s' command timed out.\n", cmd);
1965252726Srpaulo		return -2;
1966252726Srpaulo	} else if (ret < 0) {
1967252726Srpaulo		printf("'%s' command failed.\n", cmd);
1968252726Srpaulo		return -1;
1969252726Srpaulo	}
1970252726Srpaulo
1971252726Srpaulo	buf[len] = '\0';
1972252726Srpaulo	if (os_memcmp(buf, "FAIL", 4) == 0)
1973252726Srpaulo		return -1;
1974252726Srpaulo
1975252726Srpaulo	pos = buf;
1976252726Srpaulo	while (*pos != '\0' && *pos != '\n')
1977252726Srpaulo		pos++;
1978252726Srpaulo	*pos++ = '\0';
1979252726Srpaulo	os_strlcpy(addr, buf, addr_len);
1980252726Srpaulo	if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
1981252726Srpaulo		printf("%s\n", addr);
1982252726Srpaulo	return 0;
1983252726Srpaulo}
1984252726Srpaulo
1985252726Srpaulo
1986252726Srpaulostatic int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
1987252726Srpaulo{
1988252726Srpaulo	char addr[32], cmd[64];
1989252726Srpaulo	int discovered;
1990252726Srpaulo
1991252726Srpaulo	discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
1992252726Srpaulo
1993252726Srpaulo	if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
1994252726Srpaulo				      addr, sizeof(addr), discovered))
1995252726Srpaulo		return -1;
1996252726Srpaulo	do {
1997252726Srpaulo		os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
1998252726Srpaulo	} while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
1999252726Srpaulo			 discovered) == 0);
2000252726Srpaulo
2001252726Srpaulo	return 0;
2002252726Srpaulo}
2003252726Srpaulo
2004252726Srpaulo
2005252726Srpaulostatic int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2006252726Srpaulo{
2007252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2008252726Srpaulo}
2009252726Srpaulo
2010252726Srpaulo
2011252726Srpaulostatic int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2012252726Srpaulo{
2013252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2014252726Srpaulo}
2015252726Srpaulo
2016252726Srpaulo
2017252726Srpaulostatic int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2018252726Srpaulo				  char *argv[])
2019252726Srpaulo{
2020252726Srpaulo	return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2021252726Srpaulo}
2022252726Srpaulo
2023252726Srpaulo
2024252726Srpaulostatic int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2025252726Srpaulo				       char *argv[])
2026252726Srpaulo{
2027252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2028252726Srpaulo}
2029252726Srpaulo
2030252726Srpaulo
2031252726Srpaulostatic int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2032252726Srpaulo					char *argv[])
2033252726Srpaulo{
2034252726Srpaulo	if (argc != 0 && argc != 2 && argc != 4) {
2035252726Srpaulo		printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2036252726Srpaulo		       "(preferred duration, interval; in microsecods).\n"
2037252726Srpaulo		       "Optional second pair can be used to provide "
2038252726Srpaulo		       "acceptable values.\n");
2039252726Srpaulo		return -1;
2040252726Srpaulo	}
2041252726Srpaulo
2042252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2043252726Srpaulo}
2044252726Srpaulo
2045252726Srpaulo
2046252726Srpaulostatic int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2047252726Srpaulo				      char *argv[])
2048252726Srpaulo{
2049252726Srpaulo	if (argc != 0 && argc != 2) {
2050252726Srpaulo		printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2051252726Srpaulo		       "(availability period, availability interval; in "
2052252726Srpaulo		       "millisecods).\n"
2053252726Srpaulo		       "Extended Listen Timing can be cancelled with this "
2054252726Srpaulo		       "command when used without parameters.\n");
2055252726Srpaulo		return -1;
2056252726Srpaulo	}
2057252726Srpaulo
2058252726Srpaulo	return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2059252726Srpaulo}
2060252726Srpaulo
2061252726Srpaulo#endif /* CONFIG_P2P */
2062252726Srpaulo
2063252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY
2064252726Srpaulo
2065252726Srpaulostatic int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2066252726Srpaulo				       char *argv[])
2067252726Srpaulo{
2068252726Srpaulo	char cmd[100];
2069252726Srpaulo	int res;
2070252726Srpaulo
2071252726Srpaulo	if (argc != 1 && argc != 2) {
2072252726Srpaulo		printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2073252726Srpaulo		       "arguments (subelem, hexdump)\n");
2074252726Srpaulo		return -1;
2075252726Srpaulo	}
2076252726Srpaulo
2077252726Srpaulo	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2078252726Srpaulo			  argv[0], argc > 1 ? argv[1] : "");
2079252726Srpaulo	if (res < 0 || (size_t) res >= sizeof(cmd))
2080252726Srpaulo		return -1;
2081252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
2082252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2083252726Srpaulo}
2084252726Srpaulo
2085252726Srpaulo
2086252726Srpaulostatic int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2087252726Srpaulo				       char *argv[])
2088252726Srpaulo{
2089252726Srpaulo	char cmd[100];
2090252726Srpaulo	int res;
2091252726Srpaulo
2092214734Srpaulo	if (argc != 1) {
2093252726Srpaulo		printf("Invalid WFD_SUBELEM_GET command: needs one "
2094252726Srpaulo		       "argument (subelem)\n");
2095214734Srpaulo		return -1;
2096214734Srpaulo	}
2097214734Srpaulo
2098252726Srpaulo	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2099252726Srpaulo			  argv[0]);
2100252726Srpaulo	if (res < 0 || (size_t) res >= sizeof(cmd))
2101214734Srpaulo		return -1;
2102252726Srpaulo	cmd[sizeof(cmd) - 1] = '\0';
2103252726Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2104252726Srpaulo}
2105252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */
2106252726Srpaulo
2107252726Srpaulo
2108252726Srpaulo#ifdef CONFIG_INTERWORKING
2109252726Srpaulostatic int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2110252726Srpaulo				  char *argv[])
2111252726Srpaulo{
2112252726Srpaulo	return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2113252726Srpaulo}
2114252726Srpaulo
2115252726Srpaulo
2116252726Srpaulostatic int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2117252726Srpaulo				       char *argv[])
2118252726Srpaulo{
2119252726Srpaulo	return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2120252726Srpaulo}
2121252726Srpaulo
2122252726Srpaulo
2123252726Srpaulostatic int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2124252726Srpaulo					   char *argv[])
2125252726Srpaulo{
2126252726Srpaulo	return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2127252726Srpaulo}
2128252726Srpaulo
2129252726Srpaulo
2130252726Srpaulostatic int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2131252726Srpaulo					    char *argv[])
2132252726Srpaulo{
2133252726Srpaulo	return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2134252726Srpaulo}
2135252726Srpaulo
2136252726Srpaulo
2137252726Srpaulostatic int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2138252726Srpaulo{
2139252726Srpaulo	return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2140252726Srpaulo}
2141252726Srpaulo
2142252726Srpaulo
2143252726Srpaulostatic int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2144252726Srpaulo				   char *argv[])
2145252726Srpaulo{
2146252726Srpaulo	return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2147252726Srpaulo}
2148252726Srpaulo
2149252726Srpaulo
2150252726Srpaulostatic int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2151252726Srpaulo					char *argv[])
2152252726Srpaulo{
2153252726Srpaulo	return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2154252726Srpaulo}
2155252726Srpaulo#endif /* CONFIG_INTERWORKING */
2156252726Srpaulo
2157252726Srpaulo
2158252726Srpaulo#ifdef CONFIG_HS20
2159252726Srpaulo
2160252726Srpaulostatic int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2161252726Srpaulo				     char *argv[])
2162252726Srpaulo{
2163252726Srpaulo	return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2164252726Srpaulo}
2165252726Srpaulo
2166252726Srpaulo
2167252726Srpaulostatic int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2168252726Srpaulo					       char *argv[])
2169252726Srpaulo{
2170252726Srpaulo	char cmd[512];
2171252726Srpaulo
2172252726Srpaulo	if (argc == 0) {
2173252726Srpaulo		printf("Command needs one or two arguments (dst mac addr and "
2174252726Srpaulo		       "optional home realm)\n");
2175252726Srpaulo		return -1;
2176214734Srpaulo	}
2177252726Srpaulo
2178252726Srpaulo	if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2179252726Srpaulo		      argc, argv) < 0)
2180252726Srpaulo		return -1;
2181252726Srpaulo
2182214734Srpaulo	return wpa_ctrl_command(ctrl, cmd);
2183214734Srpaulo}
2184214734Srpaulo
2185252726Srpaulo#endif /* CONFIG_HS20 */
2186214734Srpaulo
2187252726Srpaulo
2188252726Srpaulostatic int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2189252726Srpaulo				       char *argv[])
2190252726Srpaulo{
2191252726Srpaulo	return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2192252726Srpaulo}
2193252726Srpaulo
2194252726Srpaulo
2195252726Srpaulostatic int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2196252726Srpaulo				     char *argv[])
2197252726Srpaulo{
2198252726Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2199252726Srpaulo}
2200252726Srpaulo
2201252726Srpaulo
2202252726Srpaulostatic int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2203252726Srpaulo				  char *argv[])
2204252726Srpaulo{
2205252726Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2206252726Srpaulo}
2207252726Srpaulo
2208252726Srpaulo
2209252726Srpaulostatic int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2210252726Srpaulo				     char *argv[])
2211252726Srpaulo{
2212252726Srpaulo	return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2213252726Srpaulo}
2214252726Srpaulo
2215252726Srpaulo
2216252726Srpaulostatic int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2217252726Srpaulo				   char *argv[])
2218252726Srpaulo{
2219252726Srpaulo	return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2220252726Srpaulo}
2221252726Srpaulo
2222252726Srpaulo
2223252726Srpaulostatic int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2224252726Srpaulo				   char *argv[])
2225252726Srpaulo{
2226252726Srpaulo	return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2227252726Srpaulo}
2228252726Srpaulo
2229252726Srpaulo
2230252726Srpaulostatic int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2231252726Srpaulo				      char *argv[])
2232252726Srpaulo{
2233252726Srpaulo	return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2234252726Srpaulo}
2235252726Srpaulo
2236252726Srpaulo
2237252726Srpaulo#ifdef CONFIG_AUTOSCAN
2238252726Srpaulo
2239252726Srpaulostatic int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2240252726Srpaulo{
2241252726Srpaulo	if (argc == 0)
2242252726Srpaulo		return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2243252726Srpaulo
2244252726Srpaulo	return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2245252726Srpaulo}
2246252726Srpaulo
2247252726Srpaulo#endif /* CONFIG_AUTOSCAN */
2248252726Srpaulo
2249252726Srpaulo
2250252726Srpaulo#ifdef CONFIG_WNM
2251252726Srpaulo
2252252726Srpaulostatic int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2253252726Srpaulo{
2254252726Srpaulo	return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2255252726Srpaulo}
2256252726Srpaulo
2257252726Srpaulo#endif /* CONFIG_WNM */
2258252726Srpaulo
2259252726Srpaulo
2260252726Srpaulostatic int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2261252726Srpaulo{
2262252726Srpaulo	if (argc == 0)
2263252726Srpaulo		return -1;
2264252726Srpaulo	return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2265252726Srpaulo}
2266252726Srpaulo
2267252726Srpaulo
2268189251Ssamenum wpa_cli_cmd_flags {
2269189251Ssam	cli_cmd_flag_none		= 0x00,
2270189251Ssam	cli_cmd_flag_sensitive		= 0x01
2271189251Ssam};
2272189251Ssam
2273189251Ssamstruct wpa_cli_cmd {
2274189251Ssam	const char *cmd;
2275189251Ssam	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2276252726Srpaulo	char ** (*completion)(const char *str, int pos);
2277189251Ssam	enum wpa_cli_cmd_flags flags;
2278189251Ssam	const char *usage;
2279189251Ssam};
2280189251Ssam
2281189251Ssamstatic struct wpa_cli_cmd wpa_cli_commands[] = {
2282252726Srpaulo	{ "status", wpa_cli_cmd_status, NULL,
2283189251Ssam	  cli_cmd_flag_none,
2284189251Ssam	  "[verbose] = get current WPA/EAPOL/EAP status" },
2285252726Srpaulo	{ "ifname", wpa_cli_cmd_ifname, NULL,
2286189251Ssam	  cli_cmd_flag_none,
2287252726Srpaulo	  "= get current interface name" },
2288252726Srpaulo	{ "ping", wpa_cli_cmd_ping, NULL,
2289252726Srpaulo	  cli_cmd_flag_none,
2290189251Ssam	  "= pings wpa_supplicant" },
2291252726Srpaulo	{ "relog", wpa_cli_cmd_relog, NULL,
2292189251Ssam	  cli_cmd_flag_none,
2293252726Srpaulo	  "= re-open log-file (allow rolling logs)" },
2294252726Srpaulo	{ "note", wpa_cli_cmd_note, NULL,
2295252726Srpaulo	  cli_cmd_flag_none,
2296252726Srpaulo	  "<text> = add a note to wpa_supplicant debug log" },
2297252726Srpaulo	{ "mib", wpa_cli_cmd_mib, NULL,
2298252726Srpaulo	  cli_cmd_flag_none,
2299189251Ssam	  "= get MIB variables (dot1x, dot11)" },
2300252726Srpaulo	{ "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2301189251Ssam	  cli_cmd_flag_none,
2302252726Srpaulo	  "[command] = show usage help" },
2303252726Srpaulo	{ "interface", wpa_cli_cmd_interface, NULL,
2304189251Ssam	  cli_cmd_flag_none,
2305189251Ssam	  "[ifname] = show interfaces/select interface" },
2306252726Srpaulo	{ "level", wpa_cli_cmd_level, NULL,
2307189251Ssam	  cli_cmd_flag_none,
2308189251Ssam	  "<debug level> = change debug level" },
2309252726Srpaulo	{ "license", wpa_cli_cmd_license, NULL,
2310189251Ssam	  cli_cmd_flag_none,
2311189251Ssam	  "= show full wpa_cli license" },
2312252726Srpaulo	{ "quit", wpa_cli_cmd_quit, NULL,
2313189251Ssam	  cli_cmd_flag_none,
2314189251Ssam	  "= exit wpa_cli" },
2315252726Srpaulo	{ "set", wpa_cli_cmd_set, NULL,
2316189251Ssam	  cli_cmd_flag_none,
2317189251Ssam	  "= set variables (shows list of variables when run without "
2318189251Ssam	  "arguments)" },
2319252726Srpaulo	{ "get", wpa_cli_cmd_get, NULL,
2320189251Ssam	  cli_cmd_flag_none,
2321252726Srpaulo	  "<name> = get information" },
2322252726Srpaulo	{ "logon", wpa_cli_cmd_logon, NULL,
2323252726Srpaulo	  cli_cmd_flag_none,
2324189251Ssam	  "= IEEE 802.1X EAPOL state machine logon" },
2325252726Srpaulo	{ "logoff", wpa_cli_cmd_logoff, NULL,
2326189251Ssam	  cli_cmd_flag_none,
2327189251Ssam	  "= IEEE 802.1X EAPOL state machine logoff" },
2328252726Srpaulo	{ "pmksa", wpa_cli_cmd_pmksa, NULL,
2329189251Ssam	  cli_cmd_flag_none,
2330189251Ssam	  "= show PMKSA cache" },
2331252726Srpaulo	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
2332189251Ssam	  cli_cmd_flag_none,
2333189251Ssam	  "= force reassociation" },
2334252726Srpaulo	{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2335189251Ssam	  cli_cmd_flag_none,
2336189251Ssam	  "<BSSID> = force preauthentication" },
2337252726Srpaulo	{ "identity", wpa_cli_cmd_identity, NULL,
2338189251Ssam	  cli_cmd_flag_none,
2339189251Ssam	  "<network id> <identity> = configure identity for an SSID" },
2340252726Srpaulo	{ "password", wpa_cli_cmd_password, NULL,
2341189251Ssam	  cli_cmd_flag_sensitive,
2342189251Ssam	  "<network id> <password> = configure password for an SSID" },
2343252726Srpaulo	{ "new_password", wpa_cli_cmd_new_password, NULL,
2344189251Ssam	  cli_cmd_flag_sensitive,
2345189251Ssam	  "<network id> <password> = change password for an SSID" },
2346252726Srpaulo	{ "pin", wpa_cli_cmd_pin, NULL,
2347189251Ssam	  cli_cmd_flag_sensitive,
2348189251Ssam	  "<network id> <pin> = configure pin for an SSID" },
2349252726Srpaulo	{ "otp", wpa_cli_cmd_otp, NULL,
2350189251Ssam	  cli_cmd_flag_sensitive,
2351189251Ssam	  "<network id> <password> = configure one-time-password for an SSID"
2352189251Ssam	},
2353252726Srpaulo	{ "passphrase", wpa_cli_cmd_passphrase, NULL,
2354189251Ssam	  cli_cmd_flag_sensitive,
2355189251Ssam	  "<network id> <passphrase> = configure private key passphrase\n"
2356189251Ssam	  "  for an SSID" },
2357252726Srpaulo	{ "bssid", wpa_cli_cmd_bssid, NULL,
2358189251Ssam	  cli_cmd_flag_none,
2359189251Ssam	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
2360252726Srpaulo	{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2361189251Ssam	  cli_cmd_flag_none,
2362252726Srpaulo	  "<BSSID> = add a BSSID to the blacklist\n"
2363252726Srpaulo	  "blacklist clear = clear the blacklist\n"
2364252726Srpaulo	  "blacklist = display the blacklist" },
2365252726Srpaulo	{ "log_level", wpa_cli_cmd_log_level, NULL,
2366252726Srpaulo	  cli_cmd_flag_none,
2367252726Srpaulo	  "<level> [<timestamp>] = update the log level/timestamp\n"
2368252726Srpaulo	  "log_level = display the current log level and log options" },
2369252726Srpaulo	{ "list_networks", wpa_cli_cmd_list_networks, NULL,
2370252726Srpaulo	  cli_cmd_flag_none,
2371189251Ssam	  "= list configured networks" },
2372252726Srpaulo	{ "select_network", wpa_cli_cmd_select_network, NULL,
2373189251Ssam	  cli_cmd_flag_none,
2374189251Ssam	  "<network id> = select a network (disable others)" },
2375252726Srpaulo	{ "enable_network", wpa_cli_cmd_enable_network, NULL,
2376189251Ssam	  cli_cmd_flag_none,
2377189251Ssam	  "<network id> = enable a network" },
2378252726Srpaulo	{ "disable_network", wpa_cli_cmd_disable_network, NULL,
2379189251Ssam	  cli_cmd_flag_none,
2380189251Ssam	  "<network id> = disable a network" },
2381252726Srpaulo	{ "add_network", wpa_cli_cmd_add_network, NULL,
2382189251Ssam	  cli_cmd_flag_none,
2383189251Ssam	  "= add a network" },
2384252726Srpaulo	{ "remove_network", wpa_cli_cmd_remove_network, NULL,
2385189251Ssam	  cli_cmd_flag_none,
2386189251Ssam	  "<network id> = remove a network" },
2387252726Srpaulo	{ "set_network", wpa_cli_cmd_set_network, NULL,
2388189251Ssam	  cli_cmd_flag_sensitive,
2389189251Ssam	  "<network id> <variable> <value> = set network variables (shows\n"
2390189251Ssam	  "  list of variables when run without arguments)" },
2391252726Srpaulo	{ "get_network", wpa_cli_cmd_get_network, NULL,
2392189251Ssam	  cli_cmd_flag_none,
2393189251Ssam	  "<network id> <variable> = get network variables" },
2394252726Srpaulo	{ "list_creds", wpa_cli_cmd_list_creds, NULL,
2395189251Ssam	  cli_cmd_flag_none,
2396252726Srpaulo	  "= list configured credentials" },
2397252726Srpaulo	{ "add_cred", wpa_cli_cmd_add_cred, NULL,
2398252726Srpaulo	  cli_cmd_flag_none,
2399252726Srpaulo	  "= add a credential" },
2400252726Srpaulo	{ "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2401252726Srpaulo	  cli_cmd_flag_none,
2402252726Srpaulo	  "<cred id> = remove a credential" },
2403252726Srpaulo	{ "set_cred", wpa_cli_cmd_set_cred, NULL,
2404252726Srpaulo	  cli_cmd_flag_sensitive,
2405252726Srpaulo	  "<cred id> <variable> <value> = set credential variables" },
2406252726Srpaulo	{ "save_config", wpa_cli_cmd_save_config, NULL,
2407252726Srpaulo	  cli_cmd_flag_none,
2408189251Ssam	  "= save the current configuration" },
2409252726Srpaulo	{ "disconnect", wpa_cli_cmd_disconnect, NULL,
2410189251Ssam	  cli_cmd_flag_none,
2411189251Ssam	  "= disconnect and wait for reassociate/reconnect command before\n"
2412189251Ssam	  "  connecting" },
2413252726Srpaulo	{ "reconnect", wpa_cli_cmd_reconnect, NULL,
2414189251Ssam	  cli_cmd_flag_none,
2415189251Ssam	  "= like reassociate, but only takes effect if already disconnected"
2416189251Ssam	},
2417252726Srpaulo	{ "scan", wpa_cli_cmd_scan, NULL,
2418189251Ssam	  cli_cmd_flag_none,
2419189251Ssam	  "= request new BSS scan" },
2420252726Srpaulo	{ "scan_results", wpa_cli_cmd_scan_results, NULL,
2421189251Ssam	  cli_cmd_flag_none,
2422189251Ssam	  "= get latest scan results" },
2423252726Srpaulo	{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2424189251Ssam	  cli_cmd_flag_none,
2425189251Ssam	  "<<idx> | <bssid>> = get detailed scan result info" },
2426252726Srpaulo	{ "get_capability", wpa_cli_cmd_get_capability, NULL,
2427189251Ssam	  cli_cmd_flag_none,
2428252726Srpaulo	  "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
2429252726Srpaulo	  "= get capabilies" },
2430252726Srpaulo	{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2431189251Ssam	  cli_cmd_flag_none,
2432189251Ssam	  "= force wpa_supplicant to re-read its configuration file" },
2433252726Srpaulo	{ "terminate", wpa_cli_cmd_terminate, NULL,
2434189251Ssam	  cli_cmd_flag_none,
2435189251Ssam	  "= terminate wpa_supplicant" },
2436252726Srpaulo	{ "interface_add", wpa_cli_cmd_interface_add, NULL,
2437189251Ssam	  cli_cmd_flag_none,
2438189251Ssam	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2439189251Ssam	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2440189251Ssam	  "  are optional" },
2441252726Srpaulo	{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2442189251Ssam	  cli_cmd_flag_none,
2443189251Ssam	  "<ifname> = removes the interface" },
2444252726Srpaulo	{ "interface_list", wpa_cli_cmd_interface_list, NULL,
2445189251Ssam	  cli_cmd_flag_none,
2446189251Ssam	  "= list available interfaces" },
2447252726Srpaulo	{ "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2448189251Ssam	  cli_cmd_flag_none,
2449189251Ssam	  "<value> = set ap_scan parameter" },
2450252726Srpaulo	{ "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2451189251Ssam	  cli_cmd_flag_none,
2452252726Srpaulo	  "<value> = set scan_interval parameter (in seconds)" },
2453252726Srpaulo	{ "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2454252726Srpaulo	  cli_cmd_flag_none,
2455252726Srpaulo	  "<value> = set BSS expiration age parameter" },
2456252726Srpaulo	{ "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2457252726Srpaulo	  cli_cmd_flag_none,
2458252726Srpaulo	  "<value> = set BSS expiration scan count parameter" },
2459252726Srpaulo	{ "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2460252726Srpaulo	  cli_cmd_flag_none,
2461252726Srpaulo	  "<value> = set BSS flush age (0 by default)" },
2462252726Srpaulo	{ "stkstart", wpa_cli_cmd_stkstart, NULL,
2463252726Srpaulo	  cli_cmd_flag_none,
2464189251Ssam	  "<addr> = request STK negotiation with <addr>" },
2465252726Srpaulo	{ "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2466189251Ssam	  cli_cmd_flag_none,
2467189251Ssam	  "<addr> = request over-the-DS FT with <addr>" },
2468252726Srpaulo	{ "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2469189251Ssam	  cli_cmd_flag_none,
2470189251Ssam	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2471252726Srpaulo	{ "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2472189251Ssam	  cli_cmd_flag_sensitive,
2473189251Ssam	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2474189251Ssam	  "hardcoded)" },
2475252726Srpaulo	{ "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2476214734Srpaulo	  cli_cmd_flag_sensitive,
2477252726Srpaulo	  "<PIN> = verify PIN checksum" },
2478252726Srpaulo	{ "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2479252726Srpaulo	  "Cancels the pending WPS operation" },
2480252726Srpaulo#ifdef CONFIG_WPS_NFC
2481252726Srpaulo	{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2482252726Srpaulo	  cli_cmd_flag_none,
2483252726Srpaulo	  "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2484252726Srpaulo	{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2485252726Srpaulo	  cli_cmd_flag_none,
2486252726Srpaulo	  "<WPS|NDEF> = create password token" },
2487252726Srpaulo	{ "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2488189251Ssam	  cli_cmd_flag_sensitive,
2489252726Srpaulo	  "<hexdump of payload> = report read NFC tag with WPS data" },
2490252726Srpaulo	{ "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2491252726Srpaulo	  cli_cmd_flag_none,
2492252726Srpaulo	  "<NDEF> <WPS> = create NFC handover request" },
2493252726Srpaulo	{ "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2494252726Srpaulo	  cli_cmd_flag_none,
2495252726Srpaulo	  "<NDEF> <WPS> = create NFC handover select" },
2496252726Srpaulo	{ "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2497252726Srpaulo	  cli_cmd_flag_none,
2498252726Srpaulo	  "<hexdump of payload> = report received NFC handover request" },
2499252726Srpaulo	{ "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2500252726Srpaulo	  cli_cmd_flag_none,
2501252726Srpaulo	  "<hexdump of payload> = report received NFC handover select" },
2502252726Srpaulo#endif /* CONFIG_WPS_NFC */
2503252726Srpaulo	{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2504252726Srpaulo	  cli_cmd_flag_sensitive,
2505189251Ssam	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2506252726Srpaulo	{ "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2507252726Srpaulo	  cli_cmd_flag_sensitive,
2508252726Srpaulo	  "[params..] = enable/disable AP PIN" },
2509252726Srpaulo	{ "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2510214734Srpaulo	  cli_cmd_flag_none,
2511252726Srpaulo	  "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2512252726Srpaulo	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2513214734Srpaulo	  cli_cmd_flag_none,
2514214734Srpaulo	  "= stop Wi-Fi Protected Setup External Registrar" },
2515252726Srpaulo	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2516214734Srpaulo	  cli_cmd_flag_sensitive,
2517214734Srpaulo	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2518252726Srpaulo	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2519214734Srpaulo	  cli_cmd_flag_none,
2520214734Srpaulo	  "<UUID> = accept an Enrollee PBC using External Registrar" },
2521252726Srpaulo	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2522214734Srpaulo	  cli_cmd_flag_sensitive,
2523214734Srpaulo	  "<UUID> <PIN> = learn AP configuration" },
2524252726Srpaulo	{ "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2525214734Srpaulo	  cli_cmd_flag_none,
2526252726Srpaulo	  "<UUID> <network id> = set AP configuration for enrolling" },
2527252726Srpaulo	{ "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2528252726Srpaulo	  cli_cmd_flag_sensitive,
2529252726Srpaulo	  "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2530252726Srpaulo#ifdef CONFIG_WPS_NFC
2531252726Srpaulo	{ "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2532252726Srpaulo	  cli_cmd_flag_none,
2533252726Srpaulo	  "<WPS/NDEF> <UUID> = build NFC configuration token" },
2534252726Srpaulo#endif /* CONFIG_WPS_NFC */
2535252726Srpaulo	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2536252726Srpaulo	  cli_cmd_flag_none,
2537214734Srpaulo	  "<addr> = request RSN authentication with <addr> in IBSS" },
2538214734Srpaulo#ifdef CONFIG_AP
2539252726Srpaulo	{ "sta", wpa_cli_cmd_sta, NULL,
2540214734Srpaulo	  cli_cmd_flag_none,
2541214734Srpaulo	  "<addr> = get information about an associated station (AP)" },
2542252726Srpaulo	{ "all_sta", wpa_cli_cmd_all_sta, NULL,
2543214734Srpaulo	  cli_cmd_flag_none,
2544214734Srpaulo	  "= get information about all associated stations (AP)" },
2545252726Srpaulo	{ "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2546252726Srpaulo	  cli_cmd_flag_none,
2547252726Srpaulo	  "<addr> = deauthenticate a station" },
2548252726Srpaulo	{ "disassociate", wpa_cli_cmd_disassociate, NULL,
2549252726Srpaulo	  cli_cmd_flag_none,
2550252726Srpaulo	  "<addr> = disassociate a station" },
2551214734Srpaulo#endif /* CONFIG_AP */
2552252726Srpaulo	{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2553214734Srpaulo	  "= notification of suspend/hibernate" },
2554252726Srpaulo	{ "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2555214734Srpaulo	  "= notification of resume/thaw" },
2556252726Srpaulo	{ "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2557214734Srpaulo	  "= drop SA without deauth/disassoc (test command)" },
2558252726Srpaulo	{ "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2559214734Srpaulo	  cli_cmd_flag_none,
2560214734Srpaulo	  "<addr> = roam to the specified BSS" },
2561252726Srpaulo#ifdef CONFIG_P2P
2562252726Srpaulo	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2563252726Srpaulo	  cli_cmd_flag_none,
2564252726Srpaulo	  "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2565252726Srpaulo	{ "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2566252726Srpaulo	  "= stop P2P Devices search" },
2567252726Srpaulo	{ "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2568252726Srpaulo	  cli_cmd_flag_none,
2569252726Srpaulo	  "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2570252726Srpaulo	{ "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2571252726Srpaulo	  "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2572252726Srpaulo	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2573252726Srpaulo	  wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2574252726Srpaulo	  "<ifname> = remove P2P group interface (terminate group if GO)" },
2575252726Srpaulo	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2576252726Srpaulo	  "[ht40] = add a new P2P group (local end as GO)" },
2577252726Srpaulo	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2578252726Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2579252726Srpaulo	  "<addr> <method> = request provisioning discovery" },
2580252726Srpaulo	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2581252726Srpaulo	  cli_cmd_flag_none,
2582252726Srpaulo	  "= get the passphrase for a group (GO only)" },
2583252726Srpaulo	{ "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2584252726Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2585252726Srpaulo	  "<addr> <TLVs> = schedule service discovery request" },
2586252726Srpaulo	{ "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2587252726Srpaulo	  NULL, cli_cmd_flag_none,
2588252726Srpaulo	  "<id> = cancel pending service discovery request" },
2589252726Srpaulo	{ "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2590252726Srpaulo	  cli_cmd_flag_none,
2591252726Srpaulo	  "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2592252726Srpaulo	{ "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2593252726Srpaulo	  cli_cmd_flag_none,
2594252726Srpaulo	  "= indicate change in local services" },
2595252726Srpaulo	{ "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2596252726Srpaulo	  cli_cmd_flag_none,
2597252726Srpaulo	  "<external> = set external processing of service discovery" },
2598252726Srpaulo	{ "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2599252726Srpaulo	  cli_cmd_flag_none,
2600252726Srpaulo	  "= remove all stored service entries" },
2601252726Srpaulo	{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2602252726Srpaulo	  cli_cmd_flag_none,
2603252726Srpaulo	  "<bonjour|upnp> <query|version> <response|service> = add a local "
2604252726Srpaulo	  "service" },
2605252726Srpaulo	{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2606252726Srpaulo	  cli_cmd_flag_none,
2607252726Srpaulo	  "<bonjour|upnp> <query|version> [|service] = remove a local "
2608252726Srpaulo	  "service" },
2609252726Srpaulo	{ "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2610252726Srpaulo	  cli_cmd_flag_none,
2611252726Srpaulo	  "<addr> = reject connection attempts from a specific peer" },
2612252726Srpaulo	{ "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2613252726Srpaulo	  cli_cmd_flag_none,
2614252726Srpaulo	  "<cmd> [peer=addr] = invite peer" },
2615252726Srpaulo	{ "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2616252726Srpaulo	  "[discovered] = list known (optionally, only fully discovered) P2P "
2617252726Srpaulo	  "peers" },
2618252726Srpaulo	{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2619252726Srpaulo	  cli_cmd_flag_none,
2620252726Srpaulo	  "<address> = show information about known P2P peer" },
2621252726Srpaulo	{ "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
2622252726Srpaulo	  "<field> <value> = set a P2P parameter" },
2623252726Srpaulo	{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2624252726Srpaulo	  "= flush P2P state" },
2625252726Srpaulo	{ "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2626252726Srpaulo	  "= cancel P2P group formation" },
2627252726Srpaulo	{ "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2628252726Srpaulo	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2629252726Srpaulo	  "<address> = unauthorize a peer" },
2630252726Srpaulo	{ "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2631252726Srpaulo	  cli_cmd_flag_none,
2632252726Srpaulo	  "[<duration> <interval>] [<duration> <interval>] = request GO "
2633252726Srpaulo	  "presence" },
2634252726Srpaulo	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2635252726Srpaulo	  cli_cmd_flag_none,
2636252726Srpaulo	  "[<period> <interval>] = set extended listen timing" },
2637252726Srpaulo#endif /* CONFIG_P2P */
2638252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY
2639252726Srpaulo	{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2640252726Srpaulo	  cli_cmd_flag_none,
2641252726Srpaulo	  "<subelem> [contents] = set Wi-Fi Display subelement" },
2642252726Srpaulo	{ "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2643252726Srpaulo	  cli_cmd_flag_none,
2644252726Srpaulo	  "<subelem> = get Wi-Fi Display subelement" },
2645252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */
2646252726Srpaulo#ifdef CONFIG_INTERWORKING
2647252726Srpaulo	{ "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
2648252726Srpaulo	  "= fetch ANQP information for all APs" },
2649252726Srpaulo	{ "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2650252726Srpaulo	  cli_cmd_flag_none,
2651252726Srpaulo	  "= stop fetch_anqp operation" },
2652252726Srpaulo	{ "interworking_select", wpa_cli_cmd_interworking_select, NULL,
2653252726Srpaulo	  cli_cmd_flag_none,
2654252726Srpaulo	  "[auto] = perform Interworking network selection" },
2655252726Srpaulo	{ "interworking_connect", wpa_cli_cmd_interworking_connect,
2656252726Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
2657252726Srpaulo	  "<BSSID> = connect using Interworking credentials" },
2658252726Srpaulo	{ "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2659252726Srpaulo	  cli_cmd_flag_none,
2660252726Srpaulo	  "<addr> <info id>[,<info id>]... = request ANQP information" },
2661252726Srpaulo	{ "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2662252726Srpaulo	  cli_cmd_flag_none,
2663252726Srpaulo	  "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2664252726Srpaulo	{ "gas_response_get", wpa_cli_cmd_gas_response_get,
2665252726Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
2666252726Srpaulo	  "<addr> <dialog token> [start,len] = Fetch last GAS response" },
2667252726Srpaulo#endif /* CONFIG_INTERWORKING */
2668252726Srpaulo#ifdef CONFIG_HS20
2669252726Srpaulo	{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2670252726Srpaulo	  cli_cmd_flag_none,
2671252726Srpaulo	  "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2672252726Srpaulo	},
2673252726Srpaulo	{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
2674252726Srpaulo	  wpa_cli_complete_bss, cli_cmd_flag_none,
2675252726Srpaulo	  "<addr> <home realm> = get HS20 nai home realm list" },
2676252726Srpaulo#endif /* CONFIG_HS20 */
2677252726Srpaulo	{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2678252726Srpaulo	  cli_cmd_flag_none,
2679252726Srpaulo	  "<0/1> = disable/enable automatic reconnection" },
2680252726Srpaulo	{ "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
2681252726Srpaulo	  cli_cmd_flag_none,
2682252726Srpaulo	  "<addr> = request TDLS discovery with <addr>" },
2683252726Srpaulo	{ "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
2684252726Srpaulo	  cli_cmd_flag_none,
2685252726Srpaulo	  "<addr> = request TDLS setup with <addr>" },
2686252726Srpaulo	{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
2687252726Srpaulo	  cli_cmd_flag_none,
2688252726Srpaulo	  "<addr> = tear down TDLS with <addr>" },
2689252726Srpaulo	{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
2690252726Srpaulo	  cli_cmd_flag_none,
2691252726Srpaulo	  "= get signal parameters" },
2692252726Srpaulo	{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
2693252726Srpaulo	  cli_cmd_flag_none,
2694252726Srpaulo	  "= get TX/RX packet counters" },
2695252726Srpaulo	{ "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2696252726Srpaulo	  cli_cmd_flag_none,
2697252726Srpaulo	  "= trigger IEEE 802.1X/EAPOL reauthentication" },
2698252726Srpaulo#ifdef CONFIG_AUTOSCAN
2699252726Srpaulo	{ "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2700252726Srpaulo	  "[params] = Set or unset (if none) autoscan parameters" },
2701252726Srpaulo#endif /* CONFIG_AUTOSCAN */
2702252726Srpaulo#ifdef CONFIG_WNM
2703252726Srpaulo	{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2704252726Srpaulo	  "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2705252726Srpaulo#endif /* CONFIG_WNM */
2706252726Srpaulo	{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2707252726Srpaulo	  "<params..> = Sent unprocessed command" },
2708252726Srpaulo	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
2709189251Ssam};
2710189251Ssam
2711189251Ssam
2712189251Ssam/*
2713189251Ssam * Prints command usage, lines are padded with the specified string.
2714189251Ssam */
2715189251Ssamstatic void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2716189251Ssam{
2717189251Ssam	char c;
2718189251Ssam	size_t n;
2719189251Ssam
2720189251Ssam	printf("%s%s ", pad, cmd->cmd);
2721189251Ssam	for (n = 0; (c = cmd->usage[n]); n++) {
2722189251Ssam		printf("%c", c);
2723189251Ssam		if (c == '\n')
2724189251Ssam			printf("%s", pad);
2725189251Ssam	}
2726189251Ssam	printf("\n");
2727189251Ssam}
2728189251Ssam
2729189251Ssam
2730252726Srpaulostatic void print_help(const char *cmd)
2731189251Ssam{
2732189251Ssam	int n;
2733189251Ssam	printf("commands:\n");
2734252726Srpaulo	for (n = 0; wpa_cli_commands[n].cmd; n++) {
2735252726Srpaulo		if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2736252726Srpaulo			print_cmd_help(&wpa_cli_commands[n], "  ");
2737252726Srpaulo	}
2738189251Ssam}
2739189251Ssam
2740189251Ssam
2741252726Srpaulostatic int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2742189251Ssam{
2743189251Ssam	const char *c, *delim;
2744189251Ssam	int n;
2745189251Ssam	size_t len;
2746189251Ssam
2747189251Ssam	delim = os_strchr(cmd, ' ');
2748189251Ssam	if (delim)
2749189251Ssam		len = delim - cmd;
2750189251Ssam	else
2751189251Ssam		len = os_strlen(cmd);
2752189251Ssam
2753189251Ssam	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2754189251Ssam		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2755189251Ssam			return (wpa_cli_commands[n].flags &
2756189251Ssam				cli_cmd_flag_sensitive);
2757189251Ssam	}
2758189251Ssam	return 0;
2759189251Ssam}
2760189251Ssam
2761189251Ssam
2762252726Srpaulostatic char ** wpa_list_cmd_list(void)
2763252726Srpaulo{
2764252726Srpaulo	char **res;
2765252726Srpaulo	int i, count;
2766252726Srpaulo
2767252726Srpaulo	count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
2768252726Srpaulo	res = os_calloc(count, sizeof(char *));
2769252726Srpaulo	if (res == NULL)
2770252726Srpaulo		return NULL;
2771252726Srpaulo
2772252726Srpaulo	for (i = 0; wpa_cli_commands[i].cmd; i++) {
2773252726Srpaulo		res[i] = os_strdup(wpa_cli_commands[i].cmd);
2774252726Srpaulo		if (res[i] == NULL)
2775252726Srpaulo			break;
2776252726Srpaulo	}
2777252726Srpaulo
2778252726Srpaulo	return res;
2779252726Srpaulo}
2780252726Srpaulo
2781252726Srpaulo
2782252726Srpaulostatic char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2783252726Srpaulo				      int pos)
2784252726Srpaulo{
2785252726Srpaulo	int i;
2786252726Srpaulo
2787252726Srpaulo	for (i = 0; wpa_cli_commands[i].cmd; i++) {
2788252726Srpaulo		if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
2789252726Srpaulo			if (wpa_cli_commands[i].completion)
2790252726Srpaulo				return wpa_cli_commands[i].completion(str,
2791252726Srpaulo								      pos);
2792252726Srpaulo			edit_clear_line();
2793252726Srpaulo			printf("\r%s\n", wpa_cli_commands[i].usage);
2794252726Srpaulo			edit_redraw();
2795252726Srpaulo			break;
2796252726Srpaulo		}
2797252726Srpaulo	}
2798252726Srpaulo
2799252726Srpaulo	return NULL;
2800252726Srpaulo}
2801252726Srpaulo
2802252726Srpaulo
2803252726Srpaulostatic char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2804252726Srpaulo{
2805252726Srpaulo	char **res;
2806252726Srpaulo	const char *end;
2807252726Srpaulo	char *cmd;
2808252726Srpaulo
2809252726Srpaulo	end = os_strchr(str, ' ');
2810252726Srpaulo	if (end == NULL || str + pos < end)
2811252726Srpaulo		return wpa_list_cmd_list();
2812252726Srpaulo
2813252726Srpaulo	cmd = os_malloc(pos + 1);
2814252726Srpaulo	if (cmd == NULL)
2815252726Srpaulo		return NULL;
2816252726Srpaulo	os_memcpy(cmd, str, pos);
2817252726Srpaulo	cmd[end - str] = '\0';
2818252726Srpaulo	res = wpa_cli_cmd_completion(cmd, str, pos);
2819252726Srpaulo	os_free(cmd);
2820252726Srpaulo	return res;
2821252726Srpaulo}
2822252726Srpaulo
2823252726Srpaulo
2824189251Ssamstatic int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2825189251Ssam{
2826189251Ssam	struct wpa_cli_cmd *cmd, *match = NULL;
2827189251Ssam	int count;
2828189251Ssam	int ret = 0;
2829189251Ssam
2830189251Ssam	count = 0;
2831189251Ssam	cmd = wpa_cli_commands;
2832189251Ssam	while (cmd->cmd) {
2833189251Ssam		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2834189251Ssam		{
2835189251Ssam			match = cmd;
2836189251Ssam			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2837189251Ssam				/* we have an exact match */
2838189251Ssam				count = 1;
2839189251Ssam				break;
2840189251Ssam			}
2841189251Ssam			count++;
2842189251Ssam		}
2843189251Ssam		cmd++;
2844189251Ssam	}
2845189251Ssam
2846189251Ssam	if (count > 1) {
2847189251Ssam		printf("Ambiguous command '%s'; possible commands:", argv[0]);
2848189251Ssam		cmd = wpa_cli_commands;
2849189251Ssam		while (cmd->cmd) {
2850189251Ssam			if (os_strncasecmp(cmd->cmd, argv[0],
2851189251Ssam					   os_strlen(argv[0])) == 0) {
2852189251Ssam				printf(" %s", cmd->cmd);
2853189251Ssam			}
2854189251Ssam			cmd++;
2855189251Ssam		}
2856189251Ssam		printf("\n");
2857189251Ssam		ret = 1;
2858189251Ssam	} else if (count == 0) {
2859189251Ssam		printf("Unknown command '%s'\n", argv[0]);
2860189251Ssam		ret = 1;
2861189251Ssam	} else {
2862189251Ssam		ret = match->handler(ctrl, argc - 1, &argv[1]);
2863189251Ssam	}
2864189251Ssam
2865189251Ssam	return ret;
2866189251Ssam}
2867189251Ssam
2868189251Ssam
2869189251Ssamstatic int str_match(const char *a, const char *b)
2870189251Ssam{
2871189251Ssam	return os_strncmp(a, b, os_strlen(b)) == 0;
2872189251Ssam}
2873189251Ssam
2874189251Ssam
2875189251Ssamstatic int wpa_cli_exec(const char *program, const char *arg1,
2876189251Ssam			const char *arg2)
2877189251Ssam{
2878189251Ssam	char *cmd;
2879189251Ssam	size_t len;
2880189251Ssam	int res;
2881189251Ssam	int ret = 0;
2882189251Ssam
2883189251Ssam	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2884189251Ssam	cmd = os_malloc(len);
2885189251Ssam	if (cmd == NULL)
2886189251Ssam		return -1;
2887189251Ssam	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2888189251Ssam	if (res < 0 || (size_t) res >= len) {
2889189251Ssam		os_free(cmd);
2890189251Ssam		return -1;
2891189251Ssam	}
2892189251Ssam	cmd[len - 1] = '\0';
2893189251Ssam#ifndef _WIN32_WCE
2894189251Ssam	if (system(cmd) < 0)
2895189251Ssam		ret = -1;
2896189251Ssam#endif /* _WIN32_WCE */
2897189251Ssam	os_free(cmd);
2898189251Ssam
2899189251Ssam	return ret;
2900189251Ssam}
2901189251Ssam
2902189251Ssam
2903189251Ssamstatic void wpa_cli_action_process(const char *msg)
2904189251Ssam{
2905189251Ssam	const char *pos;
2906189251Ssam	char *copy = NULL, *id, *pos2;
2907189251Ssam
2908189251Ssam	pos = msg;
2909189251Ssam	if (*pos == '<') {
2910189251Ssam		/* skip priority */
2911189251Ssam		pos = os_strchr(pos, '>');
2912189251Ssam		if (pos)
2913189251Ssam			pos++;
2914189251Ssam		else
2915189251Ssam			pos = msg;
2916189251Ssam	}
2917189251Ssam
2918189251Ssam	if (str_match(pos, WPA_EVENT_CONNECTED)) {
2919189251Ssam		int new_id = -1;
2920189251Ssam		os_unsetenv("WPA_ID");
2921189251Ssam		os_unsetenv("WPA_ID_STR");
2922189251Ssam		os_unsetenv("WPA_CTRL_DIR");
2923189251Ssam
2924189251Ssam		pos = os_strstr(pos, "[id=");
2925189251Ssam		if (pos)
2926189251Ssam			copy = os_strdup(pos + 4);
2927189251Ssam
2928189251Ssam		if (copy) {
2929189251Ssam			pos2 = id = copy;
2930189251Ssam			while (*pos2 && *pos2 != ' ')
2931189251Ssam				pos2++;
2932189251Ssam			*pos2++ = '\0';
2933189251Ssam			new_id = atoi(id);
2934189251Ssam			os_setenv("WPA_ID", id, 1);
2935189251Ssam			while (*pos2 && *pos2 != '=')
2936189251Ssam				pos2++;
2937189251Ssam			if (*pos2 == '=')
2938189251Ssam				pos2++;
2939189251Ssam			id = pos2;
2940189251Ssam			while (*pos2 && *pos2 != ']')
2941189251Ssam				pos2++;
2942189251Ssam			*pos2 = '\0';
2943189251Ssam			os_setenv("WPA_ID_STR", id, 1);
2944189251Ssam			os_free(copy);
2945189251Ssam		}
2946189251Ssam
2947189251Ssam		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2948189251Ssam
2949189251Ssam		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2950189251Ssam			wpa_cli_connected = 1;
2951189251Ssam			wpa_cli_last_id = new_id;
2952189251Ssam			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2953189251Ssam		}
2954189251Ssam	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2955189251Ssam		if (wpa_cli_connected) {
2956189251Ssam			wpa_cli_connected = 0;
2957189251Ssam			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2958189251Ssam		}
2959252726Srpaulo	} else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2960252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2961252726Srpaulo	} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2962252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2963252726Srpaulo	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2964252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2965252726Srpaulo	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2966252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2967252726Srpaulo	} else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
2968252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2969252726Srpaulo	} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2970252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2971252726Srpaulo	} else if (str_match(pos, WPS_EVENT_FAIL)) {
2972252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2973252726Srpaulo	} else if (str_match(pos, AP_STA_CONNECTED)) {
2974252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2975252726Srpaulo	} else if (str_match(pos, AP_STA_DISCONNECTED)) {
2976252726Srpaulo		wpa_cli_exec(action_file, ctrl_ifname, pos);
2977189251Ssam	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2978189251Ssam		printf("wpa_supplicant is terminating - stop monitoring\n");
2979189251Ssam		wpa_cli_quit = 1;
2980189251Ssam	}
2981189251Ssam}
2982189251Ssam
2983189251Ssam
2984189251Ssam#ifndef CONFIG_ANSI_C_EXTRA
2985189251Ssamstatic void wpa_cli_action_cb(char *msg, size_t len)
2986189251Ssam{
2987189251Ssam	wpa_cli_action_process(msg);
2988189251Ssam}
2989189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */
2990189251Ssam
2991189251Ssam
2992189251Ssamstatic void wpa_cli_reconnect(void)
2993189251Ssam{
2994189251Ssam	wpa_cli_close_connection();
2995252726Srpaulo	if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
2996252726Srpaulo		return;
2997252726Srpaulo
2998252726Srpaulo	if (interactive) {
2999252726Srpaulo		edit_clear_line();
3000252726Srpaulo		printf("\rConnection to wpa_supplicant re-established\n");
3001252726Srpaulo		edit_redraw();
3002252726Srpaulo	}
3003189251Ssam}
3004189251Ssam
3005189251Ssam
3006252726Srpaulostatic void cli_event(const char *str)
3007189251Ssam{
3008252726Srpaulo	const char *start, *s;
3009252726Srpaulo
3010252726Srpaulo	start = os_strchr(str, '>');
3011252726Srpaulo	if (start == NULL)
3012252726Srpaulo		return;
3013252726Srpaulo
3014252726Srpaulo	start++;
3015252726Srpaulo
3016252726Srpaulo	if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3017252726Srpaulo		s = os_strchr(start, ' ');
3018252726Srpaulo		if (s == NULL)
3019252726Srpaulo			return;
3020252726Srpaulo		s = os_strchr(s + 1, ' ');
3021252726Srpaulo		if (s == NULL)
3022252726Srpaulo			return;
3023252726Srpaulo		cli_txt_list_add(&bsses, s + 1);
3024252726Srpaulo		return;
3025252726Srpaulo	}
3026252726Srpaulo
3027252726Srpaulo	if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3028252726Srpaulo		s = os_strchr(start, ' ');
3029252726Srpaulo		if (s == NULL)
3030252726Srpaulo			return;
3031252726Srpaulo		s = os_strchr(s + 1, ' ');
3032252726Srpaulo		if (s == NULL)
3033252726Srpaulo			return;
3034252726Srpaulo		cli_txt_list_del_addr(&bsses, s + 1);
3035252726Srpaulo		return;
3036252726Srpaulo	}
3037252726Srpaulo
3038252726Srpaulo#ifdef CONFIG_P2P
3039252726Srpaulo	if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3040252726Srpaulo		s = os_strstr(start, " p2p_dev_addr=");
3041252726Srpaulo		if (s == NULL)
3042252726Srpaulo			return;
3043252726Srpaulo		cli_txt_list_add_addr(&p2p_peers, s + 14);
3044252726Srpaulo		return;
3045252726Srpaulo	}
3046252726Srpaulo
3047252726Srpaulo	if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3048252726Srpaulo		s = os_strstr(start, " p2p_dev_addr=");
3049252726Srpaulo		if (s == NULL)
3050252726Srpaulo			return;
3051252726Srpaulo		cli_txt_list_del_addr(&p2p_peers, s + 14);
3052252726Srpaulo		return;
3053252726Srpaulo	}
3054252726Srpaulo
3055252726Srpaulo	if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3056252726Srpaulo		s = os_strchr(start, ' ');
3057252726Srpaulo		if (s == NULL)
3058252726Srpaulo			return;
3059252726Srpaulo		cli_txt_list_add_word(&p2p_groups, s + 1);
3060252726Srpaulo		return;
3061252726Srpaulo	}
3062252726Srpaulo
3063252726Srpaulo	if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3064252726Srpaulo		s = os_strchr(start, ' ');
3065252726Srpaulo		if (s == NULL)
3066252726Srpaulo			return;
3067252726Srpaulo		cli_txt_list_del_word(&p2p_groups, s + 1);
3068252726Srpaulo		return;
3069252726Srpaulo	}
3070252726Srpaulo#endif /* CONFIG_P2P */
3071252726Srpaulo}
3072252726Srpaulo
3073252726Srpaulo
3074252726Srpaulostatic int check_terminating(const char *msg)
3075252726Srpaulo{
3076252726Srpaulo	const char *pos = msg;
3077252726Srpaulo
3078252726Srpaulo	if (*pos == '<') {
3079252726Srpaulo		/* skip priority */
3080252726Srpaulo		pos = os_strchr(pos, '>');
3081252726Srpaulo		if (pos)
3082252726Srpaulo			pos++;
3083252726Srpaulo		else
3084252726Srpaulo			pos = msg;
3085252726Srpaulo	}
3086252726Srpaulo
3087252726Srpaulo	if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3088252726Srpaulo		edit_clear_line();
3089252726Srpaulo		printf("\rConnection to wpa_supplicant lost - trying to "
3090252726Srpaulo		       "reconnect\n");
3091252726Srpaulo		edit_redraw();
3092252726Srpaulo		wpa_cli_attached = 0;
3093252726Srpaulo		wpa_cli_close_connection();
3094252726Srpaulo		return 1;
3095252726Srpaulo	}
3096252726Srpaulo
3097252726Srpaulo	return 0;
3098252726Srpaulo}
3099252726Srpaulo
3100252726Srpaulo
3101252726Srpaulostatic void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3102252726Srpaulo{
3103189251Ssam	if (ctrl_conn == NULL) {
3104189251Ssam		wpa_cli_reconnect();
3105189251Ssam		return;
3106189251Ssam	}
3107189251Ssam	while (wpa_ctrl_pending(ctrl) > 0) {
3108189251Ssam		char buf[256];
3109189251Ssam		size_t len = sizeof(buf) - 1;
3110189251Ssam		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3111189251Ssam			buf[len] = '\0';
3112189251Ssam			if (action_monitor)
3113189251Ssam				wpa_cli_action_process(buf);
3114189251Ssam			else {
3115252726Srpaulo				cli_event(buf);
3116252726Srpaulo				if (wpa_cli_show_event(buf)) {
3117252726Srpaulo					edit_clear_line();
3118252726Srpaulo					printf("\r%s\n", buf);
3119252726Srpaulo					edit_redraw();
3120252726Srpaulo				}
3121252726Srpaulo
3122252726Srpaulo				if (interactive && check_terminating(buf) > 0)
3123252726Srpaulo					return;
3124189251Ssam			}
3125189251Ssam		} else {
3126189251Ssam			printf("Could not read pending message.\n");
3127189251Ssam			break;
3128189251Ssam		}
3129189251Ssam	}
3130189251Ssam
3131189251Ssam	if (wpa_ctrl_pending(ctrl) < 0) {
3132189251Ssam		printf("Connection to wpa_supplicant lost - trying to "
3133189251Ssam		       "reconnect\n");
3134189251Ssam		wpa_cli_reconnect();
3135189251Ssam	}
3136189251Ssam}
3137189251Ssam
3138252726Srpaulo#define max_args 10
3139189251Ssam
3140252726Srpaulostatic int tokenize_cmd(char *cmd, char *argv[])
3141189251Ssam{
3142252726Srpaulo	char *pos;
3143252726Srpaulo	int argc = 0;
3144189251Ssam
3145252726Srpaulo	pos = cmd;
3146252726Srpaulo	for (;;) {
3147252726Srpaulo		while (*pos == ' ')
3148252726Srpaulo			pos++;
3149252726Srpaulo		if (*pos == '\0')
3150252726Srpaulo			break;
3151252726Srpaulo		argv[argc] = pos;
3152252726Srpaulo		argc++;
3153252726Srpaulo		if (argc == max_args)
3154252726Srpaulo			break;
3155252726Srpaulo		if (*pos == '"') {
3156252726Srpaulo			char *pos2 = os_strrchr(pos, '"');
3157252726Srpaulo			if (pos2)
3158252726Srpaulo				pos = pos2 + 1;
3159252726Srpaulo		}
3160252726Srpaulo		while (*pos != '\0' && *pos != ' ')
3161252726Srpaulo			pos++;
3162252726Srpaulo		if (*pos == ' ')
3163252726Srpaulo			*pos++ = '\0';
3164189251Ssam	}
3165189251Ssam
3166252726Srpaulo	return argc;
3167189251Ssam}
3168189251Ssam
3169189251Ssam
3170252726Srpaulostatic void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3171189251Ssam{
3172252726Srpaulo	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3173252726Srpaulo		printf("Connection to wpa_supplicant lost - trying to "
3174252726Srpaulo		       "reconnect\n");
3175252726Srpaulo		wpa_cli_close_connection();
3176214734Srpaulo	}
3177252726Srpaulo	if (!ctrl_conn)
3178252726Srpaulo		wpa_cli_reconnect();
3179252726Srpaulo	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3180189251Ssam}
3181189251Ssam
3182189251Ssam
3183252726Srpaulostatic void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3184214734Srpaulo{
3185252726Srpaulo	wpa_cli_recv_pending(mon_conn, 0);
3186252726Srpaulo}
3187214734Srpaulo
3188214734Srpaulo
3189252726Srpaulostatic void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3190252726Srpaulo{
3191252726Srpaulo	char *argv[max_args];
3192252726Srpaulo	int argc;
3193252726Srpaulo	argc = tokenize_cmd(cmd, argv);
3194252726Srpaulo	if (argc)
3195252726Srpaulo		wpa_request(ctrl_conn, argc, argv);
3196214734Srpaulo}
3197214734Srpaulo
3198214734Srpaulo
3199252726Srpaulostatic void wpa_cli_edit_eof_cb(void *ctx)
3200189251Ssam{
3201252726Srpaulo	eloop_terminate();
3202189251Ssam}
3203189251Ssam
3204189251Ssam
3205252726Srpaulostatic int warning_displayed = 0;
3206252726Srpaulostatic char *hfile = NULL;
3207252726Srpaulostatic int edit_started = 0;
3208252726Srpaulo
3209252726Srpaulostatic void start_edit(void)
3210189251Ssam{
3211252726Srpaulo	char *home;
3212252726Srpaulo	char *ps = NULL;
3213189251Ssam
3214252726Srpaulo#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3215252726Srpaulo	ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3216252726Srpaulo#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3217189251Ssam
3218189251Ssam	home = getenv("HOME");
3219189251Ssam	if (home) {
3220189251Ssam		const char *fname = ".wpa_cli_history";
3221189251Ssam		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3222189251Ssam		hfile = os_malloc(hfile_len);
3223252726Srpaulo		if (hfile)
3224252726Srpaulo			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3225189251Ssam	}
3226189251Ssam
3227252726Srpaulo	if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3228252726Srpaulo		      wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3229252726Srpaulo		eloop_terminate();
3230252726Srpaulo		return;
3231252726Srpaulo	}
3232189251Ssam
3233252726Srpaulo	edit_started = 1;
3234252726Srpaulo	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3235252726Srpaulo}
3236189251Ssam
3237252726Srpaulo
3238252726Srpaulostatic void try_connection(void *eloop_ctx, void *timeout_ctx)
3239252726Srpaulo{
3240252726Srpaulo	if (ctrl_ifname == NULL)
3241252726Srpaulo		ctrl_ifname = wpa_cli_get_default_ifname();
3242252726Srpaulo
3243252726Srpaulo	if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3244252726Srpaulo		if (!warning_displayed) {
3245252726Srpaulo			printf("Could not connect to wpa_supplicant: "
3246252726Srpaulo			       "%s - re-trying\n", ctrl_ifname);
3247252726Srpaulo			warning_displayed = 1;
3248189251Ssam		}
3249252726Srpaulo		eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3250252726Srpaulo		return;
3251189251Ssam	}
3252252726Srpaulo
3253252726Srpaulo	if (warning_displayed)
3254252726Srpaulo		printf("Connection established.\n");
3255252726Srpaulo
3256252726Srpaulo	start_edit();
3257189251Ssam}
3258189251Ssam
3259189251Ssam
3260252726Srpaulostatic void wpa_cli_interactive(void)
3261252726Srpaulo{
3262252726Srpaulo	printf("\nInteractive mode\n\n");
3263252726Srpaulo
3264252726Srpaulo	eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3265252726Srpaulo	eloop_run();
3266252726Srpaulo	eloop_cancel_timeout(try_connection, NULL, NULL);
3267252726Srpaulo
3268252726Srpaulo	cli_txt_list_flush(&p2p_peers);
3269252726Srpaulo	cli_txt_list_flush(&p2p_groups);
3270252726Srpaulo	cli_txt_list_flush(&bsses);
3271252726Srpaulo	if (edit_started)
3272252726Srpaulo		edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3273252726Srpaulo	os_free(hfile);
3274252726Srpaulo	eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3275252726Srpaulo	wpa_cli_close_connection();
3276252726Srpaulo}
3277252726Srpaulo
3278252726Srpaulo
3279189251Ssamstatic void wpa_cli_action(struct wpa_ctrl *ctrl)
3280189251Ssam{
3281189251Ssam#ifdef CONFIG_ANSI_C_EXTRA
3282189251Ssam	/* TODO: ANSI C version(?) */
3283189251Ssam	printf("Action processing not supported in ANSI C build.\n");
3284189251Ssam#else /* CONFIG_ANSI_C_EXTRA */
3285189251Ssam	fd_set rfds;
3286189251Ssam	int fd, res;
3287189251Ssam	struct timeval tv;
3288189251Ssam	char buf[256]; /* note: large enough to fit in unsolicited messages */
3289189251Ssam	size_t len;
3290189251Ssam
3291189251Ssam	fd = wpa_ctrl_get_fd(ctrl);
3292189251Ssam
3293189251Ssam	while (!wpa_cli_quit) {
3294189251Ssam		FD_ZERO(&rfds);
3295189251Ssam		FD_SET(fd, &rfds);
3296189251Ssam		tv.tv_sec = ping_interval;
3297189251Ssam		tv.tv_usec = 0;
3298189251Ssam		res = select(fd + 1, &rfds, NULL, NULL, &tv);
3299189251Ssam		if (res < 0 && errno != EINTR) {
3300189251Ssam			perror("select");
3301189251Ssam			break;
3302189251Ssam		}
3303189251Ssam
3304189251Ssam		if (FD_ISSET(fd, &rfds))
3305252726Srpaulo			wpa_cli_recv_pending(ctrl, 1);
3306189251Ssam		else {
3307189251Ssam			/* verify that connection is still working */
3308189251Ssam			len = sizeof(buf) - 1;
3309189251Ssam			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3310189251Ssam					     wpa_cli_action_cb) < 0 ||
3311189251Ssam			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3312189251Ssam				printf("wpa_supplicant did not reply to PING "
3313189251Ssam				       "command - exiting\n");
3314189251Ssam				break;
3315189251Ssam			}
3316189251Ssam		}
3317189251Ssam	}
3318189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */
3319189251Ssam}
3320189251Ssam
3321189251Ssam
3322189251Ssamstatic void wpa_cli_cleanup(void)
3323189251Ssam{
3324189251Ssam	wpa_cli_close_connection();
3325189251Ssam	if (pid_file)
3326189251Ssam		os_daemonize_terminate(pid_file);
3327189251Ssam
3328189251Ssam	os_program_deinit();
3329189251Ssam}
3330189251Ssam
3331189251Ssam
3332252726Srpaulostatic void wpa_cli_terminate(int sig, void *ctx)
3333214734Srpaulo{
3334252726Srpaulo	eloop_terminate();
3335214734Srpaulo}
3336214734Srpaulo
3337214734Srpaulo
3338189251Ssamstatic char * wpa_cli_get_default_ifname(void)
3339189251Ssam{
3340189251Ssam	char *ifname = NULL;
3341189251Ssam
3342189251Ssam#ifdef CONFIG_CTRL_IFACE_UNIX
3343189251Ssam	struct dirent *dent;
3344189251Ssam	DIR *dir = opendir(ctrl_iface_dir);
3345252726Srpaulo	if (!dir) {
3346252726Srpaulo#ifdef ANDROID
3347252726Srpaulo		char ifprop[PROPERTY_VALUE_MAX];
3348252726Srpaulo		if (property_get("wifi.interface", ifprop, NULL) != 0) {
3349252726Srpaulo			ifname = os_strdup(ifprop);
3350252726Srpaulo			printf("Using interface '%s'\n", ifname);
3351252726Srpaulo			return ifname;
3352252726Srpaulo		}
3353252726Srpaulo#endif /* ANDROID */
3354189251Ssam		return NULL;
3355252726Srpaulo	}
3356189251Ssam	while ((dent = readdir(dir))) {
3357189251Ssam#ifdef _DIRENT_HAVE_D_TYPE
3358189251Ssam		/*
3359189251Ssam		 * Skip the file if it is not a socket. Also accept
3360189251Ssam		 * DT_UNKNOWN (0) in case the C library or underlying
3361189251Ssam		 * file system does not support d_type.
3362189251Ssam		 */
3363189251Ssam		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3364189251Ssam			continue;
3365189251Ssam#endif /* _DIRENT_HAVE_D_TYPE */
3366189251Ssam		if (os_strcmp(dent->d_name, ".") == 0 ||
3367189251Ssam		    os_strcmp(dent->d_name, "..") == 0)
3368189251Ssam			continue;
3369189251Ssam		printf("Selected interface '%s'\n", dent->d_name);
3370189251Ssam		ifname = os_strdup(dent->d_name);
3371189251Ssam		break;
3372189251Ssam	}
3373189251Ssam	closedir(dir);
3374189251Ssam#endif /* CONFIG_CTRL_IFACE_UNIX */
3375189251Ssam
3376189251Ssam#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3377189251Ssam	char buf[2048], *pos;
3378189251Ssam	size_t len;
3379189251Ssam	struct wpa_ctrl *ctrl;
3380189251Ssam	int ret;
3381189251Ssam
3382189251Ssam	ctrl = wpa_ctrl_open(NULL);
3383189251Ssam	if (ctrl == NULL)
3384189251Ssam		return NULL;
3385189251Ssam
3386189251Ssam	len = sizeof(buf) - 1;
3387189251Ssam	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3388189251Ssam	if (ret >= 0) {
3389189251Ssam		buf[len] = '\0';
3390189251Ssam		pos = os_strchr(buf, '\n');
3391189251Ssam		if (pos)
3392189251Ssam			*pos = '\0';
3393189251Ssam		ifname = os_strdup(buf);
3394189251Ssam	}
3395189251Ssam	wpa_ctrl_close(ctrl);
3396189251Ssam#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3397189251Ssam
3398189251Ssam	return ifname;
3399189251Ssam}
3400189251Ssam
3401189251Ssam
3402189251Ssamint main(int argc, char *argv[])
3403189251Ssam{
3404189251Ssam	int c;
3405189251Ssam	int daemonize = 0;
3406189251Ssam	int ret = 0;
3407189251Ssam	const char *global = NULL;
3408189251Ssam
3409189251Ssam	if (os_program_init())
3410189251Ssam		return -1;
3411189251Ssam
3412189251Ssam	for (;;) {
3413189251Ssam		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3414189251Ssam		if (c < 0)
3415189251Ssam			break;
3416189251Ssam		switch (c) {
3417189251Ssam		case 'a':
3418189251Ssam			action_file = optarg;
3419189251Ssam			break;
3420189251Ssam		case 'B':
3421189251Ssam			daemonize = 1;
3422189251Ssam			break;
3423189251Ssam		case 'g':
3424189251Ssam			global = optarg;
3425189251Ssam			break;
3426189251Ssam		case 'G':
3427189251Ssam			ping_interval = atoi(optarg);
3428189251Ssam			break;
3429189251Ssam		case 'h':
3430189251Ssam			usage();
3431189251Ssam			return 0;
3432189251Ssam		case 'v':
3433189251Ssam			printf("%s\n", wpa_cli_version);
3434189251Ssam			return 0;
3435189251Ssam		case 'i':
3436189251Ssam			os_free(ctrl_ifname);
3437189251Ssam			ctrl_ifname = os_strdup(optarg);
3438189251Ssam			break;
3439189251Ssam		case 'p':
3440189251Ssam			ctrl_iface_dir = optarg;
3441189251Ssam			break;
3442189251Ssam		case 'P':
3443189251Ssam			pid_file = optarg;
3444189251Ssam			break;
3445189251Ssam		default:
3446189251Ssam			usage();
3447189251Ssam			return -1;
3448189251Ssam		}
3449189251Ssam	}
3450189251Ssam
3451189251Ssam	interactive = (argc == optind) && (action_file == NULL);
3452189251Ssam
3453189251Ssam	if (interactive)
3454189251Ssam		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3455189251Ssam
3456252726Srpaulo	if (eloop_init())
3457252726Srpaulo		return -1;
3458252726Srpaulo
3459189251Ssam	if (global) {
3460189251Ssam#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3461189251Ssam		ctrl_conn = wpa_ctrl_open(NULL);
3462189251Ssam#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3463189251Ssam		ctrl_conn = wpa_ctrl_open(global);
3464189251Ssam#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3465189251Ssam		if (ctrl_conn == NULL) {
3466252726Srpaulo			fprintf(stderr, "Failed to connect to wpa_supplicant "
3467252726Srpaulo				"global interface: %s  error: %s\n",
3468252726Srpaulo				global, strerror(errno));
3469189251Ssam			return -1;
3470189251Ssam		}
3471189251Ssam	}
3472189251Ssam
3473252726Srpaulo	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
3474189251Ssam
3475214734Srpaulo	if (ctrl_ifname == NULL)
3476214734Srpaulo		ctrl_ifname = wpa_cli_get_default_ifname();
3477214734Srpaulo
3478214734Srpaulo	if (interactive) {
3479252726Srpaulo		wpa_cli_interactive();
3480214734Srpaulo	} else {
3481214734Srpaulo		if (!global &&
3482214734Srpaulo		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3483252726Srpaulo			fprintf(stderr, "Failed to connect to non-global "
3484252726Srpaulo				"ctrl_ifname: %s  error: %s\n",
3485252726Srpaulo				ctrl_ifname, strerror(errno));
3486214734Srpaulo			return -1;
3487214734Srpaulo		}
3488214734Srpaulo
3489214734Srpaulo		if (action_file) {
3490214734Srpaulo			if (wpa_ctrl_attach(ctrl_conn) == 0) {
3491214734Srpaulo				wpa_cli_attached = 1;
3492214734Srpaulo			} else {
3493214734Srpaulo				printf("Warning: Failed to attach to "
3494214734Srpaulo				       "wpa_supplicant.\n");
3495189251Ssam				return -1;
3496214734Srpaulo			}
3497189251Ssam		}
3498189251Ssam
3499252726Srpaulo		if (daemonize && os_daemonize(pid_file))
3500252726Srpaulo			return -1;
3501189251Ssam
3502252726Srpaulo		if (action_file)
3503252726Srpaulo			wpa_cli_action(ctrl_conn);
3504252726Srpaulo		else
3505252726Srpaulo			ret = wpa_request(ctrl_conn, argc - optind,
3506252726Srpaulo					  &argv[optind]);
3507252726Srpaulo	}
3508189251Ssam
3509189251Ssam	os_free(ctrl_ifname);
3510252726Srpaulo	eloop_destroy();
3511189251Ssam	wpa_cli_cleanup();
3512189251Ssam
3513189251Ssam	return ret;
3514189251Ssam}
3515189251Ssam
3516189251Ssam#else /* CONFIG_CTRL_IFACE */
3517189251Ssamint main(int argc, char *argv[])
3518189251Ssam{
3519189251Ssam	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3520189251Ssam	return -1;
3521189251Ssam}
3522189251Ssam#endif /* CONFIG_CTRL_IFACE */
3523