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