wpa_cli.c revision 04949598a23f501be6eec21697465fd46a28840a
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_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2939				      char *argv[])
2940{
2941	return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2942}
2943
2944
2945#ifdef CONFIG_AUTOSCAN
2946
2947static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2948{
2949	char cmd[256];
2950	int res;
2951
2952	if (argc == 0)
2953		return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2954
2955	res = os_snprintf(cmd, sizeof(cmd), "AUTOSCAN %s", argv[0]);
2956	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2957		printf("Too long AUTOSCAN command.\n");
2958		return -1;
2959	}
2960
2961	return wpa_ctrl_command(ctrl, cmd);
2962}
2963
2964#endif /* CONFIG_AUTOSCAN */
2965
2966
2967#ifdef ANDROID
2968static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2969{
2970	char cmd[256];
2971	int i;
2972	int len;
2973
2974	if (argc < 1) {
2975		printf("Invalid DRIVER command: needs one argument (cmd)\n");
2976		return -1;
2977	}
2978
2979	len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2980	for (i=1; i < argc; i++)
2981		len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2982	cmd[sizeof(cmd) - 1] = '\0';
2983	printf("%s: %s\n", __func__, cmd);
2984	return wpa_ctrl_command(ctrl, cmd);
2985}
2986#endif
2987
2988enum wpa_cli_cmd_flags {
2989	cli_cmd_flag_none		= 0x00,
2990	cli_cmd_flag_sensitive		= 0x01
2991};
2992
2993struct wpa_cli_cmd {
2994	const char *cmd;
2995	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2996	enum wpa_cli_cmd_flags flags;
2997	const char *usage;
2998};
2999
3000static struct wpa_cli_cmd wpa_cli_commands[] = {
3001	{ "status", wpa_cli_cmd_status,
3002	  cli_cmd_flag_none,
3003	  "[verbose] = get current WPA/EAPOL/EAP status" },
3004	{ "ping", wpa_cli_cmd_ping,
3005	  cli_cmd_flag_none,
3006	  "= pings wpa_supplicant" },
3007	{ "relog", wpa_cli_cmd_relog,
3008	  cli_cmd_flag_none,
3009	  "= re-open log-file (allow rolling logs)" },
3010	{ "note", wpa_cli_cmd_note,
3011	  cli_cmd_flag_none,
3012	  "<text> = add a note to wpa_supplicant debug log" },
3013	{ "mib", wpa_cli_cmd_mib,
3014	  cli_cmd_flag_none,
3015	  "= get MIB variables (dot1x, dot11)" },
3016	{ "help", wpa_cli_cmd_help,
3017	  cli_cmd_flag_none,
3018	  "= show this usage help" },
3019	{ "interface", wpa_cli_cmd_interface,
3020	  cli_cmd_flag_none,
3021	  "[ifname] = show interfaces/select interface" },
3022	{ "level", wpa_cli_cmd_level,
3023	  cli_cmd_flag_none,
3024	  "<debug level> = change debug level" },
3025	{ "license", wpa_cli_cmd_license,
3026	  cli_cmd_flag_none,
3027	  "= show full wpa_cli license" },
3028	{ "quit", wpa_cli_cmd_quit,
3029	  cli_cmd_flag_none,
3030	  "= exit wpa_cli" },
3031	{ "set", wpa_cli_cmd_set,
3032	  cli_cmd_flag_none,
3033	  "= set variables (shows list of variables when run without "
3034	  "arguments)" },
3035	{ "get", wpa_cli_cmd_get,
3036	  cli_cmd_flag_none,
3037	  "<name> = get information" },
3038	{ "logon", wpa_cli_cmd_logon,
3039	  cli_cmd_flag_none,
3040	  "= IEEE 802.1X EAPOL state machine logon" },
3041	{ "logoff", wpa_cli_cmd_logoff,
3042	  cli_cmd_flag_none,
3043	  "= IEEE 802.1X EAPOL state machine logoff" },
3044	{ "pmksa", wpa_cli_cmd_pmksa,
3045	  cli_cmd_flag_none,
3046	  "= show PMKSA cache" },
3047	{ "reassociate", wpa_cli_cmd_reassociate,
3048	  cli_cmd_flag_none,
3049	  "= force reassociation" },
3050	{ "preauthenticate", wpa_cli_cmd_preauthenticate,
3051	  cli_cmd_flag_none,
3052	  "<BSSID> = force preauthentication" },
3053	{ "identity", wpa_cli_cmd_identity,
3054	  cli_cmd_flag_none,
3055	  "<network id> <identity> = configure identity for an SSID" },
3056	{ "password", wpa_cli_cmd_password,
3057	  cli_cmd_flag_sensitive,
3058	  "<network id> <password> = configure password for an SSID" },
3059	{ "new_password", wpa_cli_cmd_new_password,
3060	  cli_cmd_flag_sensitive,
3061	  "<network id> <password> = change password for an SSID" },
3062	{ "pin", wpa_cli_cmd_pin,
3063	  cli_cmd_flag_sensitive,
3064	  "<network id> <pin> = configure pin for an SSID" },
3065	{ "otp", wpa_cli_cmd_otp,
3066	  cli_cmd_flag_sensitive,
3067	  "<network id> <password> = configure one-time-password for an SSID"
3068	},
3069	{ "passphrase", wpa_cli_cmd_passphrase,
3070	  cli_cmd_flag_sensitive,
3071	  "<network id> <passphrase> = configure private key passphrase\n"
3072	  "  for an SSID" },
3073	{ "bssid", wpa_cli_cmd_bssid,
3074	  cli_cmd_flag_none,
3075	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
3076	{ "blacklist", wpa_cli_cmd_blacklist,
3077	  cli_cmd_flag_none,
3078	  "<BSSID> = add a BSSID to the blacklist\n"
3079	  "blacklist clear = clear the blacklist\n"
3080	  "blacklist = display the blacklist" },
3081	{ "log_level", wpa_cli_cmd_log_level,
3082	  cli_cmd_flag_none,
3083	  "<level> [<timestamp>] = update the log level/timestamp\n"
3084	  "log_level = display the current log level and log options" },
3085	{ "list_networks", wpa_cli_cmd_list_networks,
3086	  cli_cmd_flag_none,
3087	  "= list configured networks" },
3088	{ "select_network", wpa_cli_cmd_select_network,
3089	  cli_cmd_flag_none,
3090	  "<network id> = select a network (disable others)" },
3091	{ "enable_network", wpa_cli_cmd_enable_network,
3092	  cli_cmd_flag_none,
3093	  "<network id> = enable a network" },
3094	{ "disable_network", wpa_cli_cmd_disable_network,
3095	  cli_cmd_flag_none,
3096	  "<network id> = disable a network" },
3097	{ "add_network", wpa_cli_cmd_add_network,
3098	  cli_cmd_flag_none,
3099	  "= add a network" },
3100	{ "remove_network", wpa_cli_cmd_remove_network,
3101	  cli_cmd_flag_none,
3102	  "<network id> = remove a network" },
3103	{ "set_network", wpa_cli_cmd_set_network,
3104	  cli_cmd_flag_sensitive,
3105	  "<network id> <variable> <value> = set network variables (shows\n"
3106	  "  list of variables when run without arguments)" },
3107	{ "get_network", wpa_cli_cmd_get_network,
3108	  cli_cmd_flag_none,
3109	  "<network id> <variable> = get network variables" },
3110	{ "list_creds", wpa_cli_cmd_list_creds,
3111	  cli_cmd_flag_none,
3112	  "= list configured credentials" },
3113	{ "add_cred", wpa_cli_cmd_add_cred,
3114	  cli_cmd_flag_none,
3115	  "= add a credential" },
3116	{ "remove_cred", wpa_cli_cmd_remove_cred,
3117	  cli_cmd_flag_none,
3118	  "<cred id> = remove a credential" },
3119	{ "set_cred", wpa_cli_cmd_set_cred,
3120	  cli_cmd_flag_sensitive,
3121	  "<cred id> <variable> <value> = set credential variables" },
3122	{ "save_config", wpa_cli_cmd_save_config,
3123	  cli_cmd_flag_none,
3124	  "= save the current configuration" },
3125	{ "disconnect", wpa_cli_cmd_disconnect,
3126	  cli_cmd_flag_none,
3127	  "= disconnect and wait for reassociate/reconnect command before\n"
3128	  "  connecting" },
3129	{ "reconnect", wpa_cli_cmd_reconnect,
3130	  cli_cmd_flag_none,
3131	  "= like reassociate, but only takes effect if already disconnected"
3132	},
3133	{ "scan", wpa_cli_cmd_scan,
3134	  cli_cmd_flag_none,
3135	  "= request new BSS scan" },
3136	{ "scan_results", wpa_cli_cmd_scan_results,
3137	  cli_cmd_flag_none,
3138	  "= get latest scan results" },
3139	{ "bss", wpa_cli_cmd_bss,
3140	  cli_cmd_flag_none,
3141	  "<<idx> | <bssid>> = get detailed scan result info" },
3142	{ "get_capability", wpa_cli_cmd_get_capability,
3143	  cli_cmd_flag_none,
3144	  "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels>\n"
3145	  "  = get capabilities" },
3146	{ "reconfigure", wpa_cli_cmd_reconfigure,
3147	  cli_cmd_flag_none,
3148	  "= force wpa_supplicant to re-read its configuration file" },
3149	{ "terminate", wpa_cli_cmd_terminate,
3150	  cli_cmd_flag_none,
3151	  "= terminate wpa_supplicant" },
3152	{ "interface_add", wpa_cli_cmd_interface_add,
3153	  cli_cmd_flag_none,
3154	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
3155	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
3156	  "  are optional" },
3157	{ "interface_remove", wpa_cli_cmd_interface_remove,
3158	  cli_cmd_flag_none,
3159	  "<ifname> = removes the interface" },
3160	{ "interface_list", wpa_cli_cmd_interface_list,
3161	  cli_cmd_flag_none,
3162	  "= list available interfaces" },
3163	{ "ap_scan", wpa_cli_cmd_ap_scan,
3164	  cli_cmd_flag_none,
3165	  "<value> = set ap_scan parameter" },
3166	{ "scan_interval", wpa_cli_cmd_scan_interval,
3167	  cli_cmd_flag_none,
3168	  "<value> = set scan_interval parameter (in seconds)" },
3169	{ "bss_expire_age", wpa_cli_cmd_bss_expire_age,
3170	  cli_cmd_flag_none,
3171	  "<value> = set BSS expiration age parameter" },
3172	{ "bss_expire_count", wpa_cli_cmd_bss_expire_count,
3173	  cli_cmd_flag_none,
3174	  "<value> = set BSS expiration scan count parameter" },
3175	{ "stkstart", wpa_cli_cmd_stkstart,
3176	  cli_cmd_flag_none,
3177	  "<addr> = request STK negotiation with <addr>" },
3178	{ "ft_ds", wpa_cli_cmd_ft_ds,
3179	  cli_cmd_flag_none,
3180	  "<addr> = request over-the-DS FT with <addr>" },
3181	{ "wps_pbc", wpa_cli_cmd_wps_pbc,
3182	  cli_cmd_flag_none,
3183	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
3184	{ "wps_pin", wpa_cli_cmd_wps_pin,
3185	  cli_cmd_flag_sensitive,
3186	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3187	  "hardcoded)" },
3188	{ "wps_check_pin", wpa_cli_cmd_wps_check_pin,
3189	  cli_cmd_flag_sensitive,
3190	  "<PIN> = verify PIN checksum" },
3191	{ "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
3192	  "Cancels the pending WPS operation" },
3193#ifdef CONFIG_WPS_OOB
3194	{ "wps_oob", wpa_cli_cmd_wps_oob,
3195	  cli_cmd_flag_sensitive,
3196	  "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
3197#endif /* CONFIG_WPS_OOB */
3198#ifdef CONFIG_WPS_NFC
3199	{ "wps_nfc", wpa_cli_cmd_wps_nfc,
3200	  cli_cmd_flag_none,
3201	  "[BSSID] = start Wi-Fi Protected Setup: NFC" },
3202	{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token,
3203	  cli_cmd_flag_none,
3204	  "<WPS|NDEF> = create password token" },
3205	{ "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read,
3206	  cli_cmd_flag_sensitive,
3207	  "<hexdump of payload> = report read NFC tag with WPS data" },
3208#endif /* CONFIG_WPS_NFC */
3209	{ "wps_reg", wpa_cli_cmd_wps_reg,
3210	  cli_cmd_flag_sensitive,
3211	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
3212	{ "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
3213	  cli_cmd_flag_sensitive,
3214	  "[params..] = enable/disable AP PIN" },
3215	{ "wps_er_start", wpa_cli_cmd_wps_er_start,
3216	  cli_cmd_flag_none,
3217	  "[IP address] = start Wi-Fi Protected Setup External Registrar" },
3218	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop,
3219	  cli_cmd_flag_none,
3220	  "= stop Wi-Fi Protected Setup External Registrar" },
3221	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin,
3222	  cli_cmd_flag_sensitive,
3223	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
3224	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
3225	  cli_cmd_flag_none,
3226	  "<UUID> = accept an Enrollee PBC using External Registrar" },
3227	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn,
3228	  cli_cmd_flag_sensitive,
3229	  "<UUID> <PIN> = learn AP configuration" },
3230	{ "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
3231	  cli_cmd_flag_none,
3232	  "<UUID> <network id> = set AP configuration for enrolling" },
3233	{ "wps_er_config", wpa_cli_cmd_wps_er_config,
3234	  cli_cmd_flag_sensitive,
3235	  "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
3236#ifdef CONFIG_WPS_NFC
3237	{ "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token,
3238	  cli_cmd_flag_none,
3239	  "<WPS/NDEF> <UUID> = build NFC configuration token" },
3240#endif /* CONFIG_WPS_NFC */
3241	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
3242	  cli_cmd_flag_none,
3243	  "<addr> = request RSN authentication with <addr> in IBSS" },
3244#ifdef CONFIG_AP
3245	{ "sta", wpa_cli_cmd_sta,
3246	  cli_cmd_flag_none,
3247	  "<addr> = get information about an associated station (AP)" },
3248	{ "all_sta", wpa_cli_cmd_all_sta,
3249	  cli_cmd_flag_none,
3250	  "= get information about all associated stations (AP)" },
3251	{ "deauthenticate", wpa_cli_cmd_deauthenticate,
3252	  cli_cmd_flag_none,
3253	  "<addr> = deauthenticate a station" },
3254	{ "disassociate", wpa_cli_cmd_disassociate,
3255	  cli_cmd_flag_none,
3256	  "<addr> = disassociate a station" },
3257#endif /* CONFIG_AP */
3258	{ "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
3259	  "= notification of suspend/hibernate" },
3260	{ "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
3261	  "= notification of resume/thaw" },
3262	{ "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
3263	  "= drop SA without deauth/disassoc (test command)" },
3264	{ "roam", wpa_cli_cmd_roam,
3265	  cli_cmd_flag_none,
3266	  "<addr> = roam to the specified BSS" },
3267#ifdef CONFIG_P2P
3268	{ "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
3269	  "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3270	{ "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
3271	  "= stop P2P Devices search" },
3272	{ "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
3273	  "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
3274	{ "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
3275	  "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3276	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
3277	  "<ifname> = remove P2P group interface (terminate group if GO)" },
3278	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
3279	  "= add a new P2P group (local end as GO)" },
3280	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
3281	  "<addr> <method> = request provisioning discovery" },
3282	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
3283	  cli_cmd_flag_none,
3284	  "= get the passphrase for a group (GO only)" },
3285	{ "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3286	  cli_cmd_flag_none,
3287	  "<addr> <TLVs> = schedule service discovery request" },
3288	{ "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3289	  cli_cmd_flag_none,
3290	  "<id> = cancel pending service discovery request" },
3291	{ "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
3292	  cli_cmd_flag_none,
3293	  "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3294	{ "p2p_service_update", wpa_cli_cmd_p2p_service_update,
3295	  cli_cmd_flag_none,
3296	  "= indicate change in local services" },
3297	{ "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
3298	  cli_cmd_flag_none,
3299	  "<external> = set external processing of service discovery" },
3300	{ "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
3301	  cli_cmd_flag_none,
3302	  "= remove all stored service entries" },
3303	{ "p2p_service_add", wpa_cli_cmd_p2p_service_add,
3304	  cli_cmd_flag_none,
3305	  "<bonjour|upnp> <query|version> <response|service> = add a local "
3306	  "service" },
3307	{ "p2p_service_del", wpa_cli_cmd_p2p_service_del,
3308	  cli_cmd_flag_none,
3309	  "<bonjour|upnp> <query|version> [|service] = remove a local "
3310	  "service" },
3311	{ "p2p_reject", wpa_cli_cmd_p2p_reject,
3312	  cli_cmd_flag_none,
3313	  "<addr> = reject connection attempts from a specific peer" },
3314	{ "p2p_invite", wpa_cli_cmd_p2p_invite,
3315	  cli_cmd_flag_none,
3316	  "<cmd> [peer=addr] = invite peer" },
3317	{ "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
3318	  "[discovered] = list known (optionally, only fully discovered) P2P "
3319	  "peers" },
3320	{ "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
3321	  "<address> = show information about known P2P peer" },
3322	{ "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
3323	  "<field> <value> = set a P2P parameter" },
3324	{ "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
3325	  "= flush P2P state" },
3326	{ "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
3327	  "= cancel P2P group formation" },
3328	{ "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
3329	  "<address> = unauthorize a peer" },
3330	{ "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
3331	  "[<duration> <interval>] [<duration> <interval>] = request GO "
3332	  "presence" },
3333	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
3334	  "[<period> <interval>] = set extended listen timing" },
3335#endif /* CONFIG_P2P */
3336
3337#ifdef CONFIG_INTERWORKING
3338	{ "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
3339	  "= fetch ANQP information for all APs" },
3340	{ "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
3341	  "= stop fetch_anqp operation" },
3342	{ "interworking_select", wpa_cli_cmd_interworking_select,
3343	  cli_cmd_flag_none,
3344	  "[auto] = perform Interworking network selection" },
3345	{ "interworking_connect", wpa_cli_cmd_interworking_connect,
3346	  cli_cmd_flag_none,
3347	  "<BSSID> = connect using Interworking credentials" },
3348	{ "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
3349	  "<addr> <info id>[,<info id>]... = request ANQP information" },
3350#endif /* CONFIG_INTERWORKING */
3351#ifdef CONFIG_HS20
3352	{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, cli_cmd_flag_none,
3353	  "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3354	},
3355	{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3356	  cli_cmd_flag_none,
3357	  "<addr> <home realm> = get HS20 nai home realm list" },
3358#endif /* CONFIG_HS20 */
3359	{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
3360	  "<0/1> = disable/enable automatic reconnection" },
3361	{ "tdls_discover", wpa_cli_cmd_tdls_discover,
3362	  cli_cmd_flag_none,
3363	  "<addr> = request TDLS discovery with <addr>" },
3364	{ "tdls_setup", wpa_cli_cmd_tdls_setup,
3365	  cli_cmd_flag_none,
3366	  "<addr> = request TDLS setup with <addr>" },
3367	{ "tdls_teardown", wpa_cli_cmd_tdls_teardown,
3368	  cli_cmd_flag_none,
3369	  "<addr> = tear down TDLS with <addr>" },
3370	{ "signal_poll", wpa_cli_cmd_signal_poll,
3371	  cli_cmd_flag_none,
3372	  "= get signal parameters" },
3373	{ "reauthenticate", wpa_cli_cmd_reauthenticate, cli_cmd_flag_none,
3374	  "= trigger IEEE 802.1X/EAPOL reauthentication" },
3375#ifdef CONFIG_AUTOSCAN
3376	{ "autoscan", wpa_cli_cmd_autoscan, cli_cmd_flag_none,
3377	  "[params] = Set or unset (if none) autoscan parameters" },
3378#endif /* CONFIG_AUTOSCAN */
3379#ifdef ANDROID
3380	{ "driver", wpa_cli_cmd_driver,
3381	  cli_cmd_flag_none,
3382	  "<command> = driver private commands" },
3383#endif
3384	{ NULL, NULL, cli_cmd_flag_none, NULL }
3385};
3386
3387
3388/*
3389 * Prints command usage, lines are padded with the specified string.
3390 */
3391static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3392{
3393	char c;
3394	size_t n;
3395
3396	printf("%s%s ", pad, cmd->cmd);
3397	for (n = 0; (c = cmd->usage[n]); n++) {
3398		printf("%c", c);
3399		if (c == '\n')
3400			printf("%s", pad);
3401	}
3402	printf("\n");
3403}
3404
3405
3406static void print_help(void)
3407{
3408	int n;
3409	printf("commands:\n");
3410	for (n = 0; wpa_cli_commands[n].cmd; n++)
3411		print_cmd_help(&wpa_cli_commands[n], "  ");
3412}
3413
3414
3415static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3416{
3417	const char *c, *delim;
3418	int n;
3419	size_t len;
3420
3421	delim = os_strchr(cmd, ' ');
3422	if (delim)
3423		len = delim - cmd;
3424	else
3425		len = os_strlen(cmd);
3426
3427	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3428		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3429			return (wpa_cli_commands[n].flags &
3430				cli_cmd_flag_sensitive);
3431	}
3432	return 0;
3433}
3434
3435
3436static char ** wpa_list_cmd_list(void)
3437{
3438	char **res;
3439	int i, count;
3440
3441	count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
3442	res = os_zalloc(count * sizeof(char *));
3443	if (res == NULL)
3444		return NULL;
3445
3446	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3447		res[i] = os_strdup(wpa_cli_commands[i].cmd);
3448		if (res[i] == NULL)
3449			break;
3450	}
3451
3452	return res;
3453}
3454
3455
3456static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3457				      int pos)
3458{
3459	int i;
3460
3461	if (os_strcasecmp(cmd, "bss") == 0)
3462		return wpa_cli_complete_bss(str, pos);
3463#ifdef CONFIG_P2P
3464	if (os_strcasecmp(cmd, "p2p_connect") == 0)
3465		return wpa_cli_complete_p2p_connect(str, pos);
3466	if (os_strcasecmp(cmd, "p2p_peer") == 0)
3467		return wpa_cli_complete_p2p_peer(str, pos);
3468	if (os_strcasecmp(cmd, "p2p_group_remove") == 0)
3469		return wpa_cli_complete_p2p_group_remove(str, pos);
3470#endif /* CONFIG_P2P */
3471
3472	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3473		if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3474			edit_clear_line();
3475			printf("\r%s\n", wpa_cli_commands[i].usage);
3476			edit_redraw();
3477			break;
3478		}
3479	}
3480
3481	return NULL;
3482}
3483
3484
3485static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3486{
3487	char **res;
3488	const char *end;
3489	char *cmd;
3490
3491	end = os_strchr(str, ' ');
3492	if (end == NULL || str + pos < end)
3493		return wpa_list_cmd_list();
3494
3495	cmd = os_malloc(pos + 1);
3496	if (cmd == NULL)
3497		return NULL;
3498	os_memcpy(cmd, str, pos);
3499	cmd[end - str] = '\0';
3500	res = wpa_cli_cmd_completion(cmd, str, pos);
3501	os_free(cmd);
3502	return res;
3503}
3504
3505
3506static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3507{
3508	struct wpa_cli_cmd *cmd, *match = NULL;
3509	int count;
3510	int ret = 0;
3511
3512	count = 0;
3513	cmd = wpa_cli_commands;
3514	while (cmd->cmd) {
3515		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3516		{
3517			match = cmd;
3518			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3519				/* we have an exact match */
3520				count = 1;
3521				break;
3522			}
3523			count++;
3524		}
3525		cmd++;
3526	}
3527
3528	if (count > 1) {
3529		printf("Ambiguous command '%s'; possible commands:", argv[0]);
3530		cmd = wpa_cli_commands;
3531		while (cmd->cmd) {
3532			if (os_strncasecmp(cmd->cmd, argv[0],
3533					   os_strlen(argv[0])) == 0) {
3534				printf(" %s", cmd->cmd);
3535			}
3536			cmd++;
3537		}
3538		printf("\n");
3539		ret = 1;
3540	} else if (count == 0) {
3541		printf("Unknown command '%s'\n", argv[0]);
3542		ret = 1;
3543	} else {
3544#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
3545		if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
3546			redirect_interface = os_strdup(argv[1]);
3547			ret = match->handler(ctrl, argc - 2, &argv[2]);
3548		}
3549		else
3550#endif
3551		ret = match->handler(ctrl, argc - 1, &argv[1]);
3552	}
3553
3554	return ret;
3555}
3556
3557
3558static int str_match(const char *a, const char *b)
3559{
3560	return os_strncmp(a, b, os_strlen(b)) == 0;
3561}
3562
3563
3564static int wpa_cli_exec(const char *program, const char *arg1,
3565			const char *arg2)
3566{
3567	char *cmd;
3568	size_t len;
3569	int res;
3570	int ret = 0;
3571
3572	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3573	cmd = os_malloc(len);
3574	if (cmd == NULL)
3575		return -1;
3576	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3577	if (res < 0 || (size_t) res >= len) {
3578		os_free(cmd);
3579		return -1;
3580	}
3581	cmd[len - 1] = '\0';
3582#ifndef _WIN32_WCE
3583	if (system(cmd) < 0)
3584		ret = -1;
3585#endif /* _WIN32_WCE */
3586	os_free(cmd);
3587
3588	return ret;
3589}
3590
3591
3592static void wpa_cli_action_process(const char *msg)
3593{
3594	const char *pos;
3595	char *copy = NULL, *id, *pos2;
3596
3597	pos = msg;
3598	if (*pos == '<') {
3599		/* skip priority */
3600		pos = os_strchr(pos, '>');
3601		if (pos)
3602			pos++;
3603		else
3604			pos = msg;
3605	}
3606
3607	if (str_match(pos, WPA_EVENT_CONNECTED)) {
3608		int new_id = -1;
3609		os_unsetenv("WPA_ID");
3610		os_unsetenv("WPA_ID_STR");
3611		os_unsetenv("WPA_CTRL_DIR");
3612
3613		pos = os_strstr(pos, "[id=");
3614		if (pos)
3615			copy = os_strdup(pos + 4);
3616
3617		if (copy) {
3618			pos2 = id = copy;
3619			while (*pos2 && *pos2 != ' ')
3620				pos2++;
3621			*pos2++ = '\0';
3622			new_id = atoi(id);
3623			os_setenv("WPA_ID", id, 1);
3624			while (*pos2 && *pos2 != '=')
3625				pos2++;
3626			if (*pos2 == '=')
3627				pos2++;
3628			id = pos2;
3629			while (*pos2 && *pos2 != ']')
3630				pos2++;
3631			*pos2 = '\0';
3632			os_setenv("WPA_ID_STR", id, 1);
3633			os_free(copy);
3634		}
3635
3636		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3637
3638		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3639			wpa_cli_connected = 1;
3640			wpa_cli_last_id = new_id;
3641			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3642		}
3643	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3644		if (wpa_cli_connected) {
3645			wpa_cli_connected = 0;
3646			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3647		}
3648	} else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3649		wpa_cli_exec(action_file, ctrl_ifname, pos);
3650	} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3651		wpa_cli_exec(action_file, ctrl_ifname, pos);
3652	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3653		wpa_cli_exec(action_file, ctrl_ifname, pos);
3654	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3655		wpa_cli_exec(action_file, ctrl_ifname, pos);
3656	} else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3657		wpa_cli_exec(action_file, ctrl_ifname, pos);
3658	} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3659		wpa_cli_exec(action_file, ctrl_ifname, pos);
3660	} else if (str_match(pos, WPS_EVENT_FAIL)) {
3661		wpa_cli_exec(action_file, ctrl_ifname, pos);
3662	} else if (str_match(pos, AP_STA_CONNECTED)) {
3663		wpa_cli_exec(action_file, ctrl_ifname, pos);
3664	} else if (str_match(pos, AP_STA_DISCONNECTED)) {
3665		wpa_cli_exec(action_file, ctrl_ifname, pos);
3666	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3667		printf("wpa_supplicant is terminating - stop monitoring\n");
3668		wpa_cli_quit = 1;
3669	}
3670}
3671
3672
3673#ifndef CONFIG_ANSI_C_EXTRA
3674static void wpa_cli_action_cb(char *msg, size_t len)
3675{
3676	wpa_cli_action_process(msg);
3677}
3678#endif /* CONFIG_ANSI_C_EXTRA */
3679
3680
3681static void wpa_cli_reconnect(void)
3682{
3683	wpa_cli_close_connection();
3684	wpa_cli_open_connection(ctrl_ifname, 1);
3685}
3686
3687
3688static void cli_event(const char *str)
3689{
3690	const char *start, *s;
3691
3692	start = os_strchr(str, '>');
3693	if (start == NULL)
3694		return;
3695
3696	start++;
3697
3698	if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3699		s = os_strchr(start, ' ');
3700		if (s == NULL)
3701			return;
3702		s = os_strchr(s + 1, ' ');
3703		if (s == NULL)
3704			return;
3705		cli_txt_list_add(&bsses, s + 1);
3706		return;
3707	}
3708
3709	if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3710		s = os_strchr(start, ' ');
3711		if (s == NULL)
3712			return;
3713		s = os_strchr(s + 1, ' ');
3714		if (s == NULL)
3715			return;
3716		cli_txt_list_del_addr(&bsses, s + 1);
3717		return;
3718	}
3719
3720#ifdef CONFIG_P2P
3721	if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3722		s = os_strstr(start, " p2p_dev_addr=");
3723		if (s == NULL)
3724			return;
3725		cli_txt_list_add_addr(&p2p_peers, s + 14);
3726		return;
3727	}
3728
3729	if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3730		s = os_strstr(start, " p2p_dev_addr=");
3731		if (s == NULL)
3732			return;
3733		cli_txt_list_del_addr(&p2p_peers, s + 14);
3734		return;
3735	}
3736
3737	if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3738		s = os_strchr(start, ' ');
3739		if (s == NULL)
3740			return;
3741		cli_txt_list_add_word(&p2p_groups, s + 1);
3742		return;
3743	}
3744
3745	if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3746		s = os_strchr(start, ' ');
3747		if (s == NULL)
3748			return;
3749		cli_txt_list_del_word(&p2p_groups, s + 1);
3750		return;
3751	}
3752#endif /* CONFIG_P2P */
3753}
3754
3755
3756static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3757{
3758	if (ctrl_conn == NULL) {
3759		wpa_cli_reconnect();
3760		return;
3761	}
3762	while (wpa_ctrl_pending(ctrl) > 0) {
3763		char buf[256];
3764		size_t len = sizeof(buf) - 1;
3765		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3766			buf[len] = '\0';
3767			if (action_monitor)
3768				wpa_cli_action_process(buf);
3769			else {
3770				cli_event(buf);
3771				if (wpa_cli_show_event(buf)) {
3772					edit_clear_line();
3773					printf("\r%s\n", buf);
3774					edit_redraw();
3775				}
3776			}
3777		} else {
3778			printf("Could not read pending message.\n");
3779			break;
3780		}
3781	}
3782
3783	if (wpa_ctrl_pending(ctrl) < 0) {
3784		printf("Connection to wpa_supplicant lost - trying to "
3785		       "reconnect\n");
3786		wpa_cli_reconnect();
3787	}
3788}
3789
3790#define max_args 10
3791
3792static int tokenize_cmd(char *cmd, char *argv[])
3793{
3794	char *pos;
3795	int argc = 0;
3796
3797	pos = cmd;
3798	for (;;) {
3799		while (*pos == ' ')
3800			pos++;
3801		if (*pos == '\0')
3802			break;
3803		argv[argc] = pos;
3804		argc++;
3805		if (argc == max_args)
3806			break;
3807		if (*pos == '"') {
3808			char *pos2 = os_strrchr(pos, '"');
3809			if (pos2)
3810				pos = pos2 + 1;
3811		}
3812		while (*pos != '\0' && *pos != ' ')
3813			pos++;
3814		if (*pos == ' ')
3815			*pos++ = '\0';
3816	}
3817
3818	return argc;
3819}
3820
3821
3822static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3823{
3824	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3825		printf("Connection to wpa_supplicant lost - trying to "
3826		       "reconnect\n");
3827		wpa_cli_close_connection();
3828	}
3829	if (!ctrl_conn)
3830		wpa_cli_reconnect();
3831	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3832}
3833
3834
3835static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3836{
3837	eloop_terminate();
3838}
3839
3840
3841static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3842{
3843	wpa_cli_recv_pending(mon_conn, 0);
3844}
3845
3846
3847static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3848{
3849	char *argv[max_args];
3850	int argc;
3851	argc = tokenize_cmd(cmd, argv);
3852	if (argc)
3853		wpa_request(ctrl_conn, argc, argv);
3854}
3855
3856
3857static void wpa_cli_edit_eof_cb(void *ctx)
3858{
3859	eloop_terminate();
3860}
3861
3862
3863static void wpa_cli_interactive(void)
3864{
3865	char *home, *hfile = NULL;
3866
3867	printf("\nInteractive mode\n\n");
3868
3869	home = getenv("HOME");
3870	if (home) {
3871		const char *fname = ".wpa_cli_history";
3872		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3873		hfile = os_malloc(hfile_len);
3874		if (hfile)
3875			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3876	}
3877
3878	eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
3879	edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3880		  wpa_cli_edit_completion_cb, NULL, hfile);
3881	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3882
3883	eloop_run();
3884
3885	cli_txt_list_flush(&p2p_peers);
3886	cli_txt_list_flush(&p2p_groups);
3887	cli_txt_list_flush(&bsses);
3888	edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3889	os_free(hfile);
3890	eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3891	wpa_cli_close_connection();
3892}
3893
3894
3895static void wpa_cli_action(struct wpa_ctrl *ctrl)
3896{
3897#ifdef CONFIG_ANSI_C_EXTRA
3898	/* TODO: ANSI C version(?) */
3899	printf("Action processing not supported in ANSI C build.\n");
3900#else /* CONFIG_ANSI_C_EXTRA */
3901	fd_set rfds;
3902	int fd, res;
3903	struct timeval tv;
3904	char buf[256]; /* note: large enough to fit in unsolicited messages */
3905	size_t len;
3906
3907	fd = wpa_ctrl_get_fd(ctrl);
3908
3909	while (!wpa_cli_quit) {
3910		FD_ZERO(&rfds);
3911		FD_SET(fd, &rfds);
3912		tv.tv_sec = ping_interval;
3913		tv.tv_usec = 0;
3914		res = select(fd + 1, &rfds, NULL, NULL, &tv);
3915		if (res < 0 && errno != EINTR) {
3916			perror("select");
3917			break;
3918		}
3919
3920		if (FD_ISSET(fd, &rfds))
3921			wpa_cli_recv_pending(ctrl, 1);
3922		else {
3923			/* verify that connection is still working */
3924			len = sizeof(buf) - 1;
3925			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3926					     wpa_cli_action_cb) < 0 ||
3927			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3928				printf("wpa_supplicant did not reply to PING "
3929				       "command - exiting\n");
3930				break;
3931			}
3932		}
3933	}
3934#endif /* CONFIG_ANSI_C_EXTRA */
3935}
3936
3937
3938static void wpa_cli_cleanup(void)
3939{
3940	wpa_cli_close_connection();
3941	if (pid_file)
3942		os_daemonize_terminate(pid_file);
3943
3944	os_program_deinit();
3945}
3946
3947static void wpa_cli_terminate(int sig)
3948{
3949	wpa_cli_cleanup();
3950	exit(0);
3951}
3952
3953
3954static char * wpa_cli_get_default_ifname(void)
3955{
3956	char *ifname = NULL;
3957
3958#ifdef CONFIG_CTRL_IFACE_UNIX
3959	struct dirent *dent;
3960	DIR *dir = opendir(ctrl_iface_dir);
3961	if (!dir) {
3962#ifdef ANDROID
3963		char ifprop[PROPERTY_VALUE_MAX];
3964		if (property_get("wifi.interface", ifprop, NULL) != 0) {
3965			ifname = os_strdup(ifprop);
3966			printf("Using interface '%s'\n", ifname);
3967			return ifname;
3968		}
3969#endif /* ANDROID */
3970		return NULL;
3971	}
3972	while ((dent = readdir(dir))) {
3973#ifdef _DIRENT_HAVE_D_TYPE
3974		/*
3975		 * Skip the file if it is not a socket. Also accept
3976		 * DT_UNKNOWN (0) in case the C library or underlying
3977		 * file system does not support d_type.
3978		 */
3979		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3980			continue;
3981#endif /* _DIRENT_HAVE_D_TYPE */
3982		if (os_strcmp(dent->d_name, ".") == 0 ||
3983		    os_strcmp(dent->d_name, "..") == 0)
3984			continue;
3985		printf("Selected interface '%s'\n", dent->d_name);
3986		ifname = os_strdup(dent->d_name);
3987		break;
3988	}
3989	closedir(dir);
3990#endif /* CONFIG_CTRL_IFACE_UNIX */
3991
3992#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3993#ifdef ANDROID
3994	char buf[4096], *pos;
3995#else
3996	char buf[2048], *pos;
3997#endif
3998	size_t len;
3999	struct wpa_ctrl *ctrl;
4000	int ret;
4001
4002	ctrl = wpa_ctrl_open(NULL);
4003	if (ctrl == NULL)
4004		return NULL;
4005
4006	len = sizeof(buf) - 1;
4007	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4008	if (ret >= 0) {
4009		buf[len] = '\0';
4010		pos = os_strchr(buf, '\n');
4011		if (pos)
4012			*pos = '\0';
4013		ifname = os_strdup(buf);
4014	}
4015	wpa_ctrl_close(ctrl);
4016#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4017
4018	return ifname;
4019}
4020
4021
4022int main(int argc, char *argv[])
4023{
4024	int warning_displayed = 0;
4025	int c;
4026	int daemonize = 0;
4027	int ret = 0;
4028	const char *global = NULL;
4029
4030	if (os_program_init())
4031		return -1;
4032
4033	for (;;) {
4034		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
4035		if (c < 0)
4036			break;
4037		switch (c) {
4038		case 'a':
4039			action_file = optarg;
4040			break;
4041		case 'B':
4042			daemonize = 1;
4043			break;
4044		case 'g':
4045			global = optarg;
4046			break;
4047		case 'G':
4048			ping_interval = atoi(optarg);
4049			break;
4050		case 'h':
4051			usage();
4052			return 0;
4053		case 'v':
4054			printf("%s\n", wpa_cli_version);
4055			return 0;
4056		case 'i':
4057			os_free(ctrl_ifname);
4058			ctrl_ifname = os_strdup(optarg);
4059			break;
4060		case 'p':
4061			ctrl_iface_dir = optarg;
4062			break;
4063		case 'P':
4064			pid_file = optarg;
4065			break;
4066		default:
4067			usage();
4068			return -1;
4069		}
4070	}
4071
4072	interactive = (argc == optind) && (action_file == NULL);
4073
4074	if (interactive)
4075		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4076
4077	if (eloop_init())
4078		return -1;
4079
4080	if (global) {
4081#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4082		ctrl_conn = wpa_ctrl_open(NULL);
4083#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4084		ctrl_conn = wpa_ctrl_open(global);
4085#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4086		if (ctrl_conn == NULL) {
4087			fprintf(stderr, "Failed to connect to wpa_supplicant "
4088				"global interface: %s  error: %s\n",
4089				global, strerror(errno));
4090			return -1;
4091		}
4092	}
4093
4094#ifndef _WIN32_WCE
4095	signal(SIGINT, wpa_cli_terminate);
4096	signal(SIGTERM, wpa_cli_terminate);
4097#endif /* _WIN32_WCE */
4098
4099	if (ctrl_ifname == NULL)
4100		ctrl_ifname = wpa_cli_get_default_ifname();
4101
4102	if (interactive) {
4103		for (; !global;) {
4104			if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
4105				if (warning_displayed)
4106					printf("Connection established.\n");
4107				break;
4108			}
4109
4110			if (!warning_displayed) {
4111				printf("Could not connect to wpa_supplicant: "
4112				       "%s - re-trying\n", ctrl_ifname);
4113				warning_displayed = 1;
4114			}
4115			os_sleep(1, 0);
4116			continue;
4117		}
4118	} else {
4119		if (!global &&
4120		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4121			fprintf(stderr, "Failed to connect to non-global "
4122				"ctrl_ifname: %s  error: %s\n",
4123				ctrl_ifname, strerror(errno));
4124			return -1;
4125		}
4126
4127		if (action_file) {
4128			if (wpa_ctrl_attach(ctrl_conn) == 0) {
4129				wpa_cli_attached = 1;
4130			} else {
4131				printf("Warning: Failed to attach to "
4132				       "wpa_supplicant.\n");
4133				return -1;
4134			}
4135		}
4136	}
4137
4138	if (daemonize && os_daemonize(pid_file))
4139		return -1;
4140
4141	if (interactive)
4142		wpa_cli_interactive();
4143	else if (action_file)
4144		wpa_cli_action(ctrl_conn);
4145	else
4146		ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
4147
4148	os_free(ctrl_ifname);
4149	eloop_destroy();
4150	wpa_cli_cleanup();
4151
4152	return ret;
4153}
4154
4155#else /* CONFIG_CTRL_IFACE */
4156int main(int argc, char *argv[])
4157{
4158	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4159	return -1;
4160}
4161#endif /* CONFIG_CTRL_IFACE */
4162