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