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