1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2016, 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 *const wpa_cli_version =
30 "wpa_cli v" VERSION_STR "\n"
31 "Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
32 
33 
34 static const char *const 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 *const 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 #define VENDOR_ELEM_FRAME_ID \
70 	"  0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
71 	"3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
72 	"7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \
73 	"11: Assoc Req (P2P), 12: Assoc Resp (P2P)"
74 
75 static struct wpa_ctrl *ctrl_conn;
76 static struct wpa_ctrl *mon_conn;
77 static int wpa_cli_quit = 0;
78 static int wpa_cli_attached = 0;
79 static int wpa_cli_connected = -1;
80 static int wpa_cli_last_id = 0;
81 #ifndef CONFIG_CTRL_IFACE_DIR
82 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
83 #endif /* CONFIG_CTRL_IFACE_DIR */
84 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
85 static const char *client_socket_dir = NULL;
86 static char *ctrl_ifname = NULL;
87 static const char *pid_file = NULL;
88 static const char *action_file = NULL;
89 static int ping_interval = 5;
90 static int interactive = 0;
91 static char *ifname_prefix = NULL;
92 
93 struct cli_txt_entry {
94 	struct dl_list list;
95 	char *txt;
96 };
97 
98 static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
99 static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
100 static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
101 static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
102 static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
103 
104 
105 static void print_help(const char *cmd);
106 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
107 static void wpa_cli_close_connection(void);
108 static char * wpa_cli_get_default_ifname(void);
109 static char ** wpa_list_cmd_list(void);
110 static void update_networks(struct wpa_ctrl *ctrl);
111 
112 
usage(void)113 static void usage(void)
114 {
115 	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
116 	       "[-a<action file>] \\\n"
117 	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
118 	       "\\\n"
119 	       "        [-s<wpa_client_socket_file_path>] "
120 	       "[command..]\n"
121 	       "  -h = help (show this usage text)\n"
122 	       "  -v = shown version information\n"
123 	       "  -a = run in daemon mode executing the action file based on "
124 	       "events from\n"
125 	       "       wpa_supplicant\n"
126 	       "  -B = run a daemon in the background\n"
127 	       "  default path: " CONFIG_CTRL_IFACE_DIR "\n"
128 	       "  default interface: first interface found in socket path\n");
129 	print_help(NULL);
130 }
131 
132 
cli_txt_list_free(struct cli_txt_entry * e)133 static void cli_txt_list_free(struct cli_txt_entry *e)
134 {
135 	dl_list_del(&e->list);
136 	os_free(e->txt);
137 	os_free(e);
138 }
139 
140 
cli_txt_list_flush(struct dl_list * list)141 static void cli_txt_list_flush(struct dl_list *list)
142 {
143 	struct cli_txt_entry *e;
144 	while ((e = dl_list_first(list, struct cli_txt_entry, list)))
145 		cli_txt_list_free(e);
146 }
147 
148 
cli_txt_list_get(struct dl_list * txt_list,const char * txt)149 static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
150 					       const char *txt)
151 {
152 	struct cli_txt_entry *e;
153 	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
154 		if (os_strcmp(e->txt, txt) == 0)
155 			return e;
156 	}
157 	return NULL;
158 }
159 
160 
cli_txt_list_del(struct dl_list * txt_list,const char * txt)161 static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
162 {
163 	struct cli_txt_entry *e;
164 	e = cli_txt_list_get(txt_list, txt);
165 	if (e)
166 		cli_txt_list_free(e);
167 }
168 
169 
cli_txt_list_del_addr(struct dl_list * txt_list,const char * txt)170 static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
171 {
172 	u8 addr[ETH_ALEN];
173 	char buf[18];
174 	if (hwaddr_aton(txt, addr) < 0)
175 		return;
176 	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
177 	cli_txt_list_del(txt_list, buf);
178 }
179 
180 
181 #ifdef CONFIG_P2P
cli_txt_list_del_word(struct dl_list * txt_list,const char * txt,int separator)182 static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
183 				  int separator)
184 {
185 	const char *end;
186 	char *buf;
187 	end = os_strchr(txt, separator);
188 	if (end == NULL)
189 		end = txt + os_strlen(txt);
190 	buf = dup_binstr(txt, end - txt);
191 	if (buf == NULL)
192 		return;
193 	cli_txt_list_del(txt_list, buf);
194 	os_free(buf);
195 }
196 #endif /* CONFIG_P2P */
197 
198 
cli_txt_list_add(struct dl_list * txt_list,const char * txt)199 static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
200 {
201 	struct cli_txt_entry *e;
202 	e = cli_txt_list_get(txt_list, txt);
203 	if (e)
204 		return 0;
205 	e = os_zalloc(sizeof(*e));
206 	if (e == NULL)
207 		return -1;
208 	e->txt = os_strdup(txt);
209 	if (e->txt == NULL) {
210 		os_free(e);
211 		return -1;
212 	}
213 	dl_list_add(txt_list, &e->list);
214 	return 0;
215 }
216 
217 
218 #ifdef CONFIG_P2P
cli_txt_list_add_addr(struct dl_list * txt_list,const char * txt)219 static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
220 {
221 	u8 addr[ETH_ALEN];
222 	char buf[18];
223 	if (hwaddr_aton(txt, addr) < 0)
224 		return -1;
225 	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
226 	return cli_txt_list_add(txt_list, buf);
227 }
228 #endif /* CONFIG_P2P */
229 
230 
cli_txt_list_add_word(struct dl_list * txt_list,const char * txt,int separator)231 static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
232 				 int separator)
233 {
234 	const char *end;
235 	char *buf;
236 	int ret;
237 	end = os_strchr(txt, separator);
238 	if (end == NULL)
239 		end = txt + os_strlen(txt);
240 	buf = dup_binstr(txt, end - txt);
241 	if (buf == NULL)
242 		return -1;
243 	ret = cli_txt_list_add(txt_list, buf);
244 	os_free(buf);
245 	return ret;
246 }
247 
248 
cli_txt_list_array(struct dl_list * txt_list)249 static char ** cli_txt_list_array(struct dl_list *txt_list)
250 {
251 	unsigned int i, count = dl_list_len(txt_list);
252 	char **res;
253 	struct cli_txt_entry *e;
254 
255 	res = os_calloc(count + 1, sizeof(char *));
256 	if (res == NULL)
257 		return NULL;
258 
259 	i = 0;
260 	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
261 		res[i] = os_strdup(e->txt);
262 		if (res[i] == NULL)
263 			break;
264 		i++;
265 	}
266 
267 	return res;
268 }
269 
270 
get_cmd_arg_num(const char * str,int pos)271 static int get_cmd_arg_num(const char *str, int pos)
272 {
273 	int arg = 0, i;
274 
275 	for (i = 0; i <= pos; i++) {
276 		if (str[i] != ' ') {
277 			arg++;
278 			while (i <= pos && str[i] != ' ')
279 				i++;
280 		}
281 	}
282 
283 	if (arg > 0)
284 		arg--;
285 	return arg;
286 }
287 
288 
str_starts(const char * src,const char * match)289 static int str_starts(const char *src, const char *match)
290 {
291 	return os_strncmp(src, match, os_strlen(match)) == 0;
292 }
293 
294 
wpa_cli_show_event(const char * event)295 static int wpa_cli_show_event(const char *event)
296 {
297 	const char *start;
298 
299 	start = os_strchr(event, '>');
300 	if (start == NULL)
301 		return 1;
302 
303 	start++;
304 	/*
305 	 * Skip BSS added/removed events since they can be relatively frequent
306 	 * and are likely of not much use for an interactive user.
307 	 */
308 	if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
309 	    str_starts(start, WPA_EVENT_BSS_REMOVED))
310 		return 0;
311 
312 	return 1;
313 }
314 
315 
wpa_cli_open_connection(const char * ifname,int attach)316 static int wpa_cli_open_connection(const char *ifname, int attach)
317 {
318 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
319 	ctrl_conn = wpa_ctrl_open(ifname);
320 	if (ctrl_conn == NULL)
321 		return -1;
322 
323 	if (attach && interactive)
324 		mon_conn = wpa_ctrl_open(ifname);
325 	else
326 		mon_conn = NULL;
327 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
328 	char *cfile = NULL;
329 	int flen, res;
330 
331 	if (ifname == NULL)
332 		return -1;
333 
334 #ifdef ANDROID
335 	if (access(ctrl_iface_dir, F_OK) < 0) {
336 		cfile = os_strdup(ifname);
337 		if (cfile == NULL)
338 			return -1;
339 	}
340 #endif /* ANDROID */
341 
342 	if (client_socket_dir && client_socket_dir[0] &&
343 	    access(client_socket_dir, F_OK) < 0) {
344 		perror(client_socket_dir);
345 		os_free(cfile);
346 		return -1;
347 	}
348 
349 	if (cfile == NULL) {
350 		flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
351 		cfile = os_malloc(flen);
352 		if (cfile == NULL)
353 			return -1;
354 		res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
355 				  ifname);
356 		if (os_snprintf_error(flen, res)) {
357 			os_free(cfile);
358 			return -1;
359 		}
360 	}
361 
362 	ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
363 	if (ctrl_conn == NULL) {
364 		os_free(cfile);
365 		return -1;
366 	}
367 
368 	if (attach && interactive)
369 		mon_conn = wpa_ctrl_open2(cfile, client_socket_dir);
370 	else
371 		mon_conn = NULL;
372 	os_free(cfile);
373 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
374 
375 	if (mon_conn) {
376 		if (wpa_ctrl_attach(mon_conn) == 0) {
377 			wpa_cli_attached = 1;
378 			if (interactive)
379 				eloop_register_read_sock(
380 					wpa_ctrl_get_fd(mon_conn),
381 					wpa_cli_mon_receive, NULL, NULL);
382 		} else {
383 			printf("Warning: Failed to attach to "
384 			       "wpa_supplicant.\n");
385 			wpa_cli_close_connection();
386 			return -1;
387 		}
388 	}
389 
390 	return 0;
391 }
392 
393 
wpa_cli_close_connection(void)394 static void wpa_cli_close_connection(void)
395 {
396 	if (ctrl_conn == NULL)
397 		return;
398 
399 	if (wpa_cli_attached) {
400 		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
401 		wpa_cli_attached = 0;
402 	}
403 	wpa_ctrl_close(ctrl_conn);
404 	ctrl_conn = NULL;
405 	if (mon_conn) {
406 		eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
407 		wpa_ctrl_close(mon_conn);
408 		mon_conn = NULL;
409 	}
410 }
411 
412 
wpa_cli_msg_cb(char * msg,size_t len)413 static void wpa_cli_msg_cb(char *msg, size_t len)
414 {
415 	printf("%s\n", msg);
416 }
417 
418 
_wpa_ctrl_command(struct wpa_ctrl * ctrl,char * cmd,int print)419 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
420 {
421 	char buf[4096];
422 	size_t len;
423 	int ret;
424 
425 	if (ctrl_conn == NULL) {
426 		printf("Not connected to wpa_supplicant - command dropped.\n");
427 		return -1;
428 	}
429 	if (ifname_prefix) {
430 		os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
431 			    ifname_prefix, cmd);
432 		buf[sizeof(buf) - 1] = '\0';
433 		cmd = buf;
434 	}
435 	len = sizeof(buf) - 1;
436 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
437 			       wpa_cli_msg_cb);
438 	if (ret == -2) {
439 		printf("'%s' command timed out.\n", cmd);
440 		return -2;
441 	} else if (ret < 0) {
442 		printf("'%s' command failed.\n", cmd);
443 		return -1;
444 	}
445 	if (print) {
446 		buf[len] = '\0';
447 		printf("%s", buf);
448 		if (interactive && len > 0 && buf[len - 1] != '\n')
449 			printf("\n");
450 	}
451 	return 0;
452 }
453 
454 
wpa_ctrl_command(struct wpa_ctrl * ctrl,char * cmd)455 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
456 {
457 	return _wpa_ctrl_command(ctrl, cmd, 1);
458 }
459 
460 
write_cmd(char * buf,size_t buflen,const char * cmd,int argc,char * argv[])461 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
462 		     char *argv[])
463 {
464 	int i, res;
465 	char *pos, *end;
466 
467 	pos = buf;
468 	end = buf + buflen;
469 
470 	res = os_snprintf(pos, end - pos, "%s", cmd);
471 	if (os_snprintf_error(end - pos, res))
472 		goto fail;
473 	pos += res;
474 
475 	for (i = 0; i < argc; i++) {
476 		res = os_snprintf(pos, end - pos, " %s", argv[i]);
477 		if (os_snprintf_error(end - pos, res))
478 			goto fail;
479 		pos += res;
480 	}
481 
482 	buf[buflen - 1] = '\0';
483 	return 0;
484 
485 fail:
486 	printf("Too long command\n");
487 	return -1;
488 }
489 
490 
wpa_cli_cmd(struct wpa_ctrl * ctrl,const char * cmd,int min_args,int argc,char * argv[])491 static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
492 		       int argc, char *argv[])
493 {
494 	char buf[4096];
495 	if (argc < min_args) {
496 		printf("Invalid %s command - at least %d argument%s "
497 		       "required.\n", cmd, min_args,
498 		       min_args > 1 ? "s are" : " is");
499 		return -1;
500 	}
501 	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
502 		return -1;
503 	return wpa_ctrl_command(ctrl, buf);
504 }
505 
506 
wpa_cli_cmd_ifname(struct wpa_ctrl * ctrl,int argc,char * argv[])507 static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
508 {
509 	return wpa_ctrl_command(ctrl, "IFNAME");
510 }
511 
512 
wpa_cli_cmd_status(struct wpa_ctrl * ctrl,int argc,char * argv[])513 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
514 {
515 	if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
516 		return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
517 	if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
518 		return wpa_ctrl_command(ctrl, "STATUS-WPS");
519 	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
520 		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
521 #ifdef ANDROID
522 	if (argc > 0 && os_strcmp(argv[0], "no_events") == 0)
523 		return wpa_ctrl_command(ctrl, "STATUS-NO_EVENTS");
524 #endif /* ANDROID */
525 	return wpa_ctrl_command(ctrl, "STATUS");
526 }
527 
528 
wpa_cli_cmd_ping(struct wpa_ctrl * ctrl,int argc,char * argv[])529 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
530 {
531 	return wpa_ctrl_command(ctrl, "PING");
532 }
533 
534 
wpa_cli_cmd_relog(struct wpa_ctrl * ctrl,int argc,char * argv[])535 static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
536 {
537 	return wpa_ctrl_command(ctrl, "RELOG");
538 }
539 
540 
wpa_cli_cmd_note(struct wpa_ctrl * ctrl,int argc,char * argv[])541 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
542 {
543 	return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
544 }
545 
546 
wpa_cli_cmd_mib(struct wpa_ctrl * ctrl,int argc,char * argv[])547 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
548 {
549 	return wpa_ctrl_command(ctrl, "MIB");
550 }
551 
552 
wpa_cli_cmd_pmksa(struct wpa_ctrl * ctrl,int argc,char * argv[])553 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
554 {
555 	return wpa_ctrl_command(ctrl, "PMKSA");
556 }
557 
558 
wpa_cli_cmd_pmksa_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])559 static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
560 				   char *argv[])
561 {
562 	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
563 }
564 
565 
wpa_cli_cmd_help(struct wpa_ctrl * ctrl,int argc,char * argv[])566 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
567 {
568 	print_help(argc > 0 ? argv[0] : NULL);
569 	return 0;
570 }
571 
572 
wpa_cli_complete_help(const char * str,int pos)573 static char ** wpa_cli_complete_help(const char *str, int pos)
574 {
575 	int arg = get_cmd_arg_num(str, pos);
576 	char **res = NULL;
577 
578 	switch (arg) {
579 	case 1:
580 		res = wpa_list_cmd_list();
581 		break;
582 	}
583 
584 	return res;
585 }
586 
587 
wpa_cli_cmd_license(struct wpa_ctrl * ctrl,int argc,char * argv[])588 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
589 {
590 	printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
591 	return 0;
592 }
593 
594 
wpa_cli_cmd_quit(struct wpa_ctrl * ctrl,int argc,char * argv[])595 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
596 {
597 	wpa_cli_quit = 1;
598 	if (interactive)
599 		eloop_terminate();
600 	return 0;
601 }
602 
603 
wpa_cli_cmd_set(struct wpa_ctrl * ctrl,int argc,char * argv[])604 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
605 {
606 	char cmd[256];
607 	int res;
608 
609 	if (argc == 1) {
610 		res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
611 		if (os_snprintf_error(sizeof(cmd), res)) {
612 			printf("Too long SET command.\n");
613 			return -1;
614 		}
615 		return wpa_ctrl_command(ctrl, cmd);
616 	}
617 
618 	return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
619 }
620 
621 
wpa_cli_complete_set(const char * str,int pos)622 static char ** wpa_cli_complete_set(const char *str, int pos)
623 {
624 	int arg = get_cmd_arg_num(str, pos);
625 	const char *fields[] = {
626 		/* runtime values */
627 		"EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
628 		"EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
629 		"dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
630 		"wps_fragment_size", "wps_version_number", "ampdu",
631 		"tdls_testing", "tdls_disabled", "pno", "radio_disabled",
632 		"uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
633 		"no_keep_alive",
634 		/* global configuration parameters */
635 #ifdef CONFIG_CTRL_IFACE
636 		"ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
637 #endif /* CONFIG_CTRL_IFACE */
638 		"eapol_version", "ap_scan", "bgscan",
639 #ifdef CONFIG_MESH
640 		"user_mpm", "max_peer_links", "mesh_max_inactivity",
641 		"dot11RSNASAERetransPeriod",
642 #endif /* CONFIG_MESH */
643 		"disable_scan_offload", "fast_reauth", "opensc_engine_path",
644 		"pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
645 		"pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
646 		"dot11RSNAConfigPMKLifetime",
647 		"dot11RSNAConfigPMKReauthThreshold",
648 		"dot11RSNAConfigSATimeout",
649 #ifndef CONFIG_NO_CONFIG_WRITE
650 		"update_config",
651 #endif /* CONFIG_NO_CONFIG_WRITE */
652 		"load_dynamic_eap",
653 #ifdef CONFIG_WPS
654 		"uuid", "device_name", "manufacturer", "model_name",
655 		"model_number", "serial_number", "device_type", "os_version",
656 		"config_methods", "wps_cred_processing", "wps_vendor_ext_m1",
657 #endif /* CONFIG_WPS */
658 #ifdef CONFIG_P2P
659 		"sec_device_type",
660 		"p2p_listen_reg_class", "p2p_listen_channel",
661 		"p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
662 		"p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
663 		"p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan",
664 		"p2p_no_go_freq", "p2p_add_cli_chan",
665 		"p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
666 		"p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
667 		"p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
668 		"ip_addr_start", "ip_addr_end",
669 #endif /* CONFIG_P2P */
670 		"country", "bss_max_count", "bss_expiration_age",
671 		"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
672 		"max_num_sta", "disassoc_low_ack",
673 #ifdef CONFIG_HS20
674 		"hs20",
675 #endif /* CONFIG_HS20 */
676 		"interworking", "hessid", "access_network_type", "pbc_in_m1",
677 		"autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
678 		"wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
679 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
680 		"sae_groups", "dtim_period", "beacon_int",
681 		"ap_vendor_elements", "ignore_old_scan_res", "freq_list",
682 		"scan_cur_freq", "sched_scan_interval",
683 		"tdls_external_control", "osu_dir", "wowlan_triggers",
684 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
685 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
686 		"reassoc_same_bss_optim", "wps_priority"
687 	};
688 	int i, num_fields = ARRAY_SIZE(fields);
689 
690 	if (arg == 1) {
691 		char **res = os_calloc(num_fields + 1, sizeof(char *));
692 		if (res == NULL)
693 			return NULL;
694 		for (i = 0; i < num_fields; i++) {
695 			res[i] = os_strdup(fields[i]);
696 			if (res[i] == NULL)
697 				return res;
698 		}
699 		return res;
700 	}
701 
702 	if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
703 		return cli_txt_list_array(&bsses);
704 
705 	return NULL;
706 }
707 
wpa_cli_cmd_dump(struct wpa_ctrl * ctrl,int argc,char * argv[])708 static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
709 {
710 	return wpa_ctrl_command(ctrl, "DUMP");
711 }
712 
713 
wpa_cli_cmd_get(struct wpa_ctrl * ctrl,int argc,char * argv[])714 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
715 {
716 	return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
717 }
718 
719 
wpa_cli_complete_get(const char * str,int pos)720 static char ** wpa_cli_complete_get(const char *str, int pos)
721 {
722 	int arg = get_cmd_arg_num(str, pos);
723 	const char *fields[] = {
724 #ifdef CONFIG_CTRL_IFACE
725 		"ctrl_interface", "ctrl_interface_group",
726 #endif /* CONFIG_CTRL_IFACE */
727 		"eapol_version", "ap_scan",
728 #ifdef CONFIG_MESH
729 		"user_mpm", "max_peer_links", "mesh_max_inactivity",
730 #endif /* CONFIG_MESH */
731 		"disable_scan_offload", "fast_reauth", "opensc_engine_path",
732 		"pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
733 		"pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
734 		"dot11RSNAConfigPMKLifetime",
735 		"dot11RSNAConfigPMKReauthThreshold",
736 		"dot11RSNAConfigSATimeout",
737 #ifndef CONFIG_NO_CONFIG_WRITE
738 		"update_config",
739 #endif /* CONFIG_NO_CONFIG_WRITE */
740 #ifdef CONFIG_WPS
741 		"device_name", "manufacturer", "model_name", "model_number",
742 		"serial_number", "config_methods", "wps_cred_processing",
743 #endif /* CONFIG_WPS */
744 #ifdef CONFIG_P2P
745 		"p2p_listen_reg_class", "p2p_listen_channel",
746 		"p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
747 		"p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
748 		"p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
749 		"p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
750 		"p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
751 		"p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
752 		"ip_addr_start", "ip_addr_end",
753 #endif /* CONFIG_P2P */
754 		"bss_max_count", "bss_expiration_age",
755 		"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
756 		"max_num_sta", "disassoc_low_ack",
757 #ifdef CONFIG_HS20
758 		"hs20",
759 #endif /* CONFIG_HS20 */
760 		"interworking", "access_network_type", "pbc_in_m1", "autoscan",
761 		"wps_nfc_dev_pw_id", "ext_password_backend",
762 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
763 		"dtim_period", "beacon_int", "ignore_old_scan_res",
764 		"scan_cur_freq", "sched_scan_interval",
765 		"tdls_external_control", "osu_dir", "wowlan_triggers",
766 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
767 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
768 		"reassoc_same_bss_optim"
769 	};
770 	int i, num_fields = ARRAY_SIZE(fields);
771 
772 	if (arg == 1) {
773 		char **res = os_calloc(num_fields + 1, sizeof(char *));
774 		if (res == NULL)
775 			return NULL;
776 		for (i = 0; i < num_fields; i++) {
777 			res[i] = os_strdup(fields[i]);
778 			if (res[i] == NULL)
779 				return res;
780 		}
781 		return res;
782 	}
783 
784 	return NULL;
785 }
786 
787 
wpa_cli_cmd_logoff(struct wpa_ctrl * ctrl,int argc,char * argv[])788 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
789 {
790 	return wpa_ctrl_command(ctrl, "LOGOFF");
791 }
792 
793 
wpa_cli_cmd_logon(struct wpa_ctrl * ctrl,int argc,char * argv[])794 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
795 {
796 	return wpa_ctrl_command(ctrl, "LOGON");
797 }
798 
799 
wpa_cli_cmd_reassociate(struct wpa_ctrl * ctrl,int argc,char * argv[])800 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
801 				   char *argv[])
802 {
803 	return wpa_ctrl_command(ctrl, "REASSOCIATE");
804 }
805 
806 
wpa_cli_cmd_reattach(struct wpa_ctrl * ctrl,int argc,char * argv[])807 static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
808 {
809 	return wpa_ctrl_command(ctrl, "REATTACH");
810 }
811 
812 
wpa_cli_cmd_preauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])813 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
814 				       char *argv[])
815 {
816 	return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
817 }
818 
819 
wpa_cli_cmd_ap_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])820 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
821 {
822 	return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
823 }
824 
825 
wpa_cli_cmd_scan_interval(struct wpa_ctrl * ctrl,int argc,char * argv[])826 static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
827 				     char *argv[])
828 {
829 	return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
830 }
831 
832 
wpa_cli_cmd_bss_expire_age(struct wpa_ctrl * ctrl,int argc,char * argv[])833 static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
834 				      char *argv[])
835 {
836 	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
837 }
838 
839 
wpa_cli_cmd_bss_expire_count(struct wpa_ctrl * ctrl,int argc,char * argv[])840 static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
841 				        char *argv[])
842 {
843 	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
844 }
845 
846 
wpa_cli_cmd_bss_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])847 static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
848 {
849 	char cmd[256];
850 	int res;
851 
852 	if (argc < 1)
853 		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
854 	else
855 		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
856 	if (os_snprintf_error(sizeof(cmd), res)) {
857 		printf("Too long BSS_FLUSH command.\n");
858 		return -1;
859 	}
860 	return wpa_ctrl_command(ctrl, cmd);
861 }
862 
863 
wpa_cli_cmd_stkstart(struct wpa_ctrl * ctrl,int argc,char * argv[])864 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
865 				char *argv[])
866 {
867 	return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
868 }
869 
870 
wpa_cli_cmd_ft_ds(struct wpa_ctrl * ctrl,int argc,char * argv[])871 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
872 {
873 	return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
874 }
875 
876 
wpa_cli_cmd_wps_pbc(struct wpa_ctrl * ctrl,int argc,char * argv[])877 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
878 {
879 	return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
880 }
881 
882 
wpa_cli_cmd_wps_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])883 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
884 {
885 	if (argc == 0) {
886 		printf("Invalid WPS_PIN command: need one or two arguments:\n"
887 		       "- BSSID: use 'any' to select any\n"
888 		       "- PIN: optional, used only with devices that have no "
889 		       "display\n");
890 		return -1;
891 	}
892 
893 	return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
894 }
895 
896 
wpa_cli_cmd_wps_check_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])897 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
898 				     char *argv[])
899 {
900 	return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
901 }
902 
903 
wpa_cli_cmd_wps_cancel(struct wpa_ctrl * ctrl,int argc,char * argv[])904 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
905 				  char *argv[])
906 {
907 	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
908 }
909 
910 
911 #ifdef CONFIG_WPS_NFC
912 
wpa_cli_cmd_wps_nfc(struct wpa_ctrl * ctrl,int argc,char * argv[])913 static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
914 {
915 	return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
916 }
917 
918 
wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl * ctrl,int argc,char * argv[])919 static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
920 					    char *argv[])
921 {
922 	return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
923 }
924 
925 
wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl * ctrl,int argc,char * argv[])926 static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
927 				     char *argv[])
928 {
929 	return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
930 }
931 
932 
wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl * ctrl,int argc,char * argv[])933 static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
934 					char *argv[])
935 {
936 	int ret;
937 	char *buf;
938 	size_t buflen;
939 
940 	if (argc != 1) {
941 		printf("Invalid 'wps_nfc_tag_read' command - one argument "
942 		       "is required.\n");
943 		return -1;
944 	}
945 
946 	buflen = 18 + os_strlen(argv[0]);
947 	buf = os_malloc(buflen);
948 	if (buf == NULL)
949 		return -1;
950 	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
951 
952 	ret = wpa_ctrl_command(ctrl, buf);
953 	os_free(buf);
954 
955 	return ret;
956 }
957 
958 
wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl * ctrl,int argc,char * argv[])959 static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
960 					    char *argv[])
961 {
962 	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
963 }
964 
965 
wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl * ctrl,int argc,char * argv[])966 static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
967 					    char *argv[])
968 {
969 	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
970 }
971 
972 
wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl * ctrl,int argc,char * argv[])973 static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
974 					   char *argv[])
975 {
976 	return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
977 }
978 
979 #endif /* CONFIG_WPS_NFC */
980 
981 
wpa_cli_cmd_wps_reg(struct wpa_ctrl * ctrl,int argc,char * argv[])982 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
983 {
984 	char cmd[256];
985 	int res;
986 
987 	if (argc == 2)
988 		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
989 				  argv[0], argv[1]);
990 	else if (argc == 5 || argc == 6) {
991 		char ssid_hex[2 * SSID_MAX_LEN + 1];
992 		char key_hex[2 * 64 + 1];
993 		int i;
994 
995 		ssid_hex[0] = '\0';
996 		for (i = 0; i < SSID_MAX_LEN; i++) {
997 			if (argv[2][i] == '\0')
998 				break;
999 			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1000 		}
1001 
1002 		key_hex[0] = '\0';
1003 		if (argc == 6) {
1004 			for (i = 0; i < 64; i++) {
1005 				if (argv[5][i] == '\0')
1006 					break;
1007 				os_snprintf(&key_hex[i * 2], 3, "%02x",
1008 					    argv[5][i]);
1009 			}
1010 		}
1011 
1012 		res = os_snprintf(cmd, sizeof(cmd),
1013 				  "WPS_REG %s %s %s %s %s %s",
1014 				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
1015 				  key_hex);
1016 	} else {
1017 		printf("Invalid WPS_REG command: need two arguments:\n"
1018 		       "- BSSID of the target AP\n"
1019 		       "- AP PIN\n");
1020 		printf("Alternatively, six arguments can be used to "
1021 		       "reconfigure the AP:\n"
1022 		       "- BSSID of the target AP\n"
1023 		       "- AP PIN\n"
1024 		       "- new SSID\n"
1025 		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1026 		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
1027 		       "- new key\n");
1028 		return -1;
1029 	}
1030 
1031 	if (os_snprintf_error(sizeof(cmd), res)) {
1032 		printf("Too long WPS_REG command.\n");
1033 		return -1;
1034 	}
1035 	return wpa_ctrl_command(ctrl, cmd);
1036 }
1037 
1038 
wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])1039 static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
1040 				  char *argv[])
1041 {
1042 	return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
1043 }
1044 
1045 
wpa_cli_cmd_wps_er_start(struct wpa_ctrl * ctrl,int argc,char * argv[])1046 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
1047 				    char *argv[])
1048 {
1049 	return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
1050 }
1051 
1052 
wpa_cli_cmd_wps_er_stop(struct wpa_ctrl * ctrl,int argc,char * argv[])1053 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
1054 				   char *argv[])
1055 {
1056 	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
1057 
1058 }
1059 
1060 
wpa_cli_cmd_wps_er_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])1061 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
1062 				  char *argv[])
1063 {
1064 	if (argc < 2) {
1065 		printf("Invalid WPS_ER_PIN command: need at least two "
1066 		       "arguments:\n"
1067 		       "- UUID: use 'any' to select any\n"
1068 		       "- PIN: Enrollee PIN\n"
1069 		       "optional: - Enrollee MAC address\n");
1070 		return -1;
1071 	}
1072 
1073 	return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
1074 }
1075 
1076 
wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl * ctrl,int argc,char * argv[])1077 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1078 				  char *argv[])
1079 {
1080 	return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
1081 }
1082 
1083 
wpa_cli_cmd_wps_er_learn(struct wpa_ctrl * ctrl,int argc,char * argv[])1084 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1085 				    char *argv[])
1086 {
1087 	if (argc != 2) {
1088 		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1089 		       "- UUID: specify which AP to use\n"
1090 		       "- PIN: AP PIN\n");
1091 		return -1;
1092 	}
1093 
1094 	return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
1095 }
1096 
1097 
wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl * ctrl,int argc,char * argv[])1098 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1099 					 char *argv[])
1100 {
1101 	if (argc != 2) {
1102 		printf("Invalid WPS_ER_SET_CONFIG command: need two "
1103 		       "arguments:\n"
1104 		       "- UUID: specify which AP to use\n"
1105 		       "- Network configuration id\n");
1106 		return -1;
1107 	}
1108 
1109 	return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
1110 }
1111 
1112 
wpa_cli_cmd_wps_er_config(struct wpa_ctrl * ctrl,int argc,char * argv[])1113 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1114 				     char *argv[])
1115 {
1116 	char cmd[256];
1117 	int res;
1118 
1119 	if (argc == 5 || argc == 6) {
1120 		char ssid_hex[2 * SSID_MAX_LEN + 1];
1121 		char key_hex[2 * 64 + 1];
1122 		int i;
1123 
1124 		ssid_hex[0] = '\0';
1125 		for (i = 0; i < SSID_MAX_LEN; i++) {
1126 			if (argv[2][i] == '\0')
1127 				break;
1128 			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1129 		}
1130 
1131 		key_hex[0] = '\0';
1132 		if (argc == 6) {
1133 			for (i = 0; i < 64; i++) {
1134 				if (argv[5][i] == '\0')
1135 					break;
1136 				os_snprintf(&key_hex[i * 2], 3, "%02x",
1137 					    argv[5][i]);
1138 			}
1139 		}
1140 
1141 		res = os_snprintf(cmd, sizeof(cmd),
1142 				  "WPS_ER_CONFIG %s %s %s %s %s %s",
1143 				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
1144 				  key_hex);
1145 	} else {
1146 		printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1147 		       "- AP UUID\n"
1148 		       "- AP PIN\n"
1149 		       "- new SSID\n"
1150 		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1151 		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
1152 		       "- new key\n");
1153 		return -1;
1154 	}
1155 
1156 	if (os_snprintf_error(sizeof(cmd), res)) {
1157 		printf("Too long WPS_ER_CONFIG command.\n");
1158 		return -1;
1159 	}
1160 	return wpa_ctrl_command(ctrl, cmd);
1161 }
1162 
1163 
1164 #ifdef CONFIG_WPS_NFC
wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl * ctrl,int argc,char * argv[])1165 static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1166 					       char *argv[])
1167 {
1168 	if (argc != 2) {
1169 		printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1170 		       "arguments:\n"
1171 		       "- WPS/NDEF: token format\n"
1172 		       "- UUID: specify which AP to use\n");
1173 		return -1;
1174 	}
1175 
1176 	return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1177 }
1178 #endif /* CONFIG_WPS_NFC */
1179 
1180 
wpa_cli_cmd_ibss_rsn(struct wpa_ctrl * ctrl,int argc,char * argv[])1181 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1182 {
1183 	return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
1184 }
1185 
1186 
wpa_cli_cmd_level(struct wpa_ctrl * ctrl,int argc,char * argv[])1187 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1188 {
1189 	return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
1190 }
1191 
1192 
wpa_cli_cmd_identity(struct wpa_ctrl * ctrl,int argc,char * argv[])1193 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1194 {
1195 	char cmd[256], *pos, *end;
1196 	int i, ret;
1197 
1198 	if (argc < 2) {
1199 		printf("Invalid IDENTITY command: needs two arguments "
1200 		       "(network id and identity)\n");
1201 		return -1;
1202 	}
1203 
1204 	end = cmd + sizeof(cmd);
1205 	pos = cmd;
1206 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1207 			  argv[0], argv[1]);
1208 	if (os_snprintf_error(end - pos, ret)) {
1209 		printf("Too long IDENTITY command.\n");
1210 		return -1;
1211 	}
1212 	pos += ret;
1213 	for (i = 2; i < argc; i++) {
1214 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1215 		if (os_snprintf_error(end - pos, ret)) {
1216 			printf("Too long IDENTITY command.\n");
1217 			return -1;
1218 		}
1219 		pos += ret;
1220 	}
1221 
1222 	return wpa_ctrl_command(ctrl, cmd);
1223 }
1224 
1225 
wpa_cli_cmd_password(struct wpa_ctrl * ctrl,int argc,char * argv[])1226 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1227 {
1228 	char cmd[256], *pos, *end;
1229 	int i, ret;
1230 
1231 	if (argc < 2) {
1232 		printf("Invalid PASSWORD command: needs two arguments "
1233 		       "(network id and password)\n");
1234 		return -1;
1235 	}
1236 
1237 	end = cmd + sizeof(cmd);
1238 	pos = cmd;
1239 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1240 			  argv[0], argv[1]);
1241 	if (os_snprintf_error(end - pos, ret)) {
1242 		printf("Too long PASSWORD command.\n");
1243 		return -1;
1244 	}
1245 	pos += ret;
1246 	for (i = 2; i < argc; i++) {
1247 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1248 		if (os_snprintf_error(end - pos, ret)) {
1249 			printf("Too long PASSWORD command.\n");
1250 			return -1;
1251 		}
1252 		pos += ret;
1253 	}
1254 
1255 	return wpa_ctrl_command(ctrl, cmd);
1256 }
1257 
1258 
wpa_cli_cmd_new_password(struct wpa_ctrl * ctrl,int argc,char * argv[])1259 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1260 				    char *argv[])
1261 {
1262 	char cmd[256], *pos, *end;
1263 	int i, ret;
1264 
1265 	if (argc < 2) {
1266 		printf("Invalid NEW_PASSWORD command: needs two arguments "
1267 		       "(network id and password)\n");
1268 		return -1;
1269 	}
1270 
1271 	end = cmd + sizeof(cmd);
1272 	pos = cmd;
1273 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1274 			  argv[0], argv[1]);
1275 	if (os_snprintf_error(end - pos, ret)) {
1276 		printf("Too long NEW_PASSWORD command.\n");
1277 		return -1;
1278 	}
1279 	pos += ret;
1280 	for (i = 2; i < argc; i++) {
1281 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1282 		if (os_snprintf_error(end - pos, ret)) {
1283 			printf("Too long NEW_PASSWORD command.\n");
1284 			return -1;
1285 		}
1286 		pos += ret;
1287 	}
1288 
1289 	return wpa_ctrl_command(ctrl, cmd);
1290 }
1291 
1292 
wpa_cli_cmd_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])1293 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1294 {
1295 	char cmd[256], *pos, *end;
1296 	int i, ret;
1297 
1298 	if (argc < 2) {
1299 		printf("Invalid PIN command: needs two arguments "
1300 		       "(network id and pin)\n");
1301 		return -1;
1302 	}
1303 
1304 	end = cmd + sizeof(cmd);
1305 	pos = cmd;
1306 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1307 			  argv[0], argv[1]);
1308 	if (os_snprintf_error(end - pos, ret)) {
1309 		printf("Too long PIN command.\n");
1310 		return -1;
1311 	}
1312 	pos += ret;
1313 	for (i = 2; i < argc; i++) {
1314 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1315 		if (os_snprintf_error(end - pos, ret)) {
1316 			printf("Too long PIN command.\n");
1317 			return -1;
1318 		}
1319 		pos += ret;
1320 	}
1321 	return wpa_ctrl_command(ctrl, cmd);
1322 }
1323 
1324 
wpa_cli_cmd_otp(struct wpa_ctrl * ctrl,int argc,char * argv[])1325 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1326 {
1327 	char cmd[256], *pos, *end;
1328 	int i, ret;
1329 
1330 	if (argc < 2) {
1331 		printf("Invalid OTP command: needs two arguments (network "
1332 		       "id and password)\n");
1333 		return -1;
1334 	}
1335 
1336 	end = cmd + sizeof(cmd);
1337 	pos = cmd;
1338 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1339 			  argv[0], argv[1]);
1340 	if (os_snprintf_error(end - pos, ret)) {
1341 		printf("Too long OTP command.\n");
1342 		return -1;
1343 	}
1344 	pos += ret;
1345 	for (i = 2; i < argc; i++) {
1346 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1347 		if (os_snprintf_error(end - pos, ret)) {
1348 			printf("Too long OTP command.\n");
1349 			return -1;
1350 		}
1351 		pos += ret;
1352 	}
1353 
1354 	return wpa_ctrl_command(ctrl, cmd);
1355 }
1356 
1357 
wpa_cli_cmd_sim(struct wpa_ctrl * ctrl,int argc,char * argv[])1358 static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1359 {
1360 	char cmd[256], *pos, *end;
1361 	int i, ret;
1362 
1363 	if (argc < 2) {
1364 		printf("Invalid SIM command: needs two arguments "
1365 		       "(network id and SIM operation response)\n");
1366 		return -1;
1367 	}
1368 
1369 	end = cmd + sizeof(cmd);
1370 	pos = cmd;
1371 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1372 			  argv[0], argv[1]);
1373 	if (os_snprintf_error(end - pos, ret)) {
1374 		printf("Too long SIM command.\n");
1375 		return -1;
1376 	}
1377 	pos += ret;
1378 	for (i = 2; i < argc; i++) {
1379 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1380 		if (os_snprintf_error(end - pos, ret)) {
1381 			printf("Too long SIM command.\n");
1382 			return -1;
1383 		}
1384 		pos += ret;
1385 	}
1386 	return wpa_ctrl_command(ctrl, cmd);
1387 }
1388 
1389 
wpa_cli_cmd_passphrase(struct wpa_ctrl * ctrl,int argc,char * argv[])1390 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1391 				  char *argv[])
1392 {
1393 	char cmd[256], *pos, *end;
1394 	int i, ret;
1395 
1396 	if (argc < 2) {
1397 		printf("Invalid PASSPHRASE command: needs two arguments "
1398 		       "(network id and passphrase)\n");
1399 		return -1;
1400 	}
1401 
1402 	end = cmd + sizeof(cmd);
1403 	pos = cmd;
1404 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1405 			  argv[0], argv[1]);
1406 	if (os_snprintf_error(end - pos, ret)) {
1407 		printf("Too long PASSPHRASE command.\n");
1408 		return -1;
1409 	}
1410 	pos += ret;
1411 	for (i = 2; i < argc; i++) {
1412 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1413 		if (os_snprintf_error(end - pos, ret)) {
1414 			printf("Too long PASSPHRASE command.\n");
1415 			return -1;
1416 		}
1417 		pos += ret;
1418 	}
1419 
1420 	return wpa_ctrl_command(ctrl, cmd);
1421 }
1422 
1423 
wpa_cli_cmd_bssid(struct wpa_ctrl * ctrl,int argc,char * argv[])1424 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1425 {
1426 	if (argc < 2) {
1427 		printf("Invalid BSSID command: needs two arguments (network "
1428 		       "id and BSSID)\n");
1429 		return -1;
1430 	}
1431 
1432 	return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
1433 }
1434 
1435 
wpa_cli_cmd_blacklist(struct wpa_ctrl * ctrl,int argc,char * argv[])1436 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1437 {
1438 	return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1439 }
1440 
1441 
wpa_cli_cmd_log_level(struct wpa_ctrl * ctrl,int argc,char * argv[])1442 static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1443 {
1444 	return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
1445 }
1446 
1447 
wpa_cli_cmd_list_networks(struct wpa_ctrl * ctrl,int argc,char * argv[])1448 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1449 				     char *argv[])
1450 {
1451 	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1452 }
1453 
1454 
wpa_cli_cmd_select_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1455 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1456 				      char *argv[])
1457 {
1458 	return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
1459 }
1460 
1461 
wpa_cli_cmd_enable_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1462 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1463 				      char *argv[])
1464 {
1465 	return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
1466 }
1467 
1468 
wpa_cli_cmd_disable_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1469 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1470 				       char *argv[])
1471 {
1472 	return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
1473 }
1474 
1475 
wpa_cli_cmd_add_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1476 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1477 				   char *argv[])
1478 {
1479 	int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
1480 	if (interactive)
1481 		update_networks(ctrl);
1482 	return res;
1483 }
1484 
1485 
wpa_cli_cmd_remove_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1486 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1487 				      char *argv[])
1488 {
1489 	int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1490 	if (interactive)
1491 		update_networks(ctrl);
1492 	return res;
1493 }
1494 
1495 
wpa_cli_show_network_variables(void)1496 static void wpa_cli_show_network_variables(void)
1497 {
1498 	printf("set_network variables:\n"
1499 	       "  ssid (network name, SSID)\n"
1500 	       "  psk (WPA passphrase or pre-shared key)\n"
1501 	       "  key_mgmt (key management protocol)\n"
1502 	       "  identity (EAP identity)\n"
1503 	       "  password (EAP password)\n"
1504 	       "  ...\n"
1505 	       "\n"
1506 	       "Note: Values are entered in the same format as the "
1507 	       "configuration file is using,\n"
1508 	       "i.e., strings values need to be inside double quotation "
1509 	       "marks.\n"
1510 	       "For example: set_network 1 ssid \"network name\"\n"
1511 	       "\n"
1512 	       "Please see wpa_supplicant.conf documentation for full list "
1513 	       "of\navailable variables.\n");
1514 }
1515 
1516 
wpa_cli_cmd_set_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1517 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1518 				   char *argv[])
1519 {
1520 	if (argc == 0) {
1521 		wpa_cli_show_network_variables();
1522 		return 0;
1523 	}
1524 
1525 	if (argc < 3) {
1526 		printf("Invalid SET_NETWORK command: needs three arguments\n"
1527 		       "(network id, variable name, and value)\n");
1528 		return -1;
1529 	}
1530 
1531 	return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
1532 }
1533 
1534 
wpa_cli_cmd_get_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1535 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1536 				   char *argv[])
1537 {
1538 	if (argc == 0) {
1539 		wpa_cli_show_network_variables();
1540 		return 0;
1541 	}
1542 
1543 	if (argc != 2) {
1544 		printf("Invalid GET_NETWORK command: needs two arguments\n"
1545 		       "(network id and variable name)\n");
1546 		return -1;
1547 	}
1548 
1549 	return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1550 }
1551 
1552 
1553 static const char *network_fields[] = {
1554 	"ssid", "scan_ssid", "bssid", "bssid_blacklist",
1555 	"bssid_whitelist", "psk", "proto", "key_mgmt",
1556 	"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
1557 	"freq_list", "max_oper_chwidth",
1558 #ifdef IEEE8021X_EAPOL
1559 	"eap", "identity", "anonymous_identity", "password", "ca_cert",
1560 	"ca_path", "client_cert", "private_key", "private_key_passwd",
1561 	"dh_file", "subject_match", "altsubject_match",
1562 	"domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
1563 	"client_cert2", "private_key2", "private_key2_passwd",
1564 	"dh_file2", "subject_match2", "altsubject_match2",
1565 	"domain_suffix_match2", "domain_match2", "phase1", "phase2",
1566 	"pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
1567 	"pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
1568 	"engine", "engine2", "eapol_flags", "sim_num",
1569 	"openssl_ciphers", "erp",
1570 #endif /* IEEE8021X_EAPOL */
1571 	"wep_key0", "wep_key1", "wep_key2", "wep_key3",
1572 	"wep_tx_keyidx", "priority",
1573 #ifdef IEEE8021X_EAPOL
1574 	"eap_workaround", "pac_file", "fragment_size", "ocsp",
1575 #endif /* IEEE8021X_EAPOL */
1576 #ifdef CONFIG_MESH
1577 	"mode", "no_auto_peer",
1578 #else /* CONFIG_MESH */
1579 	"mode",
1580 #endif /* CONFIG_MESH */
1581 	"proactive_key_caching", "disabled", "id_str",
1582 #ifdef CONFIG_IEEE80211W
1583 	"ieee80211w",
1584 #endif /* CONFIG_IEEE80211W */
1585 	"peerkey", "mixed_cell", "frequency", "fixed_freq",
1586 #ifdef CONFIG_MESH
1587 	"mesh_basic_rates", "dot11MeshMaxRetries",
1588 	"dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
1589 	"dot11MeshHoldingTimeout",
1590 #endif /* CONFIG_MESH */
1591 	"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
1592 #ifdef CONFIG_P2P
1593 	"go_p2p_dev_addr", "p2p_client_list", "psk_list",
1594 #endif /* CONFIG_P2P */
1595 #ifdef CONFIG_HT_OVERRIDES
1596 	"disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
1597 	"ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
1598 	"ampdu_density", "ht_mcs",
1599 #endif /* CONFIG_HT_OVERRIDES */
1600 #ifdef CONFIG_VHT_OVERRIDES
1601 	"disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
1602 	"vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
1603 	"vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
1604 	"vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
1605 	"vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
1606 	"vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
1607 #endif /* CONFIG_VHT_OVERRIDES */
1608 	"ap_max_inactivity", "dtim_period", "beacon_int",
1609 #ifdef CONFIG_MACSEC
1610 	"macsec_policy",
1611 #endif /* CONFIG_MACSEC */
1612 #ifdef CONFIG_HS20
1613 	"update_identifier",
1614 #endif /* CONFIG_HS20 */
1615 	"mac_addr", "pbss"
1616 };
1617 
1618 
wpa_cli_complete_network(const char * str,int pos)1619 static char ** wpa_cli_complete_network(const char *str, int pos)
1620 {
1621 	int arg = get_cmd_arg_num(str, pos);
1622 	int i, num_fields = ARRAY_SIZE(network_fields);
1623 	char **res = NULL;
1624 
1625 	switch (arg) {
1626 	case 1:
1627 		res = cli_txt_list_array(&networks);
1628 		break;
1629 	case 2:
1630 		res = os_calloc(num_fields + 1, sizeof(char *));
1631 		if (res == NULL)
1632 			return NULL;
1633 		for (i = 0; i < num_fields; i++) {
1634 			res[i] = os_strdup(network_fields[i]);
1635 			if (res[i] == NULL)
1636 				break;
1637 		}
1638 	}
1639 	return res;
1640 }
1641 
1642 
wpa_cli_complete_network_id(const char * str,int pos)1643 static char ** wpa_cli_complete_network_id(const char *str, int pos)
1644 {
1645 	int arg = get_cmd_arg_num(str, pos);
1646 	if (arg == 1)
1647 		return cli_txt_list_array(&networks);
1648 	return NULL;
1649 }
1650 
1651 
wpa_cli_cmd_dup_network(struct wpa_ctrl * ctrl,int argc,char * argv[])1652 static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1653 				   char *argv[])
1654 {
1655 	if (argc == 0) {
1656 		wpa_cli_show_network_variables();
1657 		return 0;
1658 	}
1659 
1660 	if (argc < 3) {
1661 		printf("Invalid DUP_NETWORK command: needs three arguments\n"
1662 		       "(src netid, dest netid, and variable name)\n");
1663 		return -1;
1664 	}
1665 
1666 	return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1667 }
1668 
1669 
wpa_cli_complete_dup_network(const char * str,int pos)1670 static char ** wpa_cli_complete_dup_network(const char *str, int pos)
1671 {
1672 	int arg = get_cmd_arg_num(str, pos);
1673 	int i, num_fields = ARRAY_SIZE(network_fields);
1674 	char **res = NULL;
1675 
1676 	switch (arg) {
1677 	case 1:
1678 	case 2:
1679 		res = cli_txt_list_array(&networks);
1680 		break;
1681 	case 3:
1682 		res = os_calloc(num_fields + 1, sizeof(char *));
1683 		if (res == NULL)
1684 			return NULL;
1685 		for (i = 0; i < num_fields; i++) {
1686 			res[i] = os_strdup(network_fields[i]);
1687 			if (res[i] == NULL)
1688 				break;
1689 		}
1690 	}
1691 	return res;
1692 }
1693 
1694 
wpa_cli_cmd_list_creds(struct wpa_ctrl * ctrl,int argc,char * argv[])1695 static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1696 				  char *argv[])
1697 {
1698 	return wpa_ctrl_command(ctrl, "LIST_CREDS");
1699 }
1700 
1701 
wpa_cli_cmd_add_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1702 static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1703 {
1704 	return wpa_ctrl_command(ctrl, "ADD_CRED");
1705 }
1706 
1707 
wpa_cli_cmd_remove_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1708 static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1709 				   char *argv[])
1710 {
1711 	return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1712 }
1713 
1714 
wpa_cli_cmd_set_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1715 static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1716 {
1717 	if (argc != 3) {
1718 		printf("Invalid SET_CRED command: needs three arguments\n"
1719 		       "(cred id, variable name, and value)\n");
1720 		return -1;
1721 	}
1722 
1723 	return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
1724 }
1725 
1726 
wpa_cli_cmd_get_cred(struct wpa_ctrl * ctrl,int argc,char * argv[])1727 static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1728 {
1729 	if (argc != 2) {
1730 		printf("Invalid GET_CRED command: needs two arguments\n"
1731 		       "(cred id, variable name)\n");
1732 		return -1;
1733 	}
1734 
1735 	return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1736 }
1737 
1738 
wpa_cli_cmd_disconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])1739 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1740 				  char *argv[])
1741 {
1742 	return wpa_ctrl_command(ctrl, "DISCONNECT");
1743 }
1744 
1745 
wpa_cli_cmd_reconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])1746 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1747 				  char *argv[])
1748 {
1749 	return wpa_ctrl_command(ctrl, "RECONNECT");
1750 }
1751 
1752 
wpa_cli_cmd_save_config(struct wpa_ctrl * ctrl,int argc,char * argv[])1753 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1754 				   char *argv[])
1755 {
1756 	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1757 }
1758 
1759 
wpa_cli_cmd_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])1760 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1761 {
1762 	return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
1763 }
1764 
1765 
wpa_cli_cmd_scan_results(struct wpa_ctrl * ctrl,int argc,char * argv[])1766 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1767 				    char *argv[])
1768 {
1769 	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1770 }
1771 
1772 
wpa_cli_cmd_abort_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])1773 static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc,
1774 				  char *argv[])
1775 {
1776 	return wpa_ctrl_command(ctrl, "ABORT_SCAN");
1777 }
1778 
1779 
wpa_cli_cmd_bss(struct wpa_ctrl * ctrl,int argc,char * argv[])1780 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1781 {
1782 	return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1783 }
1784 
1785 
wpa_cli_complete_bss(const char * str,int pos)1786 static char ** wpa_cli_complete_bss(const char *str, int pos)
1787 {
1788 	int arg = get_cmd_arg_num(str, pos);
1789 	char **res = NULL;
1790 
1791 	switch (arg) {
1792 	case 1:
1793 		res = cli_txt_list_array(&bsses);
1794 		break;
1795 	}
1796 
1797 	return res;
1798 }
1799 
1800 
wpa_cli_cmd_get_capability(struct wpa_ctrl * ctrl,int argc,char * argv[])1801 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1802 				      char *argv[])
1803 {
1804 	if (argc < 1 || argc > 2) {
1805 		printf("Invalid GET_CAPABILITY command: need either one or "
1806 		       "two arguments\n");
1807 		return -1;
1808 	}
1809 
1810 	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1811 		printf("Invalid GET_CAPABILITY command: second argument, "
1812 		       "if any, must be 'strict'\n");
1813 		return -1;
1814 	}
1815 
1816 	return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1817 }
1818 
1819 
wpa_cli_list_interfaces(struct wpa_ctrl * ctrl)1820 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1821 {
1822 	printf("Available interfaces:\n");
1823 	return wpa_ctrl_command(ctrl, "INTERFACES");
1824 }
1825 
1826 
wpa_cli_cmd_interface(struct wpa_ctrl * ctrl,int argc,char * argv[])1827 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1828 {
1829 	if (argc < 1) {
1830 		wpa_cli_list_interfaces(ctrl);
1831 		return 0;
1832 	}
1833 
1834 	wpa_cli_close_connection();
1835 	os_free(ctrl_ifname);
1836 	ctrl_ifname = os_strdup(argv[0]);
1837 	if (!ctrl_ifname) {
1838 		printf("Failed to allocate memory\n");
1839 		return 0;
1840 	}
1841 
1842 	if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
1843 		printf("Connected to interface '%s.\n", ctrl_ifname);
1844 	} else {
1845 		printf("Could not connect to interface '%s' - re-trying\n",
1846 		       ctrl_ifname);
1847 	}
1848 	return 0;
1849 }
1850 
1851 
wpa_cli_cmd_reconfigure(struct wpa_ctrl * ctrl,int argc,char * argv[])1852 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1853 				   char *argv[])
1854 {
1855 	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1856 }
1857 
1858 
wpa_cli_cmd_terminate(struct wpa_ctrl * ctrl,int argc,char * argv[])1859 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1860 				 char *argv[])
1861 {
1862 	return wpa_ctrl_command(ctrl, "TERMINATE");
1863 }
1864 
1865 
wpa_cli_cmd_interface_add(struct wpa_ctrl * ctrl,int argc,char * argv[])1866 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1867 				     char *argv[])
1868 {
1869 	char cmd[256];
1870 	int res;
1871 
1872 	if (argc < 1) {
1873 		printf("Invalid INTERFACE_ADD command: needs at least one "
1874 		       "argument (interface name)\n"
1875 		       "All arguments: ifname confname driver ctrl_interface "
1876 		       "driver_param bridge_name [create]\n");
1877 		return -1;
1878 	}
1879 
1880 	/*
1881 	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1882 	 * <driver_param>TAB<bridge_name>[TAB<create>[TAB<type>]]
1883 	 */
1884 	res = os_snprintf(cmd, sizeof(cmd),
1885 			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
1886 			  argv[0],
1887 			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1888 			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1889 			  argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "",
1890 			  argc > 7 ? argv[7] : "");
1891 	if (os_snprintf_error(sizeof(cmd), res))
1892 		return -1;
1893 	cmd[sizeof(cmd) - 1] = '\0';
1894 	return wpa_ctrl_command(ctrl, cmd);
1895 }
1896 
1897 
wpa_cli_cmd_interface_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])1898 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1899 					char *argv[])
1900 {
1901 	return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1902 }
1903 
1904 
wpa_cli_cmd_interface_list(struct wpa_ctrl * ctrl,int argc,char * argv[])1905 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1906 				      char *argv[])
1907 {
1908 	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1909 }
1910 
1911 
1912 #ifdef CONFIG_AP
wpa_cli_cmd_sta(struct wpa_ctrl * ctrl,int argc,char * argv[])1913 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1914 {
1915 	return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1916 }
1917 
1918 
wpa_ctrl_command_sta(struct wpa_ctrl * ctrl,char * cmd,char * addr,size_t addr_len)1919 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1920 				char *addr, size_t addr_len)
1921 {
1922 	char buf[4096], *pos;
1923 	size_t len;
1924 	int ret;
1925 
1926 	if (ctrl_conn == NULL) {
1927 		printf("Not connected to hostapd - command dropped.\n");
1928 		return -1;
1929 	}
1930 	if (ifname_prefix) {
1931 		os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
1932 			    ifname_prefix, cmd);
1933 		buf[sizeof(buf) - 1] = '\0';
1934 		cmd = buf;
1935 	}
1936 	len = sizeof(buf) - 1;
1937 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1938 			       wpa_cli_msg_cb);
1939 	if (ret == -2) {
1940 		printf("'%s' command timed out.\n", cmd);
1941 		return -2;
1942 	} else if (ret < 0) {
1943 		printf("'%s' command failed.\n", cmd);
1944 		return -1;
1945 	}
1946 
1947 	buf[len] = '\0';
1948 	if (os_memcmp(buf, "FAIL", 4) == 0)
1949 		return -1;
1950 	printf("%s", buf);
1951 
1952 	pos = buf;
1953 	while (*pos != '\0' && *pos != '\n')
1954 		pos++;
1955 	*pos = '\0';
1956 	os_strlcpy(addr, buf, addr_len);
1957 	return 0;
1958 }
1959 
1960 
wpa_cli_cmd_all_sta(struct wpa_ctrl * ctrl,int argc,char * argv[])1961 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1962 {
1963 	char addr[32], cmd[64];
1964 
1965 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1966 		return 0;
1967 	do {
1968 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1969 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1970 
1971 	return -1;
1972 }
1973 
1974 
wpa_cli_cmd_deauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])1975 static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1976 				      char *argv[])
1977 {
1978 	return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1979 }
1980 
1981 
wpa_cli_cmd_disassociate(struct wpa_ctrl * ctrl,int argc,char * argv[])1982 static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1983 				    char *argv[])
1984 {
1985 	return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1986 }
1987 
wpa_cli_cmd_chanswitch(struct wpa_ctrl * ctrl,int argc,char * argv[])1988 static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1989 				    char *argv[])
1990 {
1991 	return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1992 }
1993 
1994 #endif /* CONFIG_AP */
1995 
1996 
wpa_cli_cmd_suspend(struct wpa_ctrl * ctrl,int argc,char * argv[])1997 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1998 {
1999 	return wpa_ctrl_command(ctrl, "SUSPEND");
2000 }
2001 
2002 
wpa_cli_cmd_resume(struct wpa_ctrl * ctrl,int argc,char * argv[])2003 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
2004 {
2005 	return wpa_ctrl_command(ctrl, "RESUME");
2006 }
2007 
2008 
2009 #ifdef CONFIG_TESTING_OPTIONS
wpa_cli_cmd_drop_sa(struct wpa_ctrl * ctrl,int argc,char * argv[])2010 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
2011 {
2012 	return wpa_ctrl_command(ctrl, "DROP_SA");
2013 }
2014 #endif /* CONFIG_TESTING_OPTIONS */
2015 
2016 
wpa_cli_cmd_roam(struct wpa_ctrl * ctrl,int argc,char * argv[])2017 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
2018 {
2019 	return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
2020 }
2021 
2022 
2023 #ifdef CONFIG_MESH
2024 
wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl * ctrl,int argc,char * argv[])2025 static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
2026 					  char *argv[])
2027 {
2028 	return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
2029 }
2030 
2031 
wpa_cli_cmd_mesh_group_add(struct wpa_ctrl * ctrl,int argc,char * argv[])2032 static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
2033 				      char *argv[])
2034 {
2035 	return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
2036 }
2037 
2038 
wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])2039 static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
2040 					 char *argv[])
2041 {
2042 	return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
2043 }
2044 
2045 
wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])2046 static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
2047 					char *argv[])
2048 {
2049 	return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
2050 }
2051 
2052 
wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl * ctrl,int argc,char * argv[])2053 static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
2054 				     char *argv[])
2055 {
2056 	return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
2057 }
2058 
2059 #endif /* CONFIG_MESH */
2060 
2061 
2062 #ifdef CONFIG_P2P
2063 
wpa_cli_cmd_p2p_find(struct wpa_ctrl * ctrl,int argc,char * argv[])2064 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2065 {
2066 	return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
2067 }
2068 
2069 
wpa_cli_complete_p2p_find(const char * str,int pos)2070 static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
2071 {
2072 	char **res = NULL;
2073 	int arg = get_cmd_arg_num(str, pos);
2074 
2075 	res = os_calloc(6, sizeof(char *));
2076 	if (res == NULL)
2077 		return NULL;
2078 	res[0] = os_strdup("type=social");
2079 	if (res[0] == NULL) {
2080 		os_free(res);
2081 		return NULL;
2082 	}
2083 	res[1] = os_strdup("type=progressive");
2084 	if (res[1] == NULL)
2085 		return res;
2086 	res[2] = os_strdup("delay=");
2087 	if (res[2] == NULL)
2088 		return res;
2089 	res[3] = os_strdup("dev_id=");
2090 	if (res[3] == NULL)
2091 		return res;
2092 	if (arg == 1)
2093 		res[4] = os_strdup("[timeout]");
2094 
2095 	return res;
2096 }
2097 
2098 
wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl * ctrl,int argc,char * argv[])2099 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2100 				     char *argv[])
2101 {
2102 	return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2103 }
2104 
2105 
wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl * ctrl,int argc,char * argv[])2106 static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
2107 					 char *argv[])
2108 {
2109 	return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
2110 }
2111 
2112 
wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl * ctrl,int argc,char * argv[])2113 static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
2114 					      char *argv[])
2115 {
2116 	return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
2117 }
2118 
2119 
wpa_cli_cmd_p2p_connect(struct wpa_ctrl * ctrl,int argc,char * argv[])2120 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2121 				   char *argv[])
2122 {
2123 	return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
2124 }
2125 
2126 
wpa_cli_complete_p2p_connect(const char * str,int pos)2127 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2128 {
2129 	int arg = get_cmd_arg_num(str, pos);
2130 	char **res = NULL;
2131 
2132 	switch (arg) {
2133 	case 1:
2134 		res = cli_txt_list_array(&p2p_peers);
2135 		break;
2136 	}
2137 
2138 	return res;
2139 }
2140 
2141 
wpa_cli_cmd_p2p_listen(struct wpa_ctrl * ctrl,int argc,char * argv[])2142 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2143 				  char *argv[])
2144 {
2145 	return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
2146 }
2147 
2148 
wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])2149 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2150 					char *argv[])
2151 {
2152 	return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
2153 }
2154 
2155 
wpa_cli_complete_p2p_group_remove(const char * str,int pos)2156 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2157 {
2158 	int arg = get_cmd_arg_num(str, pos);
2159 	char **res = NULL;
2160 
2161 	switch (arg) {
2162 	case 1:
2163 		res = cli_txt_list_array(&p2p_groups);
2164 		break;
2165 	}
2166 
2167 	return res;
2168 }
2169 
2170 
wpa_cli_cmd_p2p_group_add(struct wpa_ctrl * ctrl,int argc,char * argv[])2171 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2172 					char *argv[])
2173 {
2174 	return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
2175 }
2176 
2177 
wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl * ctrl,int argc,char * argv[])2178 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2179 				     char *argv[])
2180 {
2181 	if (argc != 2 && argc != 3) {
2182 		printf("Invalid P2P_PROV_DISC command: needs at least "
2183 		       "two arguments, address and config method\n"
2184 		       "(display, keypad, or pbc) and an optional join\n");
2185 		return -1;
2186 	}
2187 
2188 	return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
2189 }
2190 
2191 
wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl * ctrl,int argc,char * argv[])2192 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2193 					  char *argv[])
2194 {
2195 	return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2196 }
2197 
2198 
wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl * ctrl,int argc,char * argv[])2199 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2200 					 char *argv[])
2201 {
2202 	char cmd[4096];
2203 
2204 	if (argc < 2) {
2205 		printf("Invalid P2P_SERV_DISC_REQ command: needs two "
2206 		       "or more arguments (address and TLVs)\n");
2207 		return -1;
2208 	}
2209 
2210 	if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
2211 		return -1;
2212 	return wpa_ctrl_command(ctrl, cmd);
2213 }
2214 
2215 
wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl * ctrl,int argc,char * argv[])2216 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2217 						int argc, char *argv[])
2218 {
2219 	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
2220 }
2221 
2222 
wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl * ctrl,int argc,char * argv[])2223 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2224 					  char *argv[])
2225 {
2226 	char cmd[4096];
2227 	int res;
2228 
2229 	if (argc != 4) {
2230 		printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2231 		       "arguments (freq, address, dialog token, and TLVs)\n");
2232 		return -1;
2233 	}
2234 
2235 	res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2236 			  argv[0], argv[1], argv[2], argv[3]);
2237 	if (os_snprintf_error(sizeof(cmd), res))
2238 		return -1;
2239 	cmd[sizeof(cmd) - 1] = '\0';
2240 	return wpa_ctrl_command(ctrl, cmd);
2241 }
2242 
2243 
wpa_cli_cmd_p2p_service_update(struct wpa_ctrl * ctrl,int argc,char * argv[])2244 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2245 					  char *argv[])
2246 {
2247 	return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2248 }
2249 
2250 
wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl * ctrl,int argc,char * argv[])2251 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2252 					      int argc, char *argv[])
2253 {
2254 	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
2255 }
2256 
2257 
wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])2258 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2259 					 char *argv[])
2260 {
2261 	return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2262 }
2263 
2264 
wpa_cli_cmd_p2p_service_add(struct wpa_ctrl * ctrl,int argc,char * argv[])2265 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2266 				       char *argv[])
2267 {
2268 	if (argc < 3) {
2269 		printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
2270 		return -1;
2271 	}
2272 
2273 	return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2274 }
2275 
2276 
wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl * ctrl,int argc,char * argv[])2277 static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2278 				       char *argv[])
2279 {
2280 	if (argc < 5 || argc > 6) {
2281 		printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
2282 		       "arguments\n");
2283 		return -1;
2284 	}
2285 
2286 	return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
2287 }
2288 
2289 
wpa_cli_cmd_p2p_service_del(struct wpa_ctrl * ctrl,int argc,char * argv[])2290 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2291 				       char *argv[])
2292 {
2293 	char cmd[4096];
2294 	int res;
2295 
2296 	if (argc != 2 && argc != 3) {
2297 		printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2298 		       "arguments\n");
2299 		return -1;
2300 	}
2301 
2302 	if (argc == 3)
2303 		res = os_snprintf(cmd, sizeof(cmd),
2304 				  "P2P_SERVICE_DEL %s %s %s",
2305 				  argv[0], argv[1], argv[2]);
2306 	else
2307 		res = os_snprintf(cmd, sizeof(cmd),
2308 				  "P2P_SERVICE_DEL %s %s",
2309 				  argv[0], argv[1]);
2310 	if (os_snprintf_error(sizeof(cmd), res))
2311 		return -1;
2312 	cmd[sizeof(cmd) - 1] = '\0';
2313 	return wpa_ctrl_command(ctrl, cmd);
2314 }
2315 
2316 
wpa_cli_cmd_p2p_reject(struct wpa_ctrl * ctrl,int argc,char * argv[])2317 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2318 				  int argc, char *argv[])
2319 {
2320 	return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
2321 }
2322 
2323 
wpa_cli_cmd_p2p_invite(struct wpa_ctrl * ctrl,int argc,char * argv[])2324 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2325 				  int argc, char *argv[])
2326 {
2327 	return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
2328 }
2329 
2330 
wpa_cli_cmd_p2p_peer(struct wpa_ctrl * ctrl,int argc,char * argv[])2331 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2332 {
2333 	return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
2334 }
2335 
2336 
wpa_cli_complete_p2p_peer(const char * str,int pos)2337 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2338 {
2339 	int arg = get_cmd_arg_num(str, pos);
2340 	char **res = NULL;
2341 
2342 	switch (arg) {
2343 	case 1:
2344 		res = cli_txt_list_array(&p2p_peers);
2345 		break;
2346 	}
2347 
2348 	return res;
2349 }
2350 
2351 
wpa_ctrl_command_p2p_peer(struct wpa_ctrl * ctrl,char * cmd,char * addr,size_t addr_len,int discovered)2352 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2353 				     char *addr, size_t addr_len,
2354 				     int discovered)
2355 {
2356 	char buf[4096], *pos;
2357 	size_t len;
2358 	int ret;
2359 
2360 	if (ctrl_conn == NULL)
2361 		return -1;
2362 	len = sizeof(buf) - 1;
2363 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2364 			       wpa_cli_msg_cb);
2365 	if (ret == -2) {
2366 		printf("'%s' command timed out.\n", cmd);
2367 		return -2;
2368 	} else if (ret < 0) {
2369 		printf("'%s' command failed.\n", cmd);
2370 		return -1;
2371 	}
2372 
2373 	buf[len] = '\0';
2374 	if (os_memcmp(buf, "FAIL", 4) == 0)
2375 		return -1;
2376 
2377 	pos = buf;
2378 	while (*pos != '\0' && *pos != '\n')
2379 		pos++;
2380 	*pos++ = '\0';
2381 	os_strlcpy(addr, buf, addr_len);
2382 	if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2383 		printf("%s\n", addr);
2384 	return 0;
2385 }
2386 
2387 
wpa_cli_cmd_p2p_peers(struct wpa_ctrl * ctrl,int argc,char * argv[])2388 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2389 {
2390 	char addr[32], cmd[64];
2391 	int discovered;
2392 
2393 	discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2394 
2395 	if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2396 				      addr, sizeof(addr), discovered))
2397 		return -1;
2398 	do {
2399 		os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2400 	} while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2401 			 discovered) == 0);
2402 
2403 	return 0;
2404 }
2405 
2406 
wpa_cli_cmd_p2p_set(struct wpa_ctrl * ctrl,int argc,char * argv[])2407 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2408 {
2409 	return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2410 }
2411 
2412 
wpa_cli_complete_p2p_set(const char * str,int pos)2413 static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2414 {
2415 	int arg = get_cmd_arg_num(str, pos);
2416 	const char *fields[] = {
2417 		"discoverability",
2418 		"managed",
2419 		"listen_channel",
2420 		"ssid_postfix",
2421 		"noa",
2422 		"ps",
2423 		"oppps",
2424 		"ctwindow",
2425 		"disabled",
2426 		"conc_pref",
2427 		"force_long_sd",
2428 		"peer_filter",
2429 		"cross_connect",
2430 		"go_apsd",
2431 		"client_apsd",
2432 		"disallow_freq",
2433 		"disc_int",
2434 		"per_sta_psk",
2435 	};
2436 	int i, num_fields = ARRAY_SIZE(fields);
2437 
2438 	if (arg == 1) {
2439 		char **res = os_calloc(num_fields + 1, sizeof(char *));
2440 		if (res == NULL)
2441 			return NULL;
2442 		for (i = 0; i < num_fields; i++) {
2443 			res[i] = os_strdup(fields[i]);
2444 			if (res[i] == NULL)
2445 				return res;
2446 		}
2447 		return res;
2448 	}
2449 
2450 	if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2451 		return cli_txt_list_array(&p2p_peers);
2452 
2453 	return NULL;
2454 }
2455 
2456 
wpa_cli_cmd_p2p_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])2457 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2458 {
2459 	return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2460 }
2461 
2462 
wpa_cli_cmd_p2p_cancel(struct wpa_ctrl * ctrl,int argc,char * argv[])2463 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2464 				  char *argv[])
2465 {
2466 	return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2467 }
2468 
2469 
wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl * ctrl,int argc,char * argv[])2470 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2471 				       char *argv[])
2472 {
2473 	return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2474 }
2475 
2476 
wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl * ctrl,int argc,char * argv[])2477 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2478 					char *argv[])
2479 {
2480 	if (argc != 0 && argc != 2 && argc != 4) {
2481 		printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2482 		       "(preferred duration, interval; in microsecods).\n"
2483 		       "Optional second pair can be used to provide "
2484 		       "acceptable values.\n");
2485 		return -1;
2486 	}
2487 
2488 	return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2489 }
2490 
2491 
wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl * ctrl,int argc,char * argv[])2492 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2493 				      char *argv[])
2494 {
2495 	if (argc != 0 && argc != 2) {
2496 		printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2497 		       "(availability period, availability interval; in "
2498 		       "millisecods).\n"
2499 		       "Extended Listen Timing can be cancelled with this "
2500 		       "command when used without parameters.\n");
2501 		return -1;
2502 	}
2503 
2504 	return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2505 }
2506 
2507 
wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl * ctrl,int argc,char * argv[])2508 static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2509 					 char *argv[])
2510 {
2511 	return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2512 }
2513 
2514 
wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl * ctrl,int argc,char * argv[])2515 static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
2516 				       char *argv[])
2517 {
2518 	return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
2519 }
2520 
2521 
wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2522 static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
2523 				       char *argv[])
2524 {
2525 	return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
2526 }
2527 
2528 
wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])2529 static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
2530 					  char *argv[])
2531 {
2532 	return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
2533 }
2534 
2535 #endif /* CONFIG_P2P */
2536 
2537 #ifdef CONFIG_WIFI_DISPLAY
2538 
wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl * ctrl,int argc,char * argv[])2539 static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2540 				       char *argv[])
2541 {
2542 	char cmd[100];
2543 	int res;
2544 
2545 	if (argc != 1 && argc != 2) {
2546 		printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2547 		       "arguments (subelem, hexdump)\n");
2548 		return -1;
2549 	}
2550 
2551 	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2552 			  argv[0], argc > 1 ? argv[1] : "");
2553 	if (os_snprintf_error(sizeof(cmd), res))
2554 		return -1;
2555 	cmd[sizeof(cmd) - 1] = '\0';
2556 	return wpa_ctrl_command(ctrl, cmd);
2557 }
2558 
2559 
wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2560 static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2561 				       char *argv[])
2562 {
2563 	char cmd[100];
2564 	int res;
2565 
2566 	if (argc != 1) {
2567 		printf("Invalid WFD_SUBELEM_GET command: needs one "
2568 		       "argument (subelem)\n");
2569 		return -1;
2570 	}
2571 
2572 	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2573 			  argv[0]);
2574 	if (os_snprintf_error(sizeof(cmd), res))
2575 		return -1;
2576 	cmd[sizeof(cmd) - 1] = '\0';
2577 	return wpa_ctrl_command(ctrl, cmd);
2578 }
2579 #endif /* CONFIG_WIFI_DISPLAY */
2580 
2581 
2582 #ifdef CONFIG_INTERWORKING
wpa_cli_cmd_fetch_anqp(struct wpa_ctrl * ctrl,int argc,char * argv[])2583 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2584 				  char *argv[])
2585 {
2586 	return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2587 }
2588 
2589 
wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl * ctrl,int argc,char * argv[])2590 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2591 				       char *argv[])
2592 {
2593 	return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2594 }
2595 
2596 
wpa_cli_cmd_interworking_select(struct wpa_ctrl * ctrl,int argc,char * argv[])2597 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2598 					   char *argv[])
2599 {
2600 	return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2601 }
2602 
2603 
wpa_cli_cmd_interworking_connect(struct wpa_ctrl * ctrl,int argc,char * argv[])2604 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2605 					    char *argv[])
2606 {
2607 	return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2608 }
2609 
2610 
wpa_cli_cmd_interworking_add_network(struct wpa_ctrl * ctrl,int argc,char * argv[])2611 static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2612 						char *argv[])
2613 {
2614 	return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2615 }
2616 
2617 
wpa_cli_cmd_anqp_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2618 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2619 {
2620 	return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2621 }
2622 
2623 
wpa_cli_cmd_gas_request(struct wpa_ctrl * ctrl,int argc,char * argv[])2624 static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2625 				   char *argv[])
2626 {
2627 	return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2628 }
2629 
2630 
wpa_cli_cmd_gas_response_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2631 static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2632 					char *argv[])
2633 {
2634 	return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2635 }
2636 #endif /* CONFIG_INTERWORKING */
2637 
2638 
2639 #ifdef CONFIG_HS20
2640 
wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl * ctrl,int argc,char * argv[])2641 static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2642 				     char *argv[])
2643 {
2644 	return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2645 }
2646 
2647 
wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl * ctrl,int argc,char * argv[])2648 static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2649 					       char *argv[])
2650 {
2651 	char cmd[512];
2652 
2653 	if (argc == 0) {
2654 		printf("Command needs one or two arguments (dst mac addr and "
2655 		       "optional home realm)\n");
2656 		return -1;
2657 	}
2658 
2659 	if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2660 		      argc, argv) < 0)
2661 		return -1;
2662 
2663 	return wpa_ctrl_command(ctrl, cmd);
2664 }
2665 
2666 
wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl * ctrl,int argc,char * argv[])2667 static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2668 					 char *argv[])
2669 {
2670 	char cmd[512];
2671 
2672 	if (argc < 2) {
2673 		printf("Command needs two arguments (dst mac addr and "
2674 		       "icon name)\n");
2675 		return -1;
2676 	}
2677 
2678 	if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2679 		return -1;
2680 
2681 	return wpa_ctrl_command(ctrl, cmd);
2682 }
2683 
2684 
wpa_cli_cmd_fetch_osu(struct wpa_ctrl * ctrl,int argc,char * argv[])2685 static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2686 {
2687 	return wpa_ctrl_command(ctrl, "FETCH_OSU");
2688 }
2689 
2690 
wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl * ctrl,int argc,char * argv[])2691 static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2692 					char *argv[])
2693 {
2694 	return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2695 }
2696 
2697 #endif /* CONFIG_HS20 */
2698 
2699 
wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])2700 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2701 				       char *argv[])
2702 {
2703 	return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2704 }
2705 
2706 
wpa_cli_cmd_tdls_discover(struct wpa_ctrl * ctrl,int argc,char * argv[])2707 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2708 				     char *argv[])
2709 {
2710 	return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2711 }
2712 
2713 
wpa_cli_cmd_tdls_setup(struct wpa_ctrl * ctrl,int argc,char * argv[])2714 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2715 				  char *argv[])
2716 {
2717 	return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2718 }
2719 
2720 
wpa_cli_cmd_tdls_teardown(struct wpa_ctrl * ctrl,int argc,char * argv[])2721 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2722 				     char *argv[])
2723 {
2724 	return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2725 }
2726 
2727 
wpa_cli_cmd_tdls_link_status(struct wpa_ctrl * ctrl,int argc,char * argv[])2728 static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
2729 					char *argv[])
2730 {
2731 	return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
2732 }
2733 
2734 
wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl * ctrl,int argc,char * argv[])2735 static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2736 				    char *argv[])
2737 {
2738 	return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2739 }
2740 
2741 
wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl * ctrl,int argc,char * argv[])2742 static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2743 				    char *argv[])
2744 {
2745 	return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2746 }
2747 
2748 
wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl * ctrl,int argc,char * argv[])2749 static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2750 				    char *argv[])
2751 {
2752 	return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2753 }
2754 
2755 
wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl * ctrl,int argc,char * argv[])2756 static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2757 					char *argv[])
2758 {
2759 	return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2760 }
2761 
2762 
wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl * ctrl,int argc,char * argv[])2763 static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2764 					       char *argv[])
2765 {
2766 	return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2767 }
2768 
2769 
wpa_cli_cmd_signal_poll(struct wpa_ctrl * ctrl,int argc,char * argv[])2770 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2771 				   char *argv[])
2772 {
2773 	return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2774 }
2775 
2776 
wpa_cli_cmd_signal_monitor(struct wpa_ctrl * ctrl,int argc,char * argv[])2777 static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc,
2778 				   char *argv[])
2779 {
2780 	return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv);
2781 }
2782 
2783 
wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl * ctrl,int argc,char * argv[])2784 static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2785 				   char *argv[])
2786 {
2787 	return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2788 }
2789 
2790 
wpa_cli_cmd_reauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])2791 static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2792 				      char *argv[])
2793 {
2794 	return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2795 }
2796 
2797 
2798 #ifdef CONFIG_AUTOSCAN
2799 
wpa_cli_cmd_autoscan(struct wpa_ctrl * ctrl,int argc,char * argv[])2800 static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2801 {
2802 	if (argc == 0)
2803 		return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2804 
2805 	return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2806 }
2807 
2808 #endif /* CONFIG_AUTOSCAN */
2809 
2810 
2811 #ifdef CONFIG_WNM
2812 
wpa_cli_cmd_wnm_sleep(struct wpa_ctrl * ctrl,int argc,char * argv[])2813 static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2814 {
2815 	return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2816 }
2817 
2818 
wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl * ctrl,int argc,char * argv[])2819 static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2820 {
2821 	return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2822 }
2823 
2824 #endif /* CONFIG_WNM */
2825 
2826 
wpa_cli_cmd_raw(struct wpa_ctrl * ctrl,int argc,char * argv[])2827 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2828 {
2829 	if (argc == 0)
2830 		return -1;
2831 	return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2832 }
2833 
2834 
2835 #ifdef ANDROID
wpa_cli_cmd_driver(struct wpa_ctrl * ctrl,int argc,char * argv[])2836 static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2837 {
2838 	return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2839 }
2840 #endif /* ANDROID */
2841 
2842 
wpa_cli_cmd_vendor(struct wpa_ctrl * ctrl,int argc,char * argv[])2843 static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2844 {
2845 	return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2846 }
2847 
2848 
wpa_cli_cmd_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])2849 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2850 {
2851 	return wpa_ctrl_command(ctrl, "FLUSH");
2852 }
2853 
2854 
wpa_cli_cmd_radio_work(struct wpa_ctrl * ctrl,int argc,char * argv[])2855 static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2856 {
2857 	return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2858 }
2859 
2860 
wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl * ctrl,int argc,char * argv[])2861 static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2862 					    char *argv[])
2863 {
2864 	return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2865 }
2866 
2867 
wpa_cli_cmd_erp_flush(struct wpa_ctrl * ctrl,int argc,char * argv[])2868 static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2869 {
2870 	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2871 }
2872 
2873 
wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])2874 static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2875 				     char *argv[])
2876 {
2877 	return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2878 }
2879 
2880 
wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl * ctrl,int argc,char * argv[])2881 static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
2882 					  char *argv[])
2883 {
2884 	return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
2885 }
2886 
2887 
2888 enum wpa_cli_cmd_flags {
2889 	cli_cmd_flag_none		= 0x00,
2890 	cli_cmd_flag_sensitive		= 0x01
2891 };
2892 
2893 struct wpa_cli_cmd {
2894 	const char *cmd;
2895 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2896 	char ** (*completion)(const char *str, int pos);
2897 	enum wpa_cli_cmd_flags flags;
2898 	const char *usage;
2899 };
2900 
2901 static const struct wpa_cli_cmd wpa_cli_commands[] = {
2902 	{ "status", wpa_cli_cmd_status, NULL,
2903 	  cli_cmd_flag_none,
2904 	  "[verbose] = get current WPA/EAPOL/EAP status" },
2905 	{ "ifname", wpa_cli_cmd_ifname, NULL,
2906 	  cli_cmd_flag_none,
2907 	  "= get current interface name" },
2908 	{ "ping", wpa_cli_cmd_ping, NULL,
2909 	  cli_cmd_flag_none,
2910 	  "= pings wpa_supplicant" },
2911 	{ "relog", wpa_cli_cmd_relog, NULL,
2912 	  cli_cmd_flag_none,
2913 	  "= re-open log-file (allow rolling logs)" },
2914 	{ "note", wpa_cli_cmd_note, NULL,
2915 	  cli_cmd_flag_none,
2916 	  "<text> = add a note to wpa_supplicant debug log" },
2917 	{ "mib", wpa_cli_cmd_mib, NULL,
2918 	  cli_cmd_flag_none,
2919 	  "= get MIB variables (dot1x, dot11)" },
2920 	{ "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2921 	  cli_cmd_flag_none,
2922 	  "[command] = show usage help" },
2923 	{ "interface", wpa_cli_cmd_interface, NULL,
2924 	  cli_cmd_flag_none,
2925 	  "[ifname] = show interfaces/select interface" },
2926 	{ "level", wpa_cli_cmd_level, NULL,
2927 	  cli_cmd_flag_none,
2928 	  "<debug level> = change debug level" },
2929 	{ "license", wpa_cli_cmd_license, NULL,
2930 	  cli_cmd_flag_none,
2931 	  "= show full wpa_cli license" },
2932 	{ "quit", wpa_cli_cmd_quit, NULL,
2933 	  cli_cmd_flag_none,
2934 	  "= exit wpa_cli" },
2935 	{ "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2936 	  cli_cmd_flag_none,
2937 	  "= set variables (shows list of variables when run without "
2938 	  "arguments)" },
2939 	{ "dump", wpa_cli_cmd_dump, NULL,
2940 	  cli_cmd_flag_none,
2941 	  "= dump config variables" },
2942 	{ "get", wpa_cli_cmd_get, wpa_cli_complete_get,
2943 	  cli_cmd_flag_none,
2944 	  "<name> = get information" },
2945 	{ "logon", wpa_cli_cmd_logon, NULL,
2946 	  cli_cmd_flag_none,
2947 	  "= IEEE 802.1X EAPOL state machine logon" },
2948 	{ "logoff", wpa_cli_cmd_logoff, NULL,
2949 	  cli_cmd_flag_none,
2950 	  "= IEEE 802.1X EAPOL state machine logoff" },
2951 	{ "pmksa", wpa_cli_cmd_pmksa, NULL,
2952 	  cli_cmd_flag_none,
2953 	  "= show PMKSA cache" },
2954 	{ "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2955 	  cli_cmd_flag_none,
2956 	  "= flush PMKSA cache entries" },
2957 	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
2958 	  cli_cmd_flag_none,
2959 	  "= force reassociation" },
2960 	{ "reattach", wpa_cli_cmd_reattach, NULL,
2961 	  cli_cmd_flag_none,
2962 	  "= force reassociation back to the same BSS" },
2963 	{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2964 	  cli_cmd_flag_none,
2965 	  "<BSSID> = force preauthentication" },
2966 	{ "identity", wpa_cli_cmd_identity, NULL,
2967 	  cli_cmd_flag_none,
2968 	  "<network id> <identity> = configure identity for an SSID" },
2969 	{ "password", wpa_cli_cmd_password, NULL,
2970 	  cli_cmd_flag_sensitive,
2971 	  "<network id> <password> = configure password for an SSID" },
2972 	{ "new_password", wpa_cli_cmd_new_password, NULL,
2973 	  cli_cmd_flag_sensitive,
2974 	  "<network id> <password> = change password for an SSID" },
2975 	{ "pin", wpa_cli_cmd_pin, NULL,
2976 	  cli_cmd_flag_sensitive,
2977 	  "<network id> <pin> = configure pin for an SSID" },
2978 	{ "otp", wpa_cli_cmd_otp, NULL,
2979 	  cli_cmd_flag_sensitive,
2980 	  "<network id> <password> = configure one-time-password for an SSID"
2981 	},
2982 	{ "passphrase", wpa_cli_cmd_passphrase, NULL,
2983 	  cli_cmd_flag_sensitive,
2984 	  "<network id> <passphrase> = configure private key passphrase\n"
2985 	  "  for an SSID" },
2986 	{ "sim", wpa_cli_cmd_sim, NULL,
2987 	  cli_cmd_flag_sensitive,
2988 	  "<network id> <pin> = report SIM operation result" },
2989 	{ "bssid", wpa_cli_cmd_bssid, NULL,
2990 	  cli_cmd_flag_none,
2991 	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
2992 	{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2993 	  cli_cmd_flag_none,
2994 	  "<BSSID> = add a BSSID to the blacklist\n"
2995 	  "blacklist clear = clear the blacklist\n"
2996 	  "blacklist = display the blacklist" },
2997 	{ "log_level", wpa_cli_cmd_log_level, NULL,
2998 	  cli_cmd_flag_none,
2999 	  "<level> [<timestamp>] = update the log level/timestamp\n"
3000 	  "log_level = display the current log level and log options" },
3001 	{ "list_networks", wpa_cli_cmd_list_networks, NULL,
3002 	  cli_cmd_flag_none,
3003 	  "= list configured networks" },
3004 	{ "select_network", wpa_cli_cmd_select_network,
3005 	  wpa_cli_complete_network_id,
3006 	  cli_cmd_flag_none,
3007 	  "<network id> = select a network (disable others)" },
3008 	{ "enable_network", wpa_cli_cmd_enable_network,
3009 	  wpa_cli_complete_network_id,
3010 	  cli_cmd_flag_none,
3011 	  "<network id> = enable a network" },
3012 	{ "disable_network", wpa_cli_cmd_disable_network,
3013 	  wpa_cli_complete_network_id,
3014 	  cli_cmd_flag_none,
3015 	  "<network id> = disable a network" },
3016 	{ "add_network", wpa_cli_cmd_add_network, NULL,
3017 	  cli_cmd_flag_none,
3018 	  "= add a network" },
3019 	{ "remove_network", wpa_cli_cmd_remove_network,
3020 	  wpa_cli_complete_network_id,
3021 	  cli_cmd_flag_none,
3022 	  "<network id> = remove a network" },
3023 	{ "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
3024 	  cli_cmd_flag_sensitive,
3025 	  "<network id> <variable> <value> = set network variables (shows\n"
3026 	  "  list of variables when run without arguments)" },
3027 	{ "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
3028 	  cli_cmd_flag_none,
3029 	  "<network id> <variable> = get network variables" },
3030 	{ "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
3031 	  cli_cmd_flag_none,
3032 	  "<src network id> <dst network id> <variable> = duplicate network variables"
3033 	},
3034 	{ "list_creds", wpa_cli_cmd_list_creds, NULL,
3035 	  cli_cmd_flag_none,
3036 	  "= list configured credentials" },
3037 	{ "add_cred", wpa_cli_cmd_add_cred, NULL,
3038 	  cli_cmd_flag_none,
3039 	  "= add a credential" },
3040 	{ "remove_cred", wpa_cli_cmd_remove_cred, NULL,
3041 	  cli_cmd_flag_none,
3042 	  "<cred id> = remove a credential" },
3043 	{ "set_cred", wpa_cli_cmd_set_cred, NULL,
3044 	  cli_cmd_flag_sensitive,
3045 	  "<cred id> <variable> <value> = set credential variables" },
3046 	{ "get_cred", wpa_cli_cmd_get_cred, NULL,
3047 	  cli_cmd_flag_none,
3048 	  "<cred id> <variable> = get credential variables" },
3049 	{ "save_config", wpa_cli_cmd_save_config, NULL,
3050 	  cli_cmd_flag_none,
3051 	  "= save the current configuration" },
3052 	{ "disconnect", wpa_cli_cmd_disconnect, NULL,
3053 	  cli_cmd_flag_none,
3054 	  "= disconnect and wait for reassociate/reconnect command before\n"
3055 	  "  connecting" },
3056 	{ "reconnect", wpa_cli_cmd_reconnect, NULL,
3057 	  cli_cmd_flag_none,
3058 	  "= like reassociate, but only takes effect if already disconnected"
3059 	},
3060 	{ "scan", wpa_cli_cmd_scan, NULL,
3061 	  cli_cmd_flag_none,
3062 	  "= request new BSS scan" },
3063 	{ "scan_results", wpa_cli_cmd_scan_results, NULL,
3064 	  cli_cmd_flag_none,
3065 	  "= get latest scan results" },
3066 	{ "abort_scan", wpa_cli_cmd_abort_scan, NULL,
3067 	  cli_cmd_flag_none,
3068 	  "= request ongoing scan to be aborted" },
3069 	{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
3070 	  cli_cmd_flag_none,
3071 	  "<<idx> | <bssid>> = get detailed scan result info" },
3072 	{ "get_capability", wpa_cli_cmd_get_capability, NULL,
3073 	  cli_cmd_flag_none,
3074 	  "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
3075 	  "= get capabilities" },
3076 	{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
3077 	  cli_cmd_flag_none,
3078 	  "= force wpa_supplicant to re-read its configuration file" },
3079 	{ "terminate", wpa_cli_cmd_terminate, NULL,
3080 	  cli_cmd_flag_none,
3081 	  "= terminate wpa_supplicant" },
3082 	{ "interface_add", wpa_cli_cmd_interface_add, NULL,
3083 	  cli_cmd_flag_none,
3084 	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
3085 	  "  <bridge_name> <create> <type> = adds new interface, all "
3086 	  "parameters but\n"
3087 	  "  <ifname> are optional. Supported types are station ('sta') and "
3088 	  "AP ('ap')" },
3089 	{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
3090 	  cli_cmd_flag_none,
3091 	  "<ifname> = removes the interface" },
3092 	{ "interface_list", wpa_cli_cmd_interface_list, NULL,
3093 	  cli_cmd_flag_none,
3094 	  "= list available interfaces" },
3095 	{ "ap_scan", wpa_cli_cmd_ap_scan, NULL,
3096 	  cli_cmd_flag_none,
3097 	  "<value> = set ap_scan parameter" },
3098 	{ "scan_interval", wpa_cli_cmd_scan_interval, NULL,
3099 	  cli_cmd_flag_none,
3100 	  "<value> = set scan_interval parameter (in seconds)" },
3101 	{ "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
3102 	  cli_cmd_flag_none,
3103 	  "<value> = set BSS expiration age parameter" },
3104 	{ "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
3105 	  cli_cmd_flag_none,
3106 	  "<value> = set BSS expiration scan count parameter" },
3107 	{ "bss_flush", wpa_cli_cmd_bss_flush, NULL,
3108 	  cli_cmd_flag_none,
3109 	  "<value> = set BSS flush age (0 by default)" },
3110 	{ "stkstart", wpa_cli_cmd_stkstart, NULL,
3111 	  cli_cmd_flag_none,
3112 	  "<addr> = request STK negotiation with <addr>" },
3113 	{ "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
3114 	  cli_cmd_flag_none,
3115 	  "<addr> = request over-the-DS FT with <addr>" },
3116 	{ "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
3117 	  cli_cmd_flag_none,
3118 	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
3119 	{ "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
3120 	  cli_cmd_flag_sensitive,
3121 	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3122 	  "hardcoded)" },
3123 	{ "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
3124 	  cli_cmd_flag_sensitive,
3125 	  "<PIN> = verify PIN checksum" },
3126 	{ "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
3127 	  "Cancels the pending WPS operation" },
3128 #ifdef CONFIG_WPS_NFC
3129 	{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
3130 	  cli_cmd_flag_none,
3131 	  "[BSSID] = start Wi-Fi Protected Setup: NFC" },
3132 	{ "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3133 	  cli_cmd_flag_none,
3134 	  "<WPS|NDEF> = build configuration token" },
3135 	{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
3136 	  cli_cmd_flag_none,
3137 	  "<WPS|NDEF> = create password token" },
3138 	{ "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
3139 	  cli_cmd_flag_sensitive,
3140 	  "<hexdump of payload> = report read NFC tag with WPS data" },
3141 	{ "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3142 	  cli_cmd_flag_none,
3143 	  "<NDEF> <WPS> = create NFC handover request" },
3144 	{ "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3145 	  cli_cmd_flag_none,
3146 	  "<NDEF> <WPS> = create NFC handover select" },
3147 	{ "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3148 	  cli_cmd_flag_none,
3149 	  "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3150 	  "NFC handover" },
3151 #endif /* CONFIG_WPS_NFC */
3152 	{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
3153 	  cli_cmd_flag_sensitive,
3154 	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
3155 	{ "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
3156 	  cli_cmd_flag_sensitive,
3157 	  "[params..] = enable/disable AP PIN" },
3158 	{ "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
3159 	  cli_cmd_flag_none,
3160 	  "[IP address] = start Wi-Fi Protected Setup External Registrar" },
3161 	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
3162 	  cli_cmd_flag_none,
3163 	  "= stop Wi-Fi Protected Setup External Registrar" },
3164 	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
3165 	  cli_cmd_flag_sensitive,
3166 	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
3167 	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
3168 	  cli_cmd_flag_none,
3169 	  "<UUID> = accept an Enrollee PBC using External Registrar" },
3170 	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
3171 	  cli_cmd_flag_sensitive,
3172 	  "<UUID> <PIN> = learn AP configuration" },
3173 	{ "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
3174 	  cli_cmd_flag_none,
3175 	  "<UUID> <network id> = set AP configuration for enrolling" },
3176 	{ "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
3177 	  cli_cmd_flag_sensitive,
3178 	  "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
3179 #ifdef CONFIG_WPS_NFC
3180 	{ "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
3181 	  cli_cmd_flag_none,
3182 	  "<WPS/NDEF> <UUID> = build NFC configuration token" },
3183 #endif /* CONFIG_WPS_NFC */
3184 	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
3185 	  cli_cmd_flag_none,
3186 	  "<addr> = request RSN authentication with <addr> in IBSS" },
3187 #ifdef CONFIG_AP
3188 	{ "sta", wpa_cli_cmd_sta, NULL,
3189 	  cli_cmd_flag_none,
3190 	  "<addr> = get information about an associated station (AP)" },
3191 	{ "all_sta", wpa_cli_cmd_all_sta, NULL,
3192 	  cli_cmd_flag_none,
3193 	  "= get information about all associated stations (AP)" },
3194 	{ "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
3195 	  cli_cmd_flag_none,
3196 	  "<addr> = deauthenticate a station" },
3197 	{ "disassociate", wpa_cli_cmd_disassociate, NULL,
3198 	  cli_cmd_flag_none,
3199 	  "<addr> = disassociate a station" },
3200 	{ "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3201 	  cli_cmd_flag_none,
3202 	  "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3203 	  " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3204 	  " = CSA parameters" },
3205 #endif /* CONFIG_AP */
3206 	{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
3207 	  "= notification of suspend/hibernate" },
3208 	{ "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
3209 	  "= notification of resume/thaw" },
3210 #ifdef CONFIG_TESTING_OPTIONS
3211 	{ "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
3212 	  "= drop SA without deauth/disassoc (test command)" },
3213 #endif /* CONFIG_TESTING_OPTIONS */
3214 	{ "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
3215 	  cli_cmd_flag_none,
3216 	  "<addr> = roam to the specified BSS" },
3217 #ifdef CONFIG_MESH
3218 	{ "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
3219 	  cli_cmd_flag_none,
3220 	  "[ifname] = Create a new mesh interface" },
3221 	{ "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
3222 	  cli_cmd_flag_none,
3223 	  "<network id> = join a mesh network (disable others)" },
3224 	{ "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
3225 	  cli_cmd_flag_none,
3226 	  "<ifname> = Remove mesh group interface" },
3227 	{ "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
3228 	  cli_cmd_flag_none,
3229 	  "<addr> = Remove a mesh peer" },
3230 	{ "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
3231 	  cli_cmd_flag_none,
3232 	  "<addr> [duration=<seconds>] = Add a mesh peer" },
3233 #endif /* CONFIG_MESH */
3234 #ifdef CONFIG_P2P
3235 	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3236 	  cli_cmd_flag_none,
3237 	  "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3238 	{ "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
3239 	  "= stop P2P Devices search" },
3240 	{ "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3241 	  cli_cmd_flag_none,
3242 	  "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3243 	{ "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3244 	  cli_cmd_flag_none,
3245 	  "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
3246 	{ "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3247 	  cli_cmd_flag_none,
3248 	  "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3249 	{ "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
3250 	  "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3251 	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3252 	  wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
3253 	  "<ifname> = remove P2P group interface (terminate group if GO)" },
3254 	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3255 	  "[ht40] = add a new P2P group (local end as GO)" },
3256 	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3257 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3258 	  "<addr> <method> = request provisioning discovery" },
3259 	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
3260 	  cli_cmd_flag_none,
3261 	  "= get the passphrase for a group (GO only)" },
3262 	{ "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3263 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3264 	  "<addr> <TLVs> = schedule service discovery request" },
3265 	{ "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3266 	  NULL, cli_cmd_flag_none,
3267 	  "<id> = cancel pending service discovery request" },
3268 	{ "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
3269 	  cli_cmd_flag_none,
3270 	  "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3271 	{ "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
3272 	  cli_cmd_flag_none,
3273 	  "= indicate change in local services" },
3274 	{ "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
3275 	  cli_cmd_flag_none,
3276 	  "<external> = set external processing of service discovery" },
3277 	{ "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
3278 	  cli_cmd_flag_none,
3279 	  "= remove all stored service entries" },
3280 	{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
3281 	  cli_cmd_flag_none,
3282 	  "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
3283 	  "service" },
3284 	{ "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3285 	  cli_cmd_flag_none,
3286 	  "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3287 	  "local ASP service" },
3288 	{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
3289 	  cli_cmd_flag_none,
3290 	  "<bonjour|upnp> <query|version> [|service] = remove a local "
3291 	  "service" },
3292 	{ "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
3293 	  cli_cmd_flag_none,
3294 	  "<addr> = reject connection attempts from a specific peer" },
3295 	{ "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
3296 	  cli_cmd_flag_none,
3297 	  "<cmd> [peer=addr] = invite peer" },
3298 	{ "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
3299 	  "[discovered] = list known (optionally, only fully discovered) P2P "
3300 	  "peers" },
3301 	{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3302 	  cli_cmd_flag_none,
3303 	  "<address> = show information about known P2P peer" },
3304 	{ "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3305 	  cli_cmd_flag_none,
3306 	  "<field> <value> = set a P2P parameter" },
3307 	{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
3308 	  "= flush P2P state" },
3309 	{ "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
3310 	  "= cancel P2P group formation" },
3311 	{ "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3312 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3313 	  "<address> = unauthorize a peer" },
3314 	{ "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3315 	  cli_cmd_flag_none,
3316 	  "[<duration> <interval>] [<duration> <interval>] = request GO "
3317 	  "presence" },
3318 	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3319 	  cli_cmd_flag_none,
3320 	  "[<period> <interval>] = set extended listen timing" },
3321 	{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3322 	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3323 	  "<address|iface=address> = remove a peer from all groups" },
3324 	{ "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
3325 	  cli_cmd_flag_none,
3326 	  "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
3327 	  VENDOR_ELEM_FRAME_ID },
3328 	{ "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
3329 	  cli_cmd_flag_none,
3330 	  "<frame id> = get vendor specific IE(s) to frame(s)\n"
3331 	  VENDOR_ELEM_FRAME_ID },
3332 	{ "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
3333 	  cli_cmd_flag_none,
3334 	  "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
3335 	  VENDOR_ELEM_FRAME_ID },
3336 #endif /* CONFIG_P2P */
3337 #ifdef CONFIG_WIFI_DISPLAY
3338 	{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3339 	  cli_cmd_flag_none,
3340 	  "<subelem> [contents] = set Wi-Fi Display subelement" },
3341 	{ "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3342 	  cli_cmd_flag_none,
3343 	  "<subelem> = get Wi-Fi Display subelement" },
3344 #endif /* CONFIG_WIFI_DISPLAY */
3345 #ifdef CONFIG_INTERWORKING
3346 	{ "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
3347 	  "= fetch ANQP information for all APs" },
3348 	{ "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3349 	  cli_cmd_flag_none,
3350 	  "= stop fetch_anqp operation" },
3351 	{ "interworking_select", wpa_cli_cmd_interworking_select, NULL,
3352 	  cli_cmd_flag_none,
3353 	  "[auto] = perform Interworking network selection" },
3354 	{ "interworking_connect", wpa_cli_cmd_interworking_connect,
3355 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3356 	  "<BSSID> = connect using Interworking credentials" },
3357 	{ "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3358 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3359 	  "<BSSID> = connect using Interworking credentials" },
3360 	{ "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3361 	  cli_cmd_flag_none,
3362 	  "<addr> <info id>[,<info id>]... = request ANQP information" },
3363 	{ "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3364 	  cli_cmd_flag_none,
3365 	  "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3366 	{ "gas_response_get", wpa_cli_cmd_gas_response_get,
3367 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3368 	  "<addr> <dialog token> [start,len] = Fetch last GAS response" },
3369 #endif /* CONFIG_INTERWORKING */
3370 #ifdef CONFIG_HS20
3371 	{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3372 	  cli_cmd_flag_none,
3373 	  "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3374 	},
3375 	{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3376 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3377 	  "<addr> <home realm> = get HS20 nai home realm list" },
3378 	{ "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3379 	  wpa_cli_complete_bss, cli_cmd_flag_none,
3380 	  "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3381 	{ "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3382 	  "= fetch OSU provider information from all APs" },
3383 	{ "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3384 	  cli_cmd_flag_none,
3385 	  "= cancel fetch_osu command" },
3386 #endif /* CONFIG_HS20 */
3387 	{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3388 	  cli_cmd_flag_none,
3389 	  "<0/1> = disable/enable automatic reconnection" },
3390 	{ "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
3391 	  cli_cmd_flag_none,
3392 	  "<addr> = request TDLS discovery with <addr>" },
3393 	{ "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
3394 	  cli_cmd_flag_none,
3395 	  "<addr> = request TDLS setup with <addr>" },
3396 	{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
3397 	  cli_cmd_flag_none,
3398 	  "<addr> = tear down TDLS with <addr>" },
3399 	{ "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
3400 	  cli_cmd_flag_none,
3401 	  "<addr> = TDLS link status with <addr>" },
3402 	{ "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3403 	  cli_cmd_flag_none,
3404 	  "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3405 	  "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3406 	  "= add WMM-AC traffic stream" },
3407 	{ "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3408 	  cli_cmd_flag_none,
3409 	  "<tsid> = delete WMM-AC traffic stream" },
3410 	{ "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3411 	  cli_cmd_flag_none,
3412 	  "= show status for Wireless Multi-Media Admission-Control" },
3413 	{ "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3414 	  cli_cmd_flag_none,
3415 	  "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3416 	  "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3417 	  "with TDLS peer" },
3418 	{ "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3419 	  cli_cmd_flag_none,
3420 	  "<addr> = disable channel switching with TDLS peer <addr>" },
3421 	{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
3422 	  cli_cmd_flag_none,
3423 	  "= get signal parameters" },
3424 	{ "signal_monitor", wpa_cli_cmd_signal_monitor, NULL,
3425 	  cli_cmd_flag_none,
3426 	  "= set signal monitor parameters" },
3427 	{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3428 	  cli_cmd_flag_none,
3429 	  "= get TX/RX packet counters" },
3430 	{ "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3431 	  cli_cmd_flag_none,
3432 	  "= trigger IEEE 802.1X/EAPOL reauthentication" },
3433 #ifdef CONFIG_AUTOSCAN
3434 	{ "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
3435 	  "[params] = Set or unset (if none) autoscan parameters" },
3436 #endif /* CONFIG_AUTOSCAN */
3437 #ifdef CONFIG_WNM
3438 	{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3439 	  "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
3440 	{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3441 	  "<query reason> [list] = Send BSS Transition Management Query" },
3442 #endif /* CONFIG_WNM */
3443 	{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3444 	  "<params..> = Sent unprocessed command" },
3445 	{ "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3446 	  "= flush wpa_supplicant state" },
3447 #ifdef ANDROID
3448 	{ "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3449 	  "<command> = driver private commands" },
3450 #endif /* ANDROID */
3451 	{ "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3452 	  "= radio_work <show/add/done>" },
3453 	{ "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3454 	  "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3455 	},
3456 	{ "neighbor_rep_request",
3457 	  wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3458 	  "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3459 	  "(with optional given SSID, default: current SSID)"
3460 	},
3461 	{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3462 	  "= flush ERP keys" },
3463 	{ "mac_rand_scan",
3464 	  wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3465 	  "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3466 	  "mask=mac-address-mask] = scan MAC randomization"
3467 	},
3468 	{ "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
3469 	  cli_cmd_flag_none,
3470 	  "<interface type> = retrieve preferred freq list for the specified interface type" },
3471 	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
3472 };
3473 
3474 
3475 /*
3476  * Prints command usage, lines are padded with the specified string.
3477  */
print_cmd_help(const struct wpa_cli_cmd * cmd,const char * pad)3478 static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
3479 {
3480 	char c;
3481 	size_t n;
3482 
3483 	printf("%s%s ", pad, cmd->cmd);
3484 	for (n = 0; (c = cmd->usage[n]); n++) {
3485 		printf("%c", c);
3486 		if (c == '\n')
3487 			printf("%s", pad);
3488 	}
3489 	printf("\n");
3490 }
3491 
3492 
print_help(const char * cmd)3493 static void print_help(const char *cmd)
3494 {
3495 	int n;
3496 	printf("commands:\n");
3497 	for (n = 0; wpa_cli_commands[n].cmd; n++) {
3498 		if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3499 			print_cmd_help(&wpa_cli_commands[n], "  ");
3500 	}
3501 }
3502 
3503 
wpa_cli_edit_filter_history_cb(void * ctx,const char * cmd)3504 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3505 {
3506 	const char *c, *delim;
3507 	int n;
3508 	size_t len;
3509 
3510 	delim = os_strchr(cmd, ' ');
3511 	if (delim)
3512 		len = delim - cmd;
3513 	else
3514 		len = os_strlen(cmd);
3515 
3516 	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3517 		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3518 			return (wpa_cli_commands[n].flags &
3519 				cli_cmd_flag_sensitive);
3520 	}
3521 	return 0;
3522 }
3523 
3524 
wpa_list_cmd_list(void)3525 static char ** wpa_list_cmd_list(void)
3526 {
3527 	char **res;
3528 	int i, count;
3529 	struct cli_txt_entry *e;
3530 
3531 	count = ARRAY_SIZE(wpa_cli_commands);
3532 	count += dl_list_len(&p2p_groups);
3533 	count += dl_list_len(&ifnames);
3534 	res = os_calloc(count + 1, sizeof(char *));
3535 	if (res == NULL)
3536 		return NULL;
3537 
3538 	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3539 		res[i] = os_strdup(wpa_cli_commands[i].cmd);
3540 		if (res[i] == NULL)
3541 			break;
3542 	}
3543 
3544 	dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3545 		size_t len = 8 + os_strlen(e->txt);
3546 		res[i] = os_malloc(len);
3547 		if (res[i] == NULL)
3548 			break;
3549 		os_snprintf(res[i], len, "ifname=%s", e->txt);
3550 		i++;
3551 	}
3552 
3553 	dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3554 		res[i] = os_strdup(e->txt);
3555 		if (res[i] == NULL)
3556 			break;
3557 		i++;
3558 	}
3559 
3560 	return res;
3561 }
3562 
3563 
wpa_cli_cmd_completion(const char * cmd,const char * str,int pos)3564 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3565 				      int pos)
3566 {
3567 	int i;
3568 
3569 	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3570 		if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3571 			if (wpa_cli_commands[i].completion)
3572 				return wpa_cli_commands[i].completion(str,
3573 								      pos);
3574 			edit_clear_line();
3575 			printf("\r%s\n", wpa_cli_commands[i].usage);
3576 			edit_redraw();
3577 			break;
3578 		}
3579 	}
3580 
3581 	return NULL;
3582 }
3583 
3584 
wpa_cli_edit_completion_cb(void * ctx,const char * str,int pos)3585 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3586 {
3587 	char **res;
3588 	const char *end;
3589 	char *cmd;
3590 
3591 	if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3592 		end = os_strchr(str, ' ');
3593 		if (end && pos > end - str) {
3594 			pos -= end - str + 1;
3595 			str = end + 1;
3596 		}
3597 	}
3598 
3599 	end = os_strchr(str, ' ');
3600 	if (end == NULL || str + pos < end)
3601 		return wpa_list_cmd_list();
3602 
3603 	cmd = os_malloc(pos + 1);
3604 	if (cmd == NULL)
3605 		return NULL;
3606 	os_memcpy(cmd, str, pos);
3607 	cmd[end - str] = '\0';
3608 	res = wpa_cli_cmd_completion(cmd, str, pos);
3609 	os_free(cmd);
3610 	return res;
3611 }
3612 
3613 
wpa_request(struct wpa_ctrl * ctrl,int argc,char * argv[])3614 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3615 {
3616 	const struct wpa_cli_cmd *cmd, *match = NULL;
3617 	int count;
3618 	int ret = 0;
3619 
3620 	if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3621 		ifname_prefix = argv[0] + 7;
3622 		argv = &argv[1];
3623 		argc--;
3624 	} else
3625 		ifname_prefix = NULL;
3626 
3627 	if (argc == 0)
3628 		return -1;
3629 
3630 	count = 0;
3631 	cmd = wpa_cli_commands;
3632 	while (cmd->cmd) {
3633 		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3634 		{
3635 			match = cmd;
3636 			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3637 				/* we have an exact match */
3638 				count = 1;
3639 				break;
3640 			}
3641 			count++;
3642 		}
3643 		cmd++;
3644 	}
3645 
3646 	if (count > 1) {
3647 		printf("Ambiguous command '%s'; possible commands:", argv[0]);
3648 		cmd = wpa_cli_commands;
3649 		while (cmd->cmd) {
3650 			if (os_strncasecmp(cmd->cmd, argv[0],
3651 					   os_strlen(argv[0])) == 0) {
3652 				printf(" %s", cmd->cmd);
3653 			}
3654 			cmd++;
3655 		}
3656 		printf("\n");
3657 		ret = 1;
3658 	} else if (count == 0) {
3659 		printf("Unknown command '%s'\n", argv[0]);
3660 		ret = 1;
3661 	} else {
3662 		ret = match->handler(ctrl, argc - 1, &argv[1]);
3663 	}
3664 
3665 	return ret;
3666 }
3667 
3668 
str_match(const char * a,const char * b)3669 static int str_match(const char *a, const char *b)
3670 {
3671 	return os_strncmp(a, b, os_strlen(b)) == 0;
3672 }
3673 
3674 
wpa_cli_exec(const char * program,const char * arg1,const char * arg2)3675 static int wpa_cli_exec(const char *program, const char *arg1,
3676 			const char *arg2)
3677 {
3678 	char *arg;
3679 	size_t len;
3680 	int res;
3681 
3682 	/* If no interface is specified, set the global */
3683 	if (!arg1)
3684 		arg1 = "global";
3685 
3686 	len = os_strlen(arg1) + os_strlen(arg2) + 2;
3687 	arg = os_malloc(len);
3688 	if (arg == NULL)
3689 		return -1;
3690 	os_snprintf(arg, len, "%s %s", arg1, arg2);
3691 	res = os_exec(program, arg, 1);
3692 	os_free(arg);
3693 
3694 	return res;
3695 }
3696 
3697 
wpa_cli_action_process(const char * msg)3698 static void wpa_cli_action_process(const char *msg)
3699 {
3700 	const char *pos;
3701 	char *copy = NULL, *id, *pos2;
3702 	const char *ifname = ctrl_ifname;
3703 	char ifname_buf[100];
3704 
3705 	if (eloop_terminated())
3706 		return;
3707 
3708 	pos = msg;
3709 	if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3710 		const char *end;
3711 		end = os_strchr(pos + 7, ' ');
3712 		if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3713 			pos += 7;
3714 			os_memcpy(ifname_buf, pos, end - pos);
3715 			ifname_buf[end - pos] = '\0';
3716 			ifname = ifname_buf;
3717 			pos = end + 1;
3718 		}
3719 	}
3720 	if (*pos == '<') {
3721 		const char *prev = pos;
3722 		/* skip priority */
3723 		pos = os_strchr(pos, '>');
3724 		if (pos)
3725 			pos++;
3726 		else
3727 			pos = prev;
3728 	}
3729 
3730 	if (str_match(pos, WPA_EVENT_CONNECTED)) {
3731 		int new_id = -1;
3732 		os_unsetenv("WPA_ID");
3733 		os_unsetenv("WPA_ID_STR");
3734 		os_unsetenv("WPA_CTRL_DIR");
3735 
3736 		pos = os_strstr(pos, "[id=");
3737 		if (pos)
3738 			copy = os_strdup(pos + 4);
3739 
3740 		if (copy) {
3741 			pos2 = id = copy;
3742 			while (*pos2 && *pos2 != ' ')
3743 				pos2++;
3744 			*pos2++ = '\0';
3745 			new_id = atoi(id);
3746 			os_setenv("WPA_ID", id, 1);
3747 			while (*pos2 && *pos2 != '=')
3748 				pos2++;
3749 			if (*pos2 == '=')
3750 				pos2++;
3751 			id = pos2;
3752 			while (*pos2 && *pos2 != ']')
3753 				pos2++;
3754 			*pos2 = '\0';
3755 			os_setenv("WPA_ID_STR", id, 1);
3756 			os_free(copy);
3757 		}
3758 
3759 		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3760 
3761 		if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3762 			wpa_cli_connected = 1;
3763 			wpa_cli_last_id = new_id;
3764 			wpa_cli_exec(action_file, ifname, "CONNECTED");
3765 		}
3766 	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3767 		if (wpa_cli_connected) {
3768 			wpa_cli_connected = 0;
3769 			wpa_cli_exec(action_file, ifname, "DISCONNECTED");
3770 		}
3771 	} else if (str_match(pos, MESH_GROUP_STARTED)) {
3772 		wpa_cli_exec(action_file, ctrl_ifname, pos);
3773 	} else if (str_match(pos, MESH_GROUP_REMOVED)) {
3774 		wpa_cli_exec(action_file, ctrl_ifname, pos);
3775 	} else if (str_match(pos, MESH_PEER_CONNECTED)) {
3776 		wpa_cli_exec(action_file, ctrl_ifname, pos);
3777 	} else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3778 		wpa_cli_exec(action_file, ctrl_ifname, pos);
3779 	} else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3780 		wpa_cli_exec(action_file, ifname, pos);
3781 	} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3782 		wpa_cli_exec(action_file, ifname, pos);
3783 	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3784 		wpa_cli_exec(action_file, ifname, pos);
3785 	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3786 		wpa_cli_exec(action_file, ifname, pos);
3787 	} else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3788 		wpa_cli_exec(action_file, ifname, pos);
3789 	} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3790 		wpa_cli_exec(action_file, ifname, pos);
3791 	} else if (str_match(pos, WPS_EVENT_FAIL)) {
3792 		wpa_cli_exec(action_file, ifname, pos);
3793 	} else if (str_match(pos, AP_STA_CONNECTED)) {
3794 		wpa_cli_exec(action_file, ifname, pos);
3795 	} else if (str_match(pos, AP_STA_DISCONNECTED)) {
3796 		wpa_cli_exec(action_file, ifname, pos);
3797 	} else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3798 		wpa_cli_exec(action_file, ifname, pos);
3799 	} else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3800 		wpa_cli_exec(action_file, ifname, pos);
3801 	} else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3802 		wpa_cli_exec(action_file, ifname, pos);
3803 	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3804 		printf("wpa_supplicant is terminating - stop monitoring\n");
3805 		wpa_cli_quit = 1;
3806 	}
3807 }
3808 
3809 
3810 #ifndef CONFIG_ANSI_C_EXTRA
wpa_cli_action_cb(char * msg,size_t len)3811 static void wpa_cli_action_cb(char *msg, size_t len)
3812 {
3813 	wpa_cli_action_process(msg);
3814 }
3815 #endif /* CONFIG_ANSI_C_EXTRA */
3816 
3817 
wpa_cli_reconnect(void)3818 static void wpa_cli_reconnect(void)
3819 {
3820 	wpa_cli_close_connection();
3821 	if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3822 		return;
3823 
3824 	if (interactive) {
3825 		edit_clear_line();
3826 		printf("\rConnection to wpa_supplicant re-established\n");
3827 		edit_redraw();
3828 	}
3829 }
3830 
3831 
cli_event(const char * str)3832 static void cli_event(const char *str)
3833 {
3834 	const char *start, *s;
3835 
3836 	start = os_strchr(str, '>');
3837 	if (start == NULL)
3838 		return;
3839 
3840 	start++;
3841 
3842 	if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3843 		s = os_strchr(start, ' ');
3844 		if (s == NULL)
3845 			return;
3846 		s = os_strchr(s + 1, ' ');
3847 		if (s == NULL)
3848 			return;
3849 		cli_txt_list_add(&bsses, s + 1);
3850 		return;
3851 	}
3852 
3853 	if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3854 		s = os_strchr(start, ' ');
3855 		if (s == NULL)
3856 			return;
3857 		s = os_strchr(s + 1, ' ');
3858 		if (s == NULL)
3859 			return;
3860 		cli_txt_list_del_addr(&bsses, s + 1);
3861 		return;
3862 	}
3863 
3864 #ifdef CONFIG_P2P
3865 	if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3866 		s = os_strstr(start, " p2p_dev_addr=");
3867 		if (s == NULL)
3868 			return;
3869 		cli_txt_list_add_addr(&p2p_peers, s + 14);
3870 		return;
3871 	}
3872 
3873 	if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3874 		s = os_strstr(start, " p2p_dev_addr=");
3875 		if (s == NULL)
3876 			return;
3877 		cli_txt_list_del_addr(&p2p_peers, s + 14);
3878 		return;
3879 	}
3880 
3881 	if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3882 		s = os_strchr(start, ' ');
3883 		if (s == NULL)
3884 			return;
3885 		cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
3886 		return;
3887 	}
3888 
3889 	if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3890 		s = os_strchr(start, ' ');
3891 		if (s == NULL)
3892 			return;
3893 		cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
3894 		return;
3895 	}
3896 #endif /* CONFIG_P2P */
3897 }
3898 
3899 
check_terminating(const char * msg)3900 static int check_terminating(const char *msg)
3901 {
3902 	const char *pos = msg;
3903 
3904 	if (*pos == '<') {
3905 		/* skip priority */
3906 		pos = os_strchr(pos, '>');
3907 		if (pos)
3908 			pos++;
3909 		else
3910 			pos = msg;
3911 	}
3912 
3913 	if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3914 		edit_clear_line();
3915 		printf("\rConnection to wpa_supplicant lost - trying to "
3916 		       "reconnect\n");
3917 		edit_redraw();
3918 		wpa_cli_attached = 0;
3919 		wpa_cli_close_connection();
3920 		return 1;
3921 	}
3922 
3923 	return 0;
3924 }
3925 
3926 
wpa_cli_recv_pending(struct wpa_ctrl * ctrl,int action_monitor)3927 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3928 {
3929 	if (ctrl_conn == NULL) {
3930 		wpa_cli_reconnect();
3931 		return;
3932 	}
3933 	while (wpa_ctrl_pending(ctrl) > 0) {
3934 		char buf[4096];
3935 		size_t len = sizeof(buf) - 1;
3936 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3937 			buf[len] = '\0';
3938 			if (action_monitor)
3939 				wpa_cli_action_process(buf);
3940 			else {
3941 				cli_event(buf);
3942 				if (wpa_cli_show_event(buf)) {
3943 					edit_clear_line();
3944 					printf("\r%s\n", buf);
3945 					edit_redraw();
3946 				}
3947 
3948 				if (interactive && check_terminating(buf) > 0)
3949 					return;
3950 			}
3951 		} else {
3952 			printf("Could not read pending message.\n");
3953 			break;
3954 		}
3955 	}
3956 
3957 	if (wpa_ctrl_pending(ctrl) < 0) {
3958 		printf("Connection to wpa_supplicant lost - trying to "
3959 		       "reconnect\n");
3960 		wpa_cli_reconnect();
3961 	}
3962 }
3963 
3964 #define max_args 10
3965 
tokenize_cmd(char * cmd,char * argv[])3966 static int tokenize_cmd(char *cmd, char *argv[])
3967 {
3968 	char *pos;
3969 	int argc = 0;
3970 
3971 	pos = cmd;
3972 	for (;;) {
3973 		while (*pos == ' ')
3974 			pos++;
3975 		if (*pos == '\0')
3976 			break;
3977 		argv[argc] = pos;
3978 		argc++;
3979 		if (argc == max_args)
3980 			break;
3981 		if (*pos == '"') {
3982 			char *pos2 = os_strrchr(pos, '"');
3983 			if (pos2)
3984 				pos = pos2 + 1;
3985 		}
3986 		while (*pos != '\0' && *pos != ' ')
3987 			pos++;
3988 		if (*pos == ' ')
3989 			*pos++ = '\0';
3990 	}
3991 
3992 	return argc;
3993 }
3994 
3995 
wpa_cli_ping(void * eloop_ctx,void * timeout_ctx)3996 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3997 {
3998 	if (ctrl_conn) {
3999 		int res;
4000 		char *prefix = ifname_prefix;
4001 
4002 		ifname_prefix = NULL;
4003 		res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
4004 		ifname_prefix = prefix;
4005 		if (res) {
4006 			printf("Connection to wpa_supplicant lost - trying to "
4007 			       "reconnect\n");
4008 			wpa_cli_close_connection();
4009 		}
4010 	}
4011 	if (!ctrl_conn)
4012 		wpa_cli_reconnect();
4013 	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4014 }
4015 
4016 
wpa_cli_mon_receive(int sock,void * eloop_ctx,void * sock_ctx)4017 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
4018 {
4019 	wpa_cli_recv_pending(mon_conn, 0);
4020 }
4021 
4022 
wpa_cli_edit_cmd_cb(void * ctx,char * cmd)4023 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
4024 {
4025 	char *argv[max_args];
4026 	int argc;
4027 	argc = tokenize_cmd(cmd, argv);
4028 	if (argc)
4029 		wpa_request(ctrl_conn, argc, argv);
4030 }
4031 
4032 
wpa_cli_edit_eof_cb(void * ctx)4033 static void wpa_cli_edit_eof_cb(void *ctx)
4034 {
4035 	eloop_terminate();
4036 }
4037 
4038 
4039 static int warning_displayed = 0;
4040 static char *hfile = NULL;
4041 static int edit_started = 0;
4042 
start_edit(void)4043 static void start_edit(void)
4044 {
4045 	char *home;
4046 	char *ps = NULL;
4047 
4048 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
4049 	ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
4050 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
4051 
4052 #ifdef CONFIG_WPA_CLI_HISTORY_DIR
4053 	home = CONFIG_WPA_CLI_HISTORY_DIR;
4054 #else /* CONFIG_WPA_CLI_HISTORY_DIR */
4055 	home = getenv("HOME");
4056 #endif /* CONFIG_WPA_CLI_HISTORY_DIR */
4057 	if (home) {
4058 		const char *fname = ".wpa_cli_history";
4059 		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
4060 		hfile = os_malloc(hfile_len);
4061 		if (hfile)
4062 			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
4063 	}
4064 
4065 	if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
4066 		      wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4067 		eloop_terminate();
4068 		return;
4069 	}
4070 
4071 	edit_started = 1;
4072 	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4073 }
4074 
4075 
update_bssid_list(struct wpa_ctrl * ctrl)4076 static void update_bssid_list(struct wpa_ctrl *ctrl)
4077 {
4078 	char buf[4096];
4079 	size_t len = sizeof(buf);
4080 	int ret;
4081 	char *cmd = "BSS RANGE=ALL MASK=0x2";
4082 	char *pos, *end;
4083 
4084 	if (ctrl == NULL)
4085 		return;
4086 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4087 	if (ret < 0)
4088 		return;
4089 	buf[len] = '\0';
4090 
4091 	pos = buf;
4092 	while (pos) {
4093 		pos = os_strstr(pos, "bssid=");
4094 		if (pos == NULL)
4095 			break;
4096 		pos += 6;
4097 		end = os_strchr(pos, '\n');
4098 		if (end == NULL)
4099 			break;
4100 		*end = '\0';
4101 		cli_txt_list_add(&bsses, pos);
4102 		pos = end + 1;
4103 	}
4104 }
4105 
4106 
update_ifnames(struct wpa_ctrl * ctrl)4107 static void update_ifnames(struct wpa_ctrl *ctrl)
4108 {
4109 	char buf[4096];
4110 	size_t len = sizeof(buf);
4111 	int ret;
4112 	char *cmd = "INTERFACES";
4113 	char *pos, *end;
4114 	char txt[200];
4115 
4116 	cli_txt_list_flush(&ifnames);
4117 
4118 	if (ctrl == NULL)
4119 		return;
4120 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4121 	if (ret < 0)
4122 		return;
4123 	buf[len] = '\0';
4124 
4125 	pos = buf;
4126 	while (pos) {
4127 		end = os_strchr(pos, '\n');
4128 		if (end == NULL)
4129 			break;
4130 		*end = '\0';
4131 		ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
4132 		if (!os_snprintf_error(sizeof(txt), ret))
4133 			cli_txt_list_add(&ifnames, txt);
4134 		pos = end + 1;
4135 	}
4136 }
4137 
4138 
update_networks(struct wpa_ctrl * ctrl)4139 static void update_networks(struct wpa_ctrl *ctrl)
4140 {
4141 	char buf[4096];
4142 	size_t len = sizeof(buf);
4143 	int ret;
4144 	char *cmd = "LIST_NETWORKS";
4145 	char *pos, *end;
4146 	int header = 1;
4147 
4148 	cli_txt_list_flush(&networks);
4149 
4150 	if (ctrl == NULL)
4151 		return;
4152 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4153 	if (ret < 0)
4154 		return;
4155 	buf[len] = '\0';
4156 
4157 	pos = buf;
4158 	while (pos) {
4159 		end = os_strchr(pos, '\n');
4160 		if (end == NULL)
4161 			break;
4162 		*end = '\0';
4163 		if (!header)
4164 			cli_txt_list_add_word(&networks, pos, '\t');
4165 		header = 0;
4166 		pos = end + 1;
4167 	}
4168 }
4169 
4170 
try_connection(void * eloop_ctx,void * timeout_ctx)4171 static void try_connection(void *eloop_ctx, void *timeout_ctx)
4172 {
4173 	if (ctrl_conn)
4174 		goto done;
4175 
4176 	if (ctrl_ifname == NULL)
4177 		ctrl_ifname = wpa_cli_get_default_ifname();
4178 
4179 	if (wpa_cli_open_connection(ctrl_ifname, 1)) {
4180 		if (!warning_displayed) {
4181 			printf("Could not connect to wpa_supplicant: "
4182 			       "%s - re-trying\n",
4183 			       ctrl_ifname ? ctrl_ifname : "(nil)");
4184 			warning_displayed = 1;
4185 		}
4186 		eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4187 		return;
4188 	}
4189 
4190 	update_bssid_list(ctrl_conn);
4191 	update_networks(ctrl_conn);
4192 
4193 	if (warning_displayed)
4194 		printf("Connection established.\n");
4195 
4196 done:
4197 	start_edit();
4198 }
4199 
4200 
wpa_cli_interactive(void)4201 static void wpa_cli_interactive(void)
4202 {
4203 	printf("\nInteractive mode\n\n");
4204 
4205 	eloop_register_timeout(0, 0, try_connection, NULL, NULL);
4206 	eloop_run();
4207 	eloop_cancel_timeout(try_connection, NULL, NULL);
4208 
4209 	cli_txt_list_flush(&p2p_peers);
4210 	cli_txt_list_flush(&p2p_groups);
4211 	cli_txt_list_flush(&bsses);
4212 	cli_txt_list_flush(&ifnames);
4213 	cli_txt_list_flush(&networks);
4214 	if (edit_started)
4215 		edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
4216 	os_free(hfile);
4217 	eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
4218 	wpa_cli_close_connection();
4219 }
4220 
4221 
wpa_cli_action_ping(void * eloop_ctx,void * timeout_ctx)4222 static void wpa_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
4223 {
4224 	struct wpa_ctrl *ctrl = eloop_ctx;
4225 	char buf[256];
4226 	size_t len;
4227 
4228 	/* verify that connection is still working */
4229 	len = sizeof(buf) - 1;
4230 	if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
4231 			     wpa_cli_action_cb) < 0 ||
4232 	    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
4233 		printf("wpa_supplicant did not reply to PING command - exiting\n");
4234 		eloop_terminate();
4235 		return;
4236 	}
4237 	eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4238 			       ctrl, NULL);
4239 }
4240 
4241 
wpa_cli_action_receive(int sock,void * eloop_ctx,void * sock_ctx)4242 static void wpa_cli_action_receive(int sock, void *eloop_ctx, void *sock_ctx)
4243 {
4244 	struct wpa_ctrl *ctrl = eloop_ctx;
4245 
4246 	wpa_cli_recv_pending(ctrl, 1);
4247 }
4248 
4249 
wpa_cli_action(struct wpa_ctrl * ctrl)4250 static void wpa_cli_action(struct wpa_ctrl *ctrl)
4251 {
4252 #ifdef CONFIG_ANSI_C_EXTRA
4253 	/* TODO: ANSI C version(?) */
4254 	printf("Action processing not supported in ANSI C build.\n");
4255 #else /* CONFIG_ANSI_C_EXTRA */
4256 	int fd;
4257 
4258 	fd = wpa_ctrl_get_fd(ctrl);
4259 	eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4260 			       ctrl, NULL);
4261 	eloop_register_read_sock(fd, wpa_cli_action_receive, ctrl, NULL);
4262 	eloop_run();
4263 	eloop_cancel_timeout(wpa_cli_action_ping, ctrl, NULL);
4264 	eloop_unregister_read_sock(fd);
4265 #endif /* CONFIG_ANSI_C_EXTRA */
4266 }
4267 
4268 
wpa_cli_cleanup(void)4269 static void wpa_cli_cleanup(void)
4270 {
4271 	wpa_cli_close_connection();
4272 	if (pid_file)
4273 		os_daemonize_terminate(pid_file);
4274 
4275 	os_program_deinit();
4276 }
4277 
4278 
wpa_cli_terminate(int sig,void * ctx)4279 static void wpa_cli_terminate(int sig, void *ctx)
4280 {
4281 	eloop_terminate();
4282 }
4283 
4284 
wpa_cli_get_default_ifname(void)4285 static char * wpa_cli_get_default_ifname(void)
4286 {
4287 	char *ifname = NULL;
4288 
4289 #ifdef ANDROID
4290 	char ifprop[PROPERTY_VALUE_MAX];
4291 	if (property_get("wifi.interface", ifprop, NULL) != 0) {
4292 		ifname = os_strdup(ifprop);
4293 		printf("Using interface '%s'\n", ifname ? ifname : "N/A");
4294 	}
4295 #else /* ANDROID */
4296 #ifdef CONFIG_CTRL_IFACE_UNIX
4297 	struct dirent *dent;
4298 	DIR *dir = opendir(ctrl_iface_dir);
4299 	if (!dir) {
4300 		return NULL;
4301 	}
4302 	while ((dent = readdir(dir))) {
4303 #ifdef _DIRENT_HAVE_D_TYPE
4304 		/*
4305 		 * Skip the file if it is not a socket. Also accept
4306 		 * DT_UNKNOWN (0) in case the C library or underlying
4307 		 * file system does not support d_type.
4308 		 */
4309 		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4310 			continue;
4311 #endif /* _DIRENT_HAVE_D_TYPE */
4312 		if (os_strcmp(dent->d_name, ".") == 0 ||
4313 		    os_strcmp(dent->d_name, "..") == 0)
4314 			continue;
4315 		printf("Selected interface '%s'\n", dent->d_name);
4316 		ifname = os_strdup(dent->d_name);
4317 		break;
4318 	}
4319 	closedir(dir);
4320 #endif /* CONFIG_CTRL_IFACE_UNIX */
4321 
4322 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4323 	char buf[4096], *pos;
4324 	size_t len;
4325 	struct wpa_ctrl *ctrl;
4326 	int ret;
4327 
4328 	ctrl = wpa_ctrl_open(NULL);
4329 	if (ctrl == NULL)
4330 		return NULL;
4331 
4332 	len = sizeof(buf) - 1;
4333 	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4334 	if (ret >= 0) {
4335 		buf[len] = '\0';
4336 		pos = os_strchr(buf, '\n');
4337 		if (pos)
4338 			*pos = '\0';
4339 		ifname = os_strdup(buf);
4340 	}
4341 	wpa_ctrl_close(ctrl);
4342 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4343 #endif /* ANDROID */
4344 
4345 	return ifname;
4346 }
4347 
4348 
main(int argc,char * argv[])4349 int main(int argc, char *argv[])
4350 {
4351 	int c;
4352 	int daemonize = 0;
4353 	int ret = 0;
4354 	const char *global = NULL;
4355 
4356 	if (os_program_init())
4357 		return -1;
4358 
4359 	for (;;) {
4360 		c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
4361 		if (c < 0)
4362 			break;
4363 		switch (c) {
4364 		case 'a':
4365 			action_file = optarg;
4366 			break;
4367 		case 'B':
4368 			daemonize = 1;
4369 			break;
4370 		case 'g':
4371 			global = optarg;
4372 			break;
4373 		case 'G':
4374 			ping_interval = atoi(optarg);
4375 			break;
4376 		case 'h':
4377 			usage();
4378 			return 0;
4379 		case 'v':
4380 			printf("%s\n", wpa_cli_version);
4381 			return 0;
4382 		case 'i':
4383 			os_free(ctrl_ifname);
4384 			ctrl_ifname = os_strdup(optarg);
4385 			break;
4386 		case 'p':
4387 			ctrl_iface_dir = optarg;
4388 			break;
4389 		case 'P':
4390 			pid_file = optarg;
4391 			break;
4392 		case 's':
4393 			client_socket_dir = optarg;
4394 			break;
4395 		default:
4396 			usage();
4397 			return -1;
4398 		}
4399 	}
4400 
4401 	interactive = (argc == optind) && (action_file == NULL);
4402 
4403 	if (interactive)
4404 		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4405 
4406 	if (eloop_init())
4407 		return -1;
4408 
4409 	if (global) {
4410 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4411 		ctrl_conn = wpa_ctrl_open(NULL);
4412 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4413 		ctrl_conn = wpa_ctrl_open(global);
4414 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4415 		if (ctrl_conn == NULL) {
4416 			fprintf(stderr, "Failed to connect to wpa_supplicant "
4417 				"global interface: %s  error: %s\n",
4418 				global, strerror(errno));
4419 			return -1;
4420 		}
4421 
4422 		if (interactive) {
4423 			update_ifnames(ctrl_conn);
4424 			mon_conn = wpa_ctrl_open(global);
4425 			if (mon_conn) {
4426 				if (wpa_ctrl_attach(mon_conn) == 0) {
4427 					wpa_cli_attached = 1;
4428 					eloop_register_read_sock(
4429 						wpa_ctrl_get_fd(mon_conn),
4430 						wpa_cli_mon_receive,
4431 						NULL, NULL);
4432 				} else {
4433 					printf("Failed to open monitor "
4434 					       "connection through global "
4435 					       "control interface\n");
4436 				}
4437 			}
4438 		}
4439 	}
4440 
4441 	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
4442 
4443 	if (ctrl_ifname == NULL)
4444 		ctrl_ifname = wpa_cli_get_default_ifname();
4445 
4446 	if (interactive) {
4447 		wpa_cli_interactive();
4448 	} else {
4449 		if (!global &&
4450 		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4451 			fprintf(stderr, "Failed to connect to non-global "
4452 				"ctrl_ifname: %s  error: %s\n",
4453 				ctrl_ifname ? ctrl_ifname : "(nil)",
4454 				strerror(errno));
4455 			return -1;
4456 		}
4457 
4458 		if (action_file) {
4459 			if (wpa_ctrl_attach(ctrl_conn) == 0) {
4460 				wpa_cli_attached = 1;
4461 			} else {
4462 				printf("Warning: Failed to attach to "
4463 				       "wpa_supplicant.\n");
4464 				return -1;
4465 			}
4466 		}
4467 
4468 		if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
4469 			return -1;
4470 
4471 		if (action_file)
4472 			wpa_cli_action(ctrl_conn);
4473 		else
4474 			ret = wpa_request(ctrl_conn, argc - optind,
4475 					  &argv[optind]);
4476 	}
4477 
4478 	os_free(ctrl_ifname);
4479 	eloop_destroy();
4480 	wpa_cli_cleanup();
4481 
4482 	return ret;
4483 }
4484 
4485 #else /* CONFIG_CTRL_IFACE */
main(int argc,char * argv[])4486 int main(int argc, char *argv[])
4487 {
4488 	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4489 	return -1;
4490 }
4491 #endif /* CONFIG_CTRL_IFACE */
4492