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