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