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