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