]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
P2P: Add frequency into group started ctrl_interface events
[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
116f7bb0 618#ifdef CONFIG_WPS_OOB
46bdb83a
MH
619static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
620{
621 char cmd[256];
622 int res;
623
e1ee6b60
MH
624 if (argc != 3 && argc != 4) {
625 printf("Invalid WPS_OOB command: need three or four "
626 "arguments:\n"
627 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
628 "- PATH: path of OOB device like '/mnt'\n"
629 "- METHOD: OOB method 'pin-e' or 'pin-r', "
630 "'cred'\n"
631 "- DEV_NAME: (only for NFC) device name like "
632 "'pn531'\n");
46bdb83a
MH
633 return -1;
634 }
635
e1ee6b60
MH
636 if (argc == 3)
637 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
638 argv[0], argv[1], argv[2]);
639 else
640 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
641 argv[0], argv[1], argv[2], argv[3]);
46bdb83a
MH
642 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
643 printf("Too long WPS_OOB command.\n");
644 return -1;
645 }
646 return wpa_ctrl_command(ctrl, cmd);
647}
116f7bb0 648#endif /* CONFIG_WPS_OOB */
46bdb83a
MH
649
650
fcc60db4
JM
651static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
652{
653 char cmd[256];
654 int res;
655
52eb293d
JM
656 if (argc == 2)
657 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
658 argv[0], argv[1]);
7d6640a6 659 else if (argc == 5 || argc == 6) {
52eb293d
JM
660 char ssid_hex[2 * 32 + 1];
661 char key_hex[2 * 64 + 1];
662 int i;
663
664 ssid_hex[0] = '\0';
665 for (i = 0; i < 32; i++) {
666 if (argv[2][i] == '\0')
667 break;
668 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
669 }
670
671 key_hex[0] = '\0';
7d6640a6
JM
672 if (argc == 6) {
673 for (i = 0; i < 64; i++) {
674 if (argv[5][i] == '\0')
675 break;
676 os_snprintf(&key_hex[i * 2], 3, "%02x",
677 argv[5][i]);
678 }
52eb293d
JM
679 }
680
681 res = os_snprintf(cmd, sizeof(cmd),
682 "WPS_REG %s %s %s %s %s %s",
683 argv[0], argv[1], ssid_hex, argv[3], argv[4],
684 key_hex);
685 } else {
fcc60db4
JM
686 printf("Invalid WPS_REG command: need two arguments:\n"
687 "- BSSID: use 'any' to select any\n"
688 "- AP PIN\n");
52eb293d
JM
689 printf("Alternatively, six arguments can be used to "
690 "reconfigure the AP:\n"
691 "- BSSID: use 'any' to select any\n"
692 "- AP PIN\n"
693 "- new SSID\n"
694 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
695 "- new encr (NONE, WEP, TKIP, CCMP)\n"
696 "- new key\n");
fcc60db4
JM
697 return -1;
698 }
699
fcc60db4
JM
700 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
701 printf("Too long WPS_REG command.\n");
702 return -1;
703 }
704 return wpa_ctrl_command(ctrl, cmd);
705}
706
707
e9bcfebf
JM
708static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
709 char *argv[])
710{
08486685
JM
711 char cmd[100];
712 if (argc > 0) {
713 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
714 return wpa_ctrl_command(ctrl, cmd);
715 }
e9bcfebf 716 return wpa_ctrl_command(ctrl, "WPS_ER_START");
e9bcfebf
JM
717}
718
719
720static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
721 char *argv[])
722{
723 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
724
725}
726
727
72df2f5f
JM
728static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
729 char *argv[])
730{
731 char cmd[256];
732 int res;
733
31fcea93
JM
734 if (argc < 2) {
735 printf("Invalid WPS_ER_PIN command: need at least two "
736 "arguments:\n"
72df2f5f 737 "- UUID: use 'any' to select any\n"
31fcea93
JM
738 "- PIN: Enrollee PIN\n"
739 "optional: - Enrollee MAC address\n");
72df2f5f
JM
740 return -1;
741 }
742
31fcea93
JM
743 if (argc > 2)
744 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
745 argv[0], argv[1], argv[2]);
746 else
747 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
748 argv[0], argv[1]);
72df2f5f
JM
749 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
750 printf("Too long WPS_ER_PIN command.\n");
751 return -1;
752 }
753 return wpa_ctrl_command(ctrl, cmd);
754}
755
756
564cd7fa
JM
757static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
758 char *argv[])
759{
760 char cmd[256];
761 int res;
762
763 if (argc != 1) {
764 printf("Invalid WPS_ER_PBC command: need one argument:\n"
765 "- UUID: Specify the Enrollee\n");
766 return -1;
767 }
768
769 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
770 argv[0]);
771 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
772 printf("Too long WPS_ER_PBC command.\n");
773 return -1;
774 }
775 return wpa_ctrl_command(ctrl, cmd);
776}
777
778
e64dcfd5
JM
779static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
780 char *argv[])
781{
782 char cmd[256];
783 int res;
784
785 if (argc != 2) {
786 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
787 "- UUID: specify which AP to use\n"
788 "- PIN: AP PIN\n");
789 return -1;
790 }
791
792 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
793 argv[0], argv[1]);
794 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
795 printf("Too long WPS_ER_LEARN command.\n");
796 return -1;
797 }
798 return wpa_ctrl_command(ctrl, cmd);
799}
800
801
7d6640a6
JM
802static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
803 char *argv[])
804{
805 char cmd[256];
806 int res;
807
808 if (argc == 5 || argc == 6) {
809 char ssid_hex[2 * 32 + 1];
810 char key_hex[2 * 64 + 1];
811 int i;
812
813 ssid_hex[0] = '\0';
814 for (i = 0; i < 32; i++) {
815 if (argv[2][i] == '\0')
816 break;
817 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
818 }
819
820 key_hex[0] = '\0';
821 if (argc == 6) {
822 for (i = 0; i < 64; i++) {
823 if (argv[5][i] == '\0')
824 break;
825 os_snprintf(&key_hex[i * 2], 3, "%02x",
826 argv[5][i]);
827 }
828 }
829
830 res = os_snprintf(cmd, sizeof(cmd),
831 "WPS_ER_CONFIG %s %s %s %s %s %s",
832 argv[0], argv[1], ssid_hex, argv[3], argv[4],
833 key_hex);
834 } else {
835 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
836 "- AP UUID\n"
837 "- AP PIN\n"
838 "- new SSID\n"
839 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
840 "- new encr (NONE, WEP, TKIP, CCMP)\n"
841 "- new key\n");
842 return -1;
843 }
844
845 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
846 printf("Too long WPS_ER_CONFIG command.\n");
847 return -1;
848 }
849 return wpa_ctrl_command(ctrl, cmd);
850}
851
852
11ef8d35
JM
853static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
854{
855 char cmd[256];
856 int res;
857
858 if (argc != 1) {
859 printf("Invalid IBSS_RSN command: needs one argument "
860 "(Peer STA MAC address)\n");
861 return -1;
862 }
863
864 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
865 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
866 printf("Too long IBSS_RSN command.\n");
867 return -1;
868 }
869 return wpa_ctrl_command(ctrl, cmd);
870}
871
872
6fc6879b
JM
873static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
874{
875 char cmd[256];
876 int res;
877
878 if (argc != 1) {
879 printf("Invalid LEVEL command: needs one argument (debug "
880 "level)\n");
881 return -1;
882 }
883 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
884 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
885 printf("Too long LEVEL command.\n");
886 return -1;
887 }
888 return wpa_ctrl_command(ctrl, cmd);
889}
890
891
892static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
893{
894 char cmd[256], *pos, *end;
895 int i, ret;
896
897 if (argc < 2) {
898 printf("Invalid IDENTITY command: needs two arguments "
899 "(network id and identity)\n");
900 return -1;
901 }
902
903 end = cmd + sizeof(cmd);
904 pos = cmd;
905 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
906 argv[0], argv[1]);
907 if (ret < 0 || ret >= end - pos) {
908 printf("Too long IDENTITY command.\n");
909 return -1;
910 }
911 pos += ret;
912 for (i = 2; i < argc; i++) {
913 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
914 if (ret < 0 || ret >= end - pos) {
915 printf("Too long IDENTITY command.\n");
916 return -1;
917 }
918 pos += ret;
919 }
920
921 return wpa_ctrl_command(ctrl, cmd);
922}
923
924
925static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
926{
927 char cmd[256], *pos, *end;
928 int i, ret;
929
930 if (argc < 2) {
931 printf("Invalid PASSWORD command: needs two arguments "
932 "(network id and password)\n");
933 return -1;
934 }
935
936 end = cmd + sizeof(cmd);
937 pos = cmd;
938 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
939 argv[0], argv[1]);
940 if (ret < 0 || ret >= end - pos) {
941 printf("Too long PASSWORD command.\n");
942 return -1;
943 }
944 pos += ret;
945 for (i = 2; i < argc; i++) {
946 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
947 if (ret < 0 || ret >= end - pos) {
948 printf("Too long PASSWORD command.\n");
949 return -1;
950 }
951 pos += ret;
952 }
953
954 return wpa_ctrl_command(ctrl, cmd);
955}
956
957
958static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
959 char *argv[])
960{
961 char cmd[256], *pos, *end;
962 int i, ret;
963
964 if (argc < 2) {
965 printf("Invalid NEW_PASSWORD command: needs two arguments "
966 "(network id and password)\n");
967 return -1;
968 }
969
970 end = cmd + sizeof(cmd);
971 pos = cmd;
972 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
973 argv[0], argv[1]);
974 if (ret < 0 || ret >= end - pos) {
975 printf("Too long NEW_PASSWORD command.\n");
976 return -1;
977 }
978 pos += ret;
979 for (i = 2; i < argc; i++) {
980 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
981 if (ret < 0 || ret >= end - pos) {
982 printf("Too long NEW_PASSWORD command.\n");
983 return -1;
984 }
985 pos += ret;
986 }
987
988 return wpa_ctrl_command(ctrl, cmd);
989}
990
991
992static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
993{
994 char cmd[256], *pos, *end;
995 int i, ret;
996
997 if (argc < 2) {
998 printf("Invalid PIN command: needs two arguments "
999 "(network id and pin)\n");
1000 return -1;
1001 }
1002
1003 end = cmd + sizeof(cmd);
1004 pos = cmd;
1005 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1006 argv[0], argv[1]);
1007 if (ret < 0 || ret >= end - pos) {
1008 printf("Too long PIN command.\n");
1009 return -1;
1010 }
1011 pos += ret;
1012 for (i = 2; i < argc; i++) {
1013 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1014 if (ret < 0 || ret >= end - pos) {
1015 printf("Too long PIN command.\n");
1016 return -1;
1017 }
1018 pos += ret;
1019 }
1020 return wpa_ctrl_command(ctrl, cmd);
1021}
1022
1023
1024static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1025{
1026 char cmd[256], *pos, *end;
1027 int i, ret;
1028
1029 if (argc < 2) {
1030 printf("Invalid OTP command: needs two arguments (network "
1031 "id and password)\n");
1032 return -1;
1033 }
1034
1035 end = cmd + sizeof(cmd);
1036 pos = cmd;
1037 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1038 argv[0], argv[1]);
1039 if (ret < 0 || ret >= end - pos) {
1040 printf("Too long OTP command.\n");
1041 return -1;
1042 }
1043 pos += ret;
1044 for (i = 2; i < argc; i++) {
1045 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1046 if (ret < 0 || ret >= end - pos) {
1047 printf("Too long OTP command.\n");
1048 return -1;
1049 }
1050 pos += ret;
1051 }
1052
1053 return wpa_ctrl_command(ctrl, cmd);
1054}
1055
1056
1057static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1058 char *argv[])
1059{
1060 char cmd[256], *pos, *end;
1061 int i, ret;
1062
1063 if (argc < 2) {
1064 printf("Invalid PASSPHRASE command: needs two arguments "
1065 "(network id and passphrase)\n");
1066 return -1;
1067 }
1068
1069 end = cmd + sizeof(cmd);
1070 pos = cmd;
1071 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1072 argv[0], argv[1]);
1073 if (ret < 0 || ret >= end - pos) {
1074 printf("Too long PASSPHRASE command.\n");
1075 return -1;
1076 }
1077 pos += ret;
1078 for (i = 2; i < argc; i++) {
1079 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1080 if (ret < 0 || ret >= end - pos) {
1081 printf("Too long PASSPHRASE command.\n");
1082 return -1;
1083 }
1084 pos += ret;
1085 }
1086
1087 return wpa_ctrl_command(ctrl, cmd);
1088}
1089
1090
1091static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1092{
1093 char cmd[256], *pos, *end;
1094 int i, ret;
1095
1096 if (argc < 2) {
1097 printf("Invalid BSSID command: needs two arguments (network "
1098 "id and BSSID)\n");
1099 return -1;
1100 }
1101
1102 end = cmd + sizeof(cmd);
1103 pos = cmd;
1104 ret = os_snprintf(pos, end - pos, "BSSID");
1105 if (ret < 0 || ret >= end - pos) {
1106 printf("Too long BSSID command.\n");
1107 return -1;
1108 }
1109 pos += ret;
1110 for (i = 0; i < argc; i++) {
1111 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1112 if (ret < 0 || ret >= end - pos) {
1113 printf("Too long BSSID command.\n");
1114 return -1;
1115 }
1116 pos += ret;
1117 }
1118
1119 return wpa_ctrl_command(ctrl, cmd);
1120}
1121
1122
1123static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1124 char *argv[])
1125{
1126 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1127}
1128
1129
1130static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1131 char *argv[])
1132{
1133 char cmd[32];
1134 int res;
1135
1136 if (argc < 1) {
1137 printf("Invalid SELECT_NETWORK command: needs one argument "
1138 "(network id)\n");
1139 return -1;
1140 }
1141
1142 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1143 if (res < 0 || (size_t) res >= sizeof(cmd))
1144 return -1;
1145 cmd[sizeof(cmd) - 1] = '\0';
1146
1147 return wpa_ctrl_command(ctrl, cmd);
1148}
1149
1150
1151static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1152 char *argv[])
1153{
1154 char cmd[32];
1155 int res;
1156
1157 if (argc < 1) {
1158 printf("Invalid ENABLE_NETWORK command: needs one argument "
1159 "(network id)\n");
1160 return -1;
1161 }
1162
1163 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1164 if (res < 0 || (size_t) res >= sizeof(cmd))
1165 return -1;
1166 cmd[sizeof(cmd) - 1] = '\0';
1167
1168 return wpa_ctrl_command(ctrl, cmd);
1169}
1170
1171
1172static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1173 char *argv[])
1174{
1175 char cmd[32];
1176 int res;
1177
1178 if (argc < 1) {
1179 printf("Invalid DISABLE_NETWORK command: needs one argument "
1180 "(network id)\n");
1181 return -1;
1182 }
1183
1184 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1185 if (res < 0 || (size_t) res >= sizeof(cmd))
1186 return -1;
1187 cmd[sizeof(cmd) - 1] = '\0';
1188
1189 return wpa_ctrl_command(ctrl, cmd);
1190}
1191
1192
1193static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1194 char *argv[])
1195{
1196 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1197}
1198
1199
1200static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1201 char *argv[])
1202{
1203 char cmd[32];
1204 int res;
1205
1206 if (argc < 1) {
1207 printf("Invalid REMOVE_NETWORK command: needs one argument "
1208 "(network id)\n");
1209 return -1;
1210 }
1211
1212 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1213 if (res < 0 || (size_t) res >= sizeof(cmd))
1214 return -1;
1215 cmd[sizeof(cmd) - 1] = '\0';
1216
1217 return wpa_ctrl_command(ctrl, cmd);
1218}
1219
1220
1221static void wpa_cli_show_network_variables(void)
1222{
1223 printf("set_network variables:\n"
1224 " ssid (network name, SSID)\n"
1225 " psk (WPA passphrase or pre-shared key)\n"
1226 " key_mgmt (key management protocol)\n"
1227 " identity (EAP identity)\n"
1228 " password (EAP password)\n"
1229 " ...\n"
1230 "\n"
1231 "Note: Values are entered in the same format as the "
1232 "configuration file is using,\n"
1233 "i.e., strings values need to be inside double quotation "
1234 "marks.\n"
1235 "For example: set_network 1 ssid \"network name\"\n"
1236 "\n"
1237 "Please see wpa_supplicant.conf documentation for full list "
1238 "of\navailable variables.\n");
1239}
1240
1241
1242static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1243 char *argv[])
1244{
1245 char cmd[256];
1246 int res;
1247
1248 if (argc == 0) {
1249 wpa_cli_show_network_variables();
1250 return 0;
1251 }
1252
1253 if (argc != 3) {
1254 printf("Invalid SET_NETWORK command: needs three arguments\n"
1255 "(network id, variable name, and value)\n");
1256 return -1;
1257 }
1258
1259 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1260 argv[0], argv[1], argv[2]);
1261 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1262 printf("Too long SET_NETWORK command.\n");
1263 return -1;
1264 }
1265 return wpa_ctrl_command(ctrl, cmd);
1266}
1267
1268
1269static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1270 char *argv[])
1271{
1272 char cmd[256];
1273 int res;
1274
1275 if (argc == 0) {
1276 wpa_cli_show_network_variables();
1277 return 0;
1278 }
1279
1280 if (argc != 2) {
1281 printf("Invalid GET_NETWORK command: needs two arguments\n"
1282 "(network id and variable name)\n");
1283 return -1;
1284 }
1285
1286 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1287 argv[0], argv[1]);
1288 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1289 printf("Too long GET_NETWORK command.\n");
1290 return -1;
1291 }
1292 return wpa_ctrl_command(ctrl, cmd);
1293}
1294
1295
1296static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1297 char *argv[])
1298{
1299 return wpa_ctrl_command(ctrl, "DISCONNECT");
1300}
1301
1302
1303static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1304 char *argv[])
1305{
1306 return wpa_ctrl_command(ctrl, "RECONNECT");
1307}
1308
1309
1310static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1311 char *argv[])
1312{
1313 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1314}
1315
1316
1317static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1318{
1319 return wpa_ctrl_command(ctrl, "SCAN");
1320}
1321
1322
1323static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1324 char *argv[])
1325{
1326 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1327}
1328
1329
1330static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1331{
1332 char cmd[64];
1333 int res;
1334
1335 if (argc != 1) {
1336 printf("Invalid BSS command: need one argument (index or "
1337 "BSSID)\n");
1338 return -1;
1339 }
1340
1341 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1342 if (res < 0 || (size_t) res >= sizeof(cmd))
1343 return -1;
1344 cmd[sizeof(cmd) - 1] = '\0';
1345
1346 return wpa_ctrl_command(ctrl, cmd);
1347}
1348
1349
1350static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1351 char *argv[])
1352{
1353 char cmd[64];
1354 int res;
1355
1356 if (argc < 1 || argc > 2) {
1357 printf("Invalid GET_CAPABILITY command: need either one or "
1358 "two arguments\n");
1359 return -1;
1360 }
1361
1362 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1363 printf("Invalid GET_CAPABILITY command: second argument, "
1364 "if any, must be 'strict'\n");
1365 return -1;
1366 }
1367
1368 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1369 (argc == 2) ? " strict" : "");
1370 if (res < 0 || (size_t) res >= sizeof(cmd))
1371 return -1;
1372 cmd[sizeof(cmd) - 1] = '\0';
1373
1374 return wpa_ctrl_command(ctrl, cmd);
1375}
1376
1377
1378static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1379{
1380 printf("Available interfaces:\n");
1381 return wpa_ctrl_command(ctrl, "INTERFACES");
1382}
1383
1384
1385static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1386{
1387 if (argc < 1) {
1388 wpa_cli_list_interfaces(ctrl);
1389 return 0;
1390 }
1391
1392 wpa_cli_close_connection();
1393 os_free(ctrl_ifname);
1394 ctrl_ifname = os_strdup(argv[0]);
1395
4a3ade4e 1396 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
6fc6879b 1397 printf("Connected to interface '%s.\n", ctrl_ifname);
6fc6879b
JM
1398 } else {
1399 printf("Could not connect to interface '%s' - re-trying\n",
1400 ctrl_ifname);
1401 }
1402 return 0;
1403}
1404
1405
1406static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1407 char *argv[])
1408{
1409 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1410}
1411
1412
1413static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1414 char *argv[])
1415{
1416 return wpa_ctrl_command(ctrl, "TERMINATE");
1417}
1418
1419
1420static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1421 char *argv[])
1422{
1423 char cmd[256];
1424 int res;
1425
1426 if (argc < 1) {
1427 printf("Invalid INTERFACE_ADD command: needs at least one "
1428 "argument (interface name)\n"
1429 "All arguments: ifname confname driver ctrl_interface "
1430 "driver_param bridge_name\n");
1431 return -1;
1432 }
1433
1434 /*
1435 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1436 * <driver_param>TAB<bridge_name>
1437 */
1438 res = os_snprintf(cmd, sizeof(cmd),
1439 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1440 argv[0],
1441 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1442 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1443 argc > 5 ? argv[5] : "");
1444 if (res < 0 || (size_t) res >= sizeof(cmd))
1445 return -1;
1446 cmd[sizeof(cmd) - 1] = '\0';
1447 return wpa_ctrl_command(ctrl, cmd);
1448}
1449
1450
1451static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1452 char *argv[])
1453{
1454 char cmd[128];
1455 int res;
1456
1457 if (argc != 1) {
1458 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1459 "(interface name)\n");
1460 return -1;
1461 }
1462
1463 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1464 if (res < 0 || (size_t) res >= sizeof(cmd))
1465 return -1;
1466 cmd[sizeof(cmd) - 1] = '\0';
1467 return wpa_ctrl_command(ctrl, cmd);
1468}
1469
1470
4b4a8ae5
JM
1471static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1472 char *argv[])
1473{
1474 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1475}
1476
1477
e653b622
JM
1478#ifdef CONFIG_AP
1479static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1480{
1481 char buf[64];
1482 if (argc != 1) {
1483 printf("Invalid 'sta' command - exactly one argument, STA "
1484 "address, is required.\n");
1485 return -1;
1486 }
e824cc46 1487 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
e653b622
JM
1488 return wpa_ctrl_command(ctrl, buf);
1489}
1490
1491
1492static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1493 char *addr, size_t addr_len)
1494{
1495 char buf[4096], *pos;
1496 size_t len;
1497 int ret;
1498
1499 if (ctrl_conn == NULL) {
1500 printf("Not connected to hostapd - command dropped.\n");
1501 return -1;
1502 }
1503 len = sizeof(buf) - 1;
1504 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1505 wpa_cli_msg_cb);
1506 if (ret == -2) {
1507 printf("'%s' command timed out.\n", cmd);
1508 return -2;
1509 } else if (ret < 0) {
1510 printf("'%s' command failed.\n", cmd);
1511 return -1;
1512 }
1513
1514 buf[len] = '\0';
1515 if (memcmp(buf, "FAIL", 4) == 0)
1516 return -1;
1517 printf("%s", buf);
1518
1519 pos = buf;
1520 while (*pos != '\0' && *pos != '\n')
1521 pos++;
1522 *pos = '\0';
1523 os_strlcpy(addr, buf, addr_len);
1524 return 0;
1525}
1526
1527
1528static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1529{
1530 char addr[32], cmd[64];
1531
1532 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1533 return 0;
1534 do {
e824cc46 1535 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
e653b622
JM
1536 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1537
1538 return -1;
1539}
1540#endif /* CONFIG_AP */
1541
1542
207ef3fb
JM
1543static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1544{
1545 return wpa_ctrl_command(ctrl, "SUSPEND");
1546}
1547
1548
1549static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1550{
1551 return wpa_ctrl_command(ctrl, "RESUME");
1552}
1553
1554
32d5295f
JM
1555static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1556{
1557 return wpa_ctrl_command(ctrl, "DROP_SA");
1558}
1559
1560
86d4f806
JM
1561static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1562{
1563 char cmd[128];
1564 int res;
1565
1566 if (argc != 1) {
1567 printf("Invalid ROAM command: needs one argument "
1568 "(target AP's BSSID)\n");
1569 return -1;
1570 }
1571
1572 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1573 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1574 printf("Too long ROAM command.\n");
1575 return -1;
1576 }
1577 return wpa_ctrl_command(ctrl, cmd);
1578}
1579
1580
57faa1ce
JM
1581#ifdef CONFIG_P2P
1582
1583static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1584{
1585 char cmd[128];
1586 int res;
1587
1588 if (argc == 0)
1589 return wpa_ctrl_command(ctrl, "P2P_FIND");
1590
1591 if (argc > 1)
1592 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1593 argv[0], argv[1]);
1594 else
1595 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
1596 if (res < 0 || (size_t) res >= sizeof(cmd))
1597 return -1;
1598 cmd[sizeof(cmd) - 1] = '\0';
1599 return wpa_ctrl_command(ctrl, cmd);
1600}
1601
1602
1603static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1604 char *argv[])
1605{
1606 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1607}
1608
1609
1610static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1611 char *argv[])
1612{
1613 char cmd[128];
1614 int res;
1615
1616 if (argc < 2) {
1617 printf("Invalid P2P_CONNECT command: needs at least two "
1618 "arguments (address and pbc/PIN)\n");
1619 return -1;
1620 }
1621
1622 if (argc > 4)
1623 res = os_snprintf(cmd, sizeof(cmd),
1624 "P2P_CONNECT %s %s %s %s %s",
1625 argv[0], argv[1], argv[2], argv[3],
1626 argv[4]);
1627 else if (argc > 3)
1628 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1629 argv[0], argv[1], argv[2], argv[3]);
1630 else if (argc > 2)
1631 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1632 argv[0], argv[1], argv[2]);
1633 else
1634 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1635 argv[0], argv[1]);
1636 if (res < 0 || (size_t) res >= sizeof(cmd))
1637 return -1;
1638 cmd[sizeof(cmd) - 1] = '\0';
1639 return wpa_ctrl_command(ctrl, cmd);
1640}
1641
1642
1643static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1644 char *argv[])
1645{
1646 char cmd[128];
1647 int res;
1648
1649 if (argc == 0)
1650 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
1651
1652 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %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_group_remove(struct wpa_ctrl *ctrl, int argc,
1661 char *argv[])
1662{
1663 char cmd[128];
1664 int res;
1665
1666 if (argc != 1) {
1667 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
1668 "(interface name)\n");
1669 return -1;
1670 }
1671
1672 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
1673 if (res < 0 || (size_t) res >= sizeof(cmd))
1674 return -1;
1675 cmd[sizeof(cmd) - 1] = '\0';
1676 return wpa_ctrl_command(ctrl, cmd);
1677}
1678
1679
1680static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1681 char *argv[])
1682{
1683 char cmd[128];
1684 int res;
1685
1686 if (argc == 0)
1687 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
1688
1689 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s", argv[0]);
1690 if (res < 0 || (size_t) res >= sizeof(cmd))
1691 return -1;
1692 cmd[sizeof(cmd) - 1] = '\0';
1693 return wpa_ctrl_command(ctrl, cmd);
1694}
1695
1696
1697static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1698 char *argv[])
1699{
1700 char cmd[128];
1701 int res;
1702
1703 if (argc != 2) {
1704 printf("Invalid P2P_PROV_DISC command: needs two arguments "
1705 "(address and config method\n"
1706 "(display, keypad, or pbc)\n");
1707 return -1;
1708 }
1709
1710 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
1711 argv[0], argv[1]);
1712 if (res < 0 || (size_t) res >= sizeof(cmd))
1713 return -1;
1714 cmd[sizeof(cmd) - 1] = '\0';
1715 return wpa_ctrl_command(ctrl, cmd);
1716}
1717
1718
1719static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1720 char *argv[])
1721{
1722 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1723}
1724
1725
1726static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1727 char *argv[])
1728{
1729 char cmd[4096];
1730 int res;
1731
1732 if (argc != 2 && argc != 4) {
1733 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1734 "arguments (address and TLVs) or four arguments "
1735 "(address, \"upnp\", version, search target "
1736 "(SSDP ST:)\n");
1737 return -1;
1738 }
1739
1740 if (argc == 4)
1741 res = os_snprintf(cmd, sizeof(cmd),
1742 "P2P_SERV_DISC_REQ %s %s %s %s",
1743 argv[0], argv[1], argv[2], argv[3]);
1744 else
1745 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
1746 argv[0], argv[1]);
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_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1755 int argc, char *argv[])
1756{
1757 char cmd[128];
1758 int res;
1759
1760 if (argc != 1) {
1761 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
1762 "argument (pending request identifier)\n");
1763 return -1;
1764 }
1765
1766 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
1767 argv[0]);
1768 if (res < 0 || (size_t) res >= sizeof(cmd))
1769 return -1;
1770 cmd[sizeof(cmd) - 1] = '\0';
1771 return wpa_ctrl_command(ctrl, cmd);
1772}
1773
1774
1775static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1776 char *argv[])
1777{
1778 char cmd[4096];
1779 int res;
1780
1781 if (argc != 4) {
1782 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1783 "arguments (freq, address, dialog token, and TLVs)\n");
1784 return -1;
1785 }
1786
1787 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1788 argv[0], argv[1], argv[2], argv[3]);
1789 if (res < 0 || (size_t) res >= sizeof(cmd))
1790 return -1;
1791 cmd[sizeof(cmd) - 1] = '\0';
1792 return wpa_ctrl_command(ctrl, cmd);
1793}
1794
1795
1796static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1797 char *argv[])
1798{
1799 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1800}
1801
1802
1803static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1804 int argc, char *argv[])
1805{
1806 char cmd[128];
1807 int res;
1808
1809 if (argc != 1) {
1810 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
1811 "argument (external processing: 0/1)\n");
1812 return -1;
1813 }
1814
1815 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
1816 argv[0]);
1817 if (res < 0 || (size_t) res >= sizeof(cmd))
1818 return -1;
1819 cmd[sizeof(cmd) - 1] = '\0';
1820 return wpa_ctrl_command(ctrl, cmd);
1821}
1822
1823
1824static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1825 char *argv[])
1826{
1827 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1828}
1829
1830
1831static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1832 char *argv[])
1833{
1834 char cmd[4096];
1835 int res;
1836
1837 if (argc != 3 && argc != 4) {
1838 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1839 "arguments\n");
1840 return -1;
1841 }
1842
1843 if (argc == 4)
1844 res = os_snprintf(cmd, sizeof(cmd),
1845 "P2P_SERVICE_ADD %s %s %s %s",
1846 argv[0], argv[1], argv[2], argv[3]);
1847 else
1848 res = os_snprintf(cmd, sizeof(cmd),
1849 "P2P_SERVICE_ADD %s %s %s",
1850 argv[0], argv[1], argv[2]);
1851 if (res < 0 || (size_t) res >= sizeof(cmd))
1852 return -1;
1853 cmd[sizeof(cmd) - 1] = '\0';
1854 return wpa_ctrl_command(ctrl, cmd);
1855}
1856
1857
1858static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1859 char *argv[])
1860{
1861 char cmd[4096];
1862 int res;
1863
1864 if (argc != 2 && argc != 3) {
1865 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1866 "arguments\n");
1867 return -1;
1868 }
1869
1870 if (argc == 3)
1871 res = os_snprintf(cmd, sizeof(cmd),
1872 "P2P_SERVICE_DEL %s %s %s",
1873 argv[0], argv[1], argv[2]);
1874 else
1875 res = os_snprintf(cmd, sizeof(cmd),
1876 "P2P_SERVICE_DEL %s %s",
1877 argv[0], argv[1]);
1878 if (res < 0 || (size_t) res >= sizeof(cmd))
1879 return -1;
1880 cmd[sizeof(cmd) - 1] = '\0';
1881 return wpa_ctrl_command(ctrl, cmd);
1882}
1883
1884
1885static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1886 int argc, char *argv[])
1887{
1888 char cmd[128];
1889 int res;
1890
1891 if (argc != 1) {
1892 printf("Invalid P2P_REJECT command: needs one argument "
1893 "(peer address)\n");
1894 return -1;
1895 }
1896
1897 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
1898 if (res < 0 || (size_t) res >= sizeof(cmd))
1899 return -1;
1900 cmd[sizeof(cmd) - 1] = '\0';
1901 return wpa_ctrl_command(ctrl, cmd);
1902}
1903
1904
1905static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1906 int argc, char *argv[])
1907{
1908 char cmd[128];
1909 int res;
1910
1911 if (argc < 1) {
1912 printf("Invalid P2P_INVITE command: needs at least one "
1913 "argument\n");
1914 return -1;
1915 }
1916
1917 if (argc > 2)
1918 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
1919 argv[0], argv[1], argv[2]);
1920 else if (argc > 1)
1921 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
1922 argv[0], argv[1]);
1923 else
1924 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
1925 if (res < 0 || (size_t) res >= sizeof(cmd))
1926 return -1;
1927 cmd[sizeof(cmd) - 1] = '\0';
1928 return wpa_ctrl_command(ctrl, cmd);
1929}
1930
1931
1932static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1933{
1934 char buf[64];
1935 if (argc != 1) {
1936 printf("Invalid 'p2p_peer' command - exactly one argument, "
1937 "P2P peer device address, is required.\n");
1938 return -1;
1939 }
1940 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
1941 return wpa_ctrl_command(ctrl, buf);
1942}
1943
1944
1945static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1946 char *addr, size_t addr_len,
1947 int discovered)
1948{
1949 char buf[4096], *pos;
1950 size_t len;
1951 int ret;
1952
1953 if (ctrl_conn == NULL)
1954 return -1;
1955 len = sizeof(buf) - 1;
1956 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1957 wpa_cli_msg_cb);
1958 if (ret == -2) {
1959 printf("'%s' command timed out.\n", cmd);
1960 return -2;
1961 } else if (ret < 0) {
1962 printf("'%s' command failed.\n", cmd);
1963 return -1;
1964 }
1965
1966 buf[len] = '\0';
1967 if (memcmp(buf, "FAIL", 4) == 0)
1968 return -1;
1969
1970 pos = buf;
1971 while (*pos != '\0' && *pos != '\n')
1972 pos++;
1973 *pos++ = '\0';
1974 os_strlcpy(addr, buf, addr_len);
1975 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
1976 printf("%s\n", addr);
1977 return 0;
1978}
1979
1980
1981static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
1982{
1983 char addr[32], cmd[64];
1984 int discovered;
1985
1986 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
1987
1988 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
1989 addr, sizeof(addr), discovered))
1990 return 0;
1991 do {
1992 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
1993 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
1994 discovered) == 0);
1995
1996 return -1;
1997}
1998
1999
2000static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2001{
2002 char cmd[100];
2003 int res;
2004
2005 if (argc != 2) {
2006 printf("Invalid P2P_SET command: needs two arguments (field, "
2007 "value)\n");
2008 return -1;
2009 }
2010
2011 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2012 if (res < 0 || (size_t) res >= sizeof(cmd))
2013 return -1;
2014 cmd[sizeof(cmd) - 1] = '\0';
2015 return wpa_ctrl_command(ctrl, cmd);
2016}
2017
2018
2019static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2020{
2021 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2022}
2023
2024
2025static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2026 char *argv[])
2027{
2028 char cmd[100];
2029 int res;
2030
2031 if (argc != 0 && argc != 2 && argc != 4) {
2032 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2033 "(preferred duration, interval; in microsecods).\n"
2034 "Optional second pair can be used to provide "
2035 "acceptable values.\n");
2036 return -1;
2037 }
2038
2039 if (argc == 4)
2040 res = os_snprintf(cmd, sizeof(cmd),
2041 "P2P_PRESENCE_REQ %s %s %s %s",
2042 argv[0], argv[1], argv[2], argv[3]);
2043 else if (argc == 2)
2044 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2045 argv[0], argv[1]);
2046 else
2047 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2048 if (res < 0 || (size_t) res >= sizeof(cmd))
2049 return -1;
2050 cmd[sizeof(cmd) - 1] = '\0';
2051 return wpa_ctrl_command(ctrl, cmd);
2052}
2053
2054
2055static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2056 char *argv[])
2057{
2058 char cmd[100];
2059 int res;
2060
2061 if (argc != 0 && argc != 2) {
2062 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2063 "(availability period, availability interval; in "
2064 "millisecods).\n"
2065 "Extended Listen Timing can be cancelled with this "
2066 "command when used without parameters.\n");
2067 return -1;
2068 }
2069
2070 if (argc == 2)
2071 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2072 argv[0], argv[1]);
2073 else
2074 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2075 if (res < 0 || (size_t) res >= sizeof(cmd))
2076 return -1;
2077 cmd[sizeof(cmd) - 1] = '\0';
2078 return wpa_ctrl_command(ctrl, cmd);
2079}
2080
2081#endif /* CONFIG_P2P */
2082
2083
40fd868c
ER
2084enum wpa_cli_cmd_flags {
2085 cli_cmd_flag_none = 0x00,
2086 cli_cmd_flag_sensitive = 0x01
2087};
2088
6fc6879b
JM
2089struct wpa_cli_cmd {
2090 const char *cmd;
2091 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 2092 enum wpa_cli_cmd_flags flags;
dfa141b1 2093 const char *usage;
6fc6879b
JM
2094};
2095
2096static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 2097 { "status", wpa_cli_cmd_status,
dfa141b1
ER
2098 cli_cmd_flag_none,
2099 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 2100 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
2101 cli_cmd_flag_none,
2102 "= pings wpa_supplicant" },
77895cd9
JM
2103 { "note", wpa_cli_cmd_note,
2104 cli_cmd_flag_none,
2105 "<text> = add a note to wpa_supplicant debug log" },
40fd868c 2106 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
2107 cli_cmd_flag_none,
2108 "= get MIB variables (dot1x, dot11)" },
40fd868c 2109 { "help", wpa_cli_cmd_help,
dfa141b1
ER
2110 cli_cmd_flag_none,
2111 "= show this usage help" },
40fd868c 2112 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
2113 cli_cmd_flag_none,
2114 "[ifname] = show interfaces/select interface" },
40fd868c 2115 { "level", wpa_cli_cmd_level,
dfa141b1
ER
2116 cli_cmd_flag_none,
2117 "<debug level> = change debug level" },
40fd868c 2118 { "license", wpa_cli_cmd_license,
dfa141b1
ER
2119 cli_cmd_flag_none,
2120 "= show full wpa_cli license" },
40fd868c 2121 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
2122 cli_cmd_flag_none,
2123 "= exit wpa_cli" },
40fd868c 2124 { "set", wpa_cli_cmd_set,
dfa141b1
ER
2125 cli_cmd_flag_none,
2126 "= set variables (shows list of variables when run without "
2127 "arguments)" },
40fd868c 2128 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
2129 cli_cmd_flag_none,
2130 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 2131 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
2132 cli_cmd_flag_none,
2133 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 2134 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
2135 cli_cmd_flag_none,
2136 "= show PMKSA cache" },
40fd868c 2137 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
2138 cli_cmd_flag_none,
2139 "= force reassociation" },
40fd868c 2140 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
2141 cli_cmd_flag_none,
2142 "<BSSID> = force preauthentication" },
40fd868c 2143 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
2144 cli_cmd_flag_none,
2145 "<network id> <identity> = configure identity for an SSID" },
40fd868c 2146 { "password", wpa_cli_cmd_password,
dfa141b1
ER
2147 cli_cmd_flag_sensitive,
2148 "<network id> <password> = configure password for an SSID" },
40fd868c 2149 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
2150 cli_cmd_flag_sensitive,
2151 "<network id> <password> = change password for an SSID" },
40fd868c 2152 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
2153 cli_cmd_flag_sensitive,
2154 "<network id> <pin> = configure pin for an SSID" },
40fd868c 2155 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
2156 cli_cmd_flag_sensitive,
2157 "<network id> <password> = configure one-time-password for an SSID"
2158 },
40fd868c 2159 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
2160 cli_cmd_flag_sensitive,
2161 "<network id> <passphrase> = configure private key passphrase\n"
2162 " for an SSID" },
40fd868c 2163 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
2164 cli_cmd_flag_none,
2165 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 2166 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
2167 cli_cmd_flag_none,
2168 "= list configured networks" },
40fd868c 2169 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
2170 cli_cmd_flag_none,
2171 "<network id> = select a network (disable others)" },
40fd868c 2172 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
2173 cli_cmd_flag_none,
2174 "<network id> = enable a network" },
40fd868c 2175 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
2176 cli_cmd_flag_none,
2177 "<network id> = disable a network" },
40fd868c 2178 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
2179 cli_cmd_flag_none,
2180 "= add a network" },
40fd868c 2181 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
2182 cli_cmd_flag_none,
2183 "<network id> = remove a network" },
40fd868c 2184 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
2185 cli_cmd_flag_sensitive,
2186 "<network id> <variable> <value> = set network variables (shows\n"
2187 " list of variables when run without arguments)" },
40fd868c 2188 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
2189 cli_cmd_flag_none,
2190 "<network id> <variable> = get network variables" },
40fd868c 2191 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
2192 cli_cmd_flag_none,
2193 "= save the current configuration" },
40fd868c 2194 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
2195 cli_cmd_flag_none,
2196 "= disconnect and wait for reassociate/reconnect command before\n"
2197 " connecting" },
40fd868c 2198 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
2199 cli_cmd_flag_none,
2200 "= like reassociate, but only takes effect if already disconnected"
2201 },
40fd868c 2202 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
2203 cli_cmd_flag_none,
2204 "= request new BSS scan" },
40fd868c 2205 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
2206 cli_cmd_flag_none,
2207 "= get latest scan results" },
40fd868c 2208 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
2209 cli_cmd_flag_none,
2210 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 2211 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
2212 cli_cmd_flag_none,
2213 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 2214 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
2215 cli_cmd_flag_none,
2216 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 2217 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
2218 cli_cmd_flag_none,
2219 "= terminate wpa_supplicant" },
40fd868c 2220 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
2221 cli_cmd_flag_none,
2222 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2223 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2224 " are optional" },
40fd868c 2225 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
2226 cli_cmd_flag_none,
2227 "<ifname> = removes the interface" },
40fd868c 2228 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
2229 cli_cmd_flag_none,
2230 "= list available interfaces" },
40fd868c 2231 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
2232 cli_cmd_flag_none,
2233 "<value> = set ap_scan parameter" },
40fd868c 2234 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
2235 cli_cmd_flag_none,
2236 "<addr> = request STK negotiation with <addr>" },
40fd868c 2237 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
2238 cli_cmd_flag_none,
2239 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 2240 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
2241 cli_cmd_flag_none,
2242 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 2243 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
2244 cli_cmd_flag_sensitive,
2245 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2246 "hardcoded)" },
116f7bb0 2247#ifdef CONFIG_WPS_OOB
46bdb83a
MH
2248 { "wps_oob", wpa_cli_cmd_wps_oob,
2249 cli_cmd_flag_sensitive,
e1ee6b60 2250 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 2251#endif /* CONFIG_WPS_OOB */
40fd868c 2252 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
2253 cli_cmd_flag_sensitive,
2254 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
e9bcfebf
JM
2255 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2256 cli_cmd_flag_none,
08486685 2257 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
e9bcfebf
JM
2258 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2259 cli_cmd_flag_none,
2260 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
2261 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2262 cli_cmd_flag_sensitive,
2263 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
2264 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2265 cli_cmd_flag_none,
2266 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
2267 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2268 cli_cmd_flag_sensitive,
2269 "<UUID> <PIN> = learn AP configuration" },
7d6640a6
JM
2270 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2271 cli_cmd_flag_sensitive,
2272 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
11ef8d35
JM
2273 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2274 cli_cmd_flag_none,
2275 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
2276#ifdef CONFIG_AP
2277 { "sta", wpa_cli_cmd_sta,
2278 cli_cmd_flag_none,
2279 "<addr> = get information about an associated station (AP)" },
2280 { "all_sta", wpa_cli_cmd_all_sta,
2281 cli_cmd_flag_none,
2282 "= get information about all associated stations (AP)" },
2283#endif /* CONFIG_AP */
207ef3fb
JM
2284 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2285 "= notification of suspend/hibernate" },
2286 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2287 "= notification of resume/thaw" },
32d5295f
JM
2288 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2289 "= drop SA without deauth/disassoc (test command)" },
86d4f806
JM
2290 { "roam", wpa_cli_cmd_roam,
2291 cli_cmd_flag_none,
2292 "<addr> = roam to the specified BSS" },
57faa1ce
JM
2293#ifdef CONFIG_P2P
2294 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2295 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2296 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2297 "= stop P2P Devices search" },
2298 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2299 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2300 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2301 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2302 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2303 "<ifname> = remote P2P group interface (terminate group if GO)" },
2304 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2305 "= add a new P2P group (local end as GO)" },
2306 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2307 "<addr> <method> = request provisioning discovery" },
2308 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2309 cli_cmd_flag_none,
2310 "= get the passphrase for a group (GO only)" },
2311 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2312 cli_cmd_flag_none,
2313 "<addr> <TLVs> = schedule service discovery request" },
2314 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2315 cli_cmd_flag_none,
2316 "<id> = cancel pending service discovery request" },
2317 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2318 cli_cmd_flag_none,
2319 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2320 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2321 cli_cmd_flag_none,
2322 "= indicate change in local services" },
2323 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2324 cli_cmd_flag_none,
2325 "<external> = set external processing of service discovery" },
2326 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2327 cli_cmd_flag_none,
2328 "= remove all stored service entries" },
2329 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2330 cli_cmd_flag_none,
2331 "<bonjour|upnp> <query|version> <response|service> = add a local "
2332 "service" },
2333 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2334 cli_cmd_flag_none,
2335 "<bonjour|upnp> <query|version> [|service] = remove a local "
2336 "service" },
2337 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2338 cli_cmd_flag_none,
2339 "<addr> = reject connection attempts from a specific peer" },
2340 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2341 cli_cmd_flag_none,
2342 "<cmd> [peer=addr] = invite peer" },
2343 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2344 "[discovered] = list known (optionally, only fully discovered) P2P "
2345 "peers" },
2346 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2347 "<address> = show information about known P2P peer" },
2348 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2349 "<field> <value> = set a P2P parameter" },
2350 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2351 "= flush P2P state" },
2352 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2353 "[<duration> <interval>] [<duration> <interval>] = request GO "
2354 "presence" },
2355 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2356 "[<period> <interval>] = set extended listen timing" },
2357#endif /* CONFIG_P2P */
dfa141b1 2358 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
2359};
2360
2361
dfa141b1
ER
2362/*
2363 * Prints command usage, lines are padded with the specified string.
2364 */
2365static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2366{
2367 char c;
2368 size_t n;
2369
2370 printf("%s%s ", pad, cmd->cmd);
2371 for (n = 0; (c = cmd->usage[n]); n++) {
2372 printf("%c", c);
2373 if (c == '\n')
2374 printf("%s", pad);
2375 }
2376 printf("\n");
2377}
2378
2379
2380static void print_help(void)
2381{
2382 int n;
2383 printf("commands:\n");
2384 for (n = 0; wpa_cli_commands[n].cmd; n++)
2385 print_cmd_help(&wpa_cli_commands[n], " ");
2386}
2387
2388
40fd868c
ER
2389#ifdef CONFIG_READLINE
2390static int cmd_has_sensitive_data(const char *cmd)
2391{
2392 const char *c, *delim;
2393 int n;
2394 size_t len;
2395
2396 delim = os_strchr(cmd, ' ');
2397 if (delim)
2398 len = delim - cmd;
2399 else
2400 len = os_strlen(cmd);
2401
2402 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2403 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2404 return (wpa_cli_commands[n].flags &
2405 cli_cmd_flag_sensitive);
2406 }
2407 return 0;
2408}
2409#endif /* CONFIG_READLINE */
2410
2411
6fc6879b
JM
2412static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2413{
2414 struct wpa_cli_cmd *cmd, *match = NULL;
2415 int count;
2416 int ret = 0;
2417
2418 count = 0;
2419 cmd = wpa_cli_commands;
2420 while (cmd->cmd) {
2421 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2422 {
2423 match = cmd;
2424 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2425 /* we have an exact match */
2426 count = 1;
2427 break;
2428 }
2429 count++;
2430 }
2431 cmd++;
2432 }
2433
2434 if (count > 1) {
2435 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2436 cmd = wpa_cli_commands;
2437 while (cmd->cmd) {
2438 if (os_strncasecmp(cmd->cmd, argv[0],
2439 os_strlen(argv[0])) == 0) {
2440 printf(" %s", cmd->cmd);
2441 }
2442 cmd++;
2443 }
2444 printf("\n");
2445 ret = 1;
2446 } else if (count == 0) {
2447 printf("Unknown command '%s'\n", argv[0]);
2448 ret = 1;
2449 } else {
2450 ret = match->handler(ctrl, argc - 1, &argv[1]);
2451 }
2452
2453 return ret;
2454}
2455
2456
2457static int str_match(const char *a, const char *b)
2458{
2459 return os_strncmp(a, b, os_strlen(b)) == 0;
2460}
2461
2462
2463static int wpa_cli_exec(const char *program, const char *arg1,
2464 const char *arg2)
2465{
2466 char *cmd;
2467 size_t len;
2468 int res;
308a4ec8 2469 int ret = 0;
6fc6879b
JM
2470
2471 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2472 cmd = os_malloc(len);
2473 if (cmd == NULL)
2474 return -1;
2475 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2476 if (res < 0 || (size_t) res >= len) {
2477 os_free(cmd);
2478 return -1;
2479 }
2480 cmd[len - 1] = '\0';
2481#ifndef _WIN32_WCE
308a4ec8
JM
2482 if (system(cmd) < 0)
2483 ret = -1;
6fc6879b
JM
2484#endif /* _WIN32_WCE */
2485 os_free(cmd);
2486
308a4ec8 2487 return ret;
6fc6879b
JM
2488}
2489
2490
2491static void wpa_cli_action_process(const char *msg)
2492{
2493 const char *pos;
2494 char *copy = NULL, *id, *pos2;
2495
2496 pos = msg;
2497 if (*pos == '<') {
2498 /* skip priority */
2499 pos = os_strchr(pos, '>');
2500 if (pos)
2501 pos++;
2502 else
2503 pos = msg;
2504 }
2505
2506 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2507 int new_id = -1;
2508 os_unsetenv("WPA_ID");
2509 os_unsetenv("WPA_ID_STR");
2510 os_unsetenv("WPA_CTRL_DIR");
2511
2512 pos = os_strstr(pos, "[id=");
2513 if (pos)
2514 copy = os_strdup(pos + 4);
2515
2516 if (copy) {
2517 pos2 = id = copy;
2518 while (*pos2 && *pos2 != ' ')
2519 pos2++;
2520 *pos2++ = '\0';
2521 new_id = atoi(id);
2522 os_setenv("WPA_ID", id, 1);
2523 while (*pos2 && *pos2 != '=')
2524 pos2++;
2525 if (*pos2 == '=')
2526 pos2++;
2527 id = pos2;
2528 while (*pos2 && *pos2 != ']')
2529 pos2++;
2530 *pos2 = '\0';
2531 os_setenv("WPA_ID_STR", id, 1);
2532 os_free(copy);
2533 }
2534
2535 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2536
2537 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2538 wpa_cli_connected = 1;
2539 wpa_cli_last_id = new_id;
2540 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2541 }
2542 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2543 if (wpa_cli_connected) {
2544 wpa_cli_connected = 0;
2545 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2546 }
42f0101b
JM
2547 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2548 wpa_cli_exec(action_file, ctrl_ifname, pos);
2549 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2550 wpa_cli_exec(action_file, ctrl_ifname, pos);
72044390
JM
2551 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2552 wpa_cli_exec(action_file, ctrl_ifname, pos);
2553 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2554 wpa_cli_exec(action_file, ctrl_ifname, pos);
6fc6879b
JM
2555 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2556 printf("wpa_supplicant is terminating - stop monitoring\n");
2557 wpa_cli_quit = 1;
2558 }
2559}
2560
2561
2562#ifndef CONFIG_ANSI_C_EXTRA
2563static void wpa_cli_action_cb(char *msg, size_t len)
2564{
2565 wpa_cli_action_process(msg);
2566}
2567#endif /* CONFIG_ANSI_C_EXTRA */
2568
2569
2570static void wpa_cli_reconnect(void)
2571{
2572 wpa_cli_close_connection();
4a3ade4e 2573 wpa_cli_open_connection(ctrl_ifname, 1);
6fc6879b
JM
2574}
2575
2576
2577static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
2578 int action_monitor)
2579{
2580 int first = 1;
2581 if (ctrl_conn == NULL) {
2582 wpa_cli_reconnect();
2583 return;
2584 }
2585 while (wpa_ctrl_pending(ctrl) > 0) {
2586 char buf[256];
2587 size_t len = sizeof(buf) - 1;
2588 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2589 buf[len] = '\0';
2590 if (action_monitor)
2591 wpa_cli_action_process(buf);
2592 else {
f3f0f648
JM
2593 if (wpa_cli_show_event(buf)) {
2594 if (in_read && first)
2595 printf("\r");
2596 first = 0;
2597 printf("%s\n", buf);
2598 readline_redraw();
2599 }
6fc6879b
JM
2600 }
2601 } else {
2602 printf("Could not read pending message.\n");
2603 break;
2604 }
2605 }
2606
2607 if (wpa_ctrl_pending(ctrl) < 0) {
2608 printf("Connection to wpa_supplicant lost - trying to "
2609 "reconnect\n");
2610 wpa_cli_reconnect();
2611 }
2612}
2613
2614
2615#ifdef CONFIG_READLINE
2616static char * wpa_cli_cmd_gen(const char *text, int state)
2617{
2618 static int i, len;
2619 const char *cmd;
2620
2621 if (state == 0) {
2622 i = 0;
2623 len = os_strlen(text);
2624 }
2625
2626 while ((cmd = wpa_cli_commands[i].cmd)) {
2627 i++;
2628 if (os_strncasecmp(cmd, text, len) == 0)
d566f415 2629 return strdup(cmd);
6fc6879b
JM
2630 }
2631
2632 return NULL;
2633}
2634
2635
2636static char * wpa_cli_dummy_gen(const char *text, int state)
2637{
a7918ec7
JM
2638 int i;
2639
2640 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2641 const char *cmd = wpa_cli_commands[i].cmd;
2642 size_t len = os_strlen(cmd);
2643 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
2644 rl_line_buffer[len] == ' ') {
2645 printf("\n%s\n", wpa_cli_commands[i].usage);
f3f0f648 2646 readline_redraw();
a7918ec7
JM
2647 break;
2648 }
2649 }
2650
2651 rl_attempted_completion_over = 1;
2652 return NULL;
2653}
2654
2655
2656static char * wpa_cli_status_gen(const char *text, int state)
2657{
2658 static int i, len;
2659 char *options[] = {
2660 "verbose", NULL
2661 };
2662 char *t;
2663
2664 if (state == 0) {
2665 i = 0;
2666 len = os_strlen(text);
2667 }
2668
2669 while ((t = options[i])) {
2670 i++;
2671 if (os_strncasecmp(t, text, len) == 0)
2672 return strdup(t);
2673 }
2674
2675 rl_attempted_completion_over = 1;
6fc6879b
JM
2676 return NULL;
2677}
2678
2679
2680static char ** wpa_cli_completion(const char *text, int start, int end)
2681{
a7918ec7
JM
2682 char * (*func)(const char *text, int state);
2683
2684 if (start == 0)
2685 func = wpa_cli_cmd_gen;
2686 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
2687 func = wpa_cli_status_gen;
2688 else
2689 func = wpa_cli_dummy_gen;
2690 return rl_completion_matches(text, func);
6fc6879b
JM
2691}
2692#endif /* CONFIG_READLINE */
2693
2694
2695static void wpa_cli_interactive(void)
2696{
2697#define max_args 10
2698 char cmdbuf[256], *cmd, *argv[max_args], *pos;
2699 int argc;
2700#ifdef CONFIG_READLINE
2701 char *home, *hfile = NULL;
2702#endif /* CONFIG_READLINE */
2703
2704 printf("\nInteractive mode\n\n");
2705
2706#ifdef CONFIG_READLINE
2707 rl_attempted_completion_function = wpa_cli_completion;
2708 home = getenv("HOME");
2709 if (home) {
2710 const char *fname = ".wpa_cli_history";
2711 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2712 hfile = os_malloc(hfile_len);
2713 if (hfile) {
2714 int res;
2715 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2716 fname);
2717 if (res >= 0 && res < hfile_len) {
2718 hfile[hfile_len - 1] = '\0';
2719 read_history(hfile);
2720 stifle_history(100);
2721 }
2722 }
2723 }
2724#endif /* CONFIG_READLINE */
2725
2726 do {
4a3ade4e 2727 wpa_cli_recv_pending(mon_conn, 0, 0);
6fc6879b 2728#ifndef CONFIG_NATIVE_WINDOWS
1cc84c1c 2729 alarm(ping_interval);
6fc6879b 2730#endif /* CONFIG_NATIVE_WINDOWS */
dd63f314
JM
2731#ifdef CONFIG_WPA_CLI_FORK
2732 if (mon_pid)
2733 kill(mon_pid, SIGUSR1);
2734#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
2735#ifdef CONFIG_READLINE
2736 cmd = readline("> ");
2737 if (cmd && *cmd) {
2738 HIST_ENTRY *h;
2739 while (next_history())
2740 ;
2741 h = previous_history();
2742 if (h == NULL || os_strcmp(cmd, h->line) != 0)
2743 add_history(cmd);
2744 next_history();
2745 }
2746#else /* CONFIG_READLINE */
2747 printf("> ");
2748 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2749#endif /* CONFIG_READLINE */
2750#ifndef CONFIG_NATIVE_WINDOWS
2751 alarm(0);
2752#endif /* CONFIG_NATIVE_WINDOWS */
2753 if (cmd == NULL)
2754 break;
4a3ade4e 2755 wpa_cli_recv_pending(mon_conn, 0, 0);
6fc6879b
JM
2756 pos = cmd;
2757 while (*pos != '\0') {
2758 if (*pos == '\n') {
2759 *pos = '\0';
2760 break;
2761 }
2762 pos++;
2763 }
2764 argc = 0;
2765 pos = cmd;
2766 for (;;) {
2767 while (*pos == ' ')
2768 pos++;
2769 if (*pos == '\0')
2770 break;
2771 argv[argc] = pos;
2772 argc++;
2773 if (argc == max_args)
2774 break;
2775 if (*pos == '"') {
2776 char *pos2 = os_strrchr(pos, '"');
2777 if (pos2)
2778 pos = pos2 + 1;
2779 }
2780 while (*pos != '\0' && *pos != ' ')
2781 pos++;
2782 if (*pos == ' ')
2783 *pos++ = '\0';
2784 }
2785 if (argc)
2786 wpa_request(ctrl_conn, argc, argv);
2787
2788 if (cmd != cmdbuf)
a24eb842 2789 free(cmd);
dd63f314
JM
2790#ifdef CONFIG_WPA_CLI_FORK
2791 if (mon_pid)
2792 kill(mon_pid, SIGUSR2);
2793#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
2794 } while (!wpa_cli_quit);
2795
2796#ifdef CONFIG_READLINE
2797 if (hfile) {
2798 /* Save command history, excluding lines that may contain
2799 * passwords. */
2800 HIST_ENTRY *h;
2801 history_set_pos(0);
413653e8 2802 while ((h = current_history())) {
6fc6879b
JM
2803 char *p = h->line;
2804 while (*p == ' ' || *p == '\t')
2805 p++;
40fd868c 2806 if (cmd_has_sensitive_data(p)) {
6fc6879b
JM
2807 h = remove_history(where_history());
2808 if (h) {
2809 os_free(h->line);
2810 os_free(h->data);
2811 os_free(h);
413653e8
ER
2812 } else
2813 next_history();
2814 } else
2815 next_history();
6fc6879b
JM
2816 }
2817 write_history(hfile);
2818 os_free(hfile);
2819 }
2820#endif /* CONFIG_READLINE */
2821}
2822
2823
2824static void wpa_cli_action(struct wpa_ctrl *ctrl)
2825{
2826#ifdef CONFIG_ANSI_C_EXTRA
2827 /* TODO: ANSI C version(?) */
2828 printf("Action processing not supported in ANSI C build.\n");
2829#else /* CONFIG_ANSI_C_EXTRA */
2830 fd_set rfds;
2831 int fd, res;
2832 struct timeval tv;
2833 char buf[256]; /* note: large enough to fit in unsolicited messages */
2834 size_t len;
2835
2836 fd = wpa_ctrl_get_fd(ctrl);
2837
2838 while (!wpa_cli_quit) {
2839 FD_ZERO(&rfds);
2840 FD_SET(fd, &rfds);
1cc84c1c 2841 tv.tv_sec = ping_interval;
6fc6879b
JM
2842 tv.tv_usec = 0;
2843 res = select(fd + 1, &rfds, NULL, NULL, &tv);
2844 if (res < 0 && errno != EINTR) {
2845 perror("select");
2846 break;
2847 }
2848
2849 if (FD_ISSET(fd, &rfds))
2850 wpa_cli_recv_pending(ctrl, 0, 1);
2851 else {
2852 /* verify that connection is still working */
2853 len = sizeof(buf) - 1;
2854 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2855 wpa_cli_action_cb) < 0 ||
2856 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2857 printf("wpa_supplicant did not reply to PING "
2858 "command - exiting\n");
2859 break;
2860 }
2861 }
2862 }
2863#endif /* CONFIG_ANSI_C_EXTRA */
2864}
2865
2866
2867static void wpa_cli_cleanup(void)
2868{
2869 wpa_cli_close_connection();
2870 if (pid_file)
2871 os_daemonize_terminate(pid_file);
2872
2873 os_program_deinit();
2874}
2875
2876static void wpa_cli_terminate(int sig)
2877{
2878 wpa_cli_cleanup();
2879 exit(0);
2880}
2881
2882
dd63f314
JM
2883#ifdef CONFIG_WPA_CLI_FORK
2884static void wpa_cli_usr1(int sig)
2885{
f3f0f648 2886 readline_redraw();
dd63f314
JM
2887}
2888#endif /* CONFIG_WPA_CLI_FORK */
2889
2890
6fc6879b
JM
2891#ifndef CONFIG_NATIVE_WINDOWS
2892static void wpa_cli_alarm(int sig)
2893{
2894 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2895 printf("Connection to wpa_supplicant lost - trying to "
2896 "reconnect\n");
2897 wpa_cli_close_connection();
2898 }
2899 if (!ctrl_conn)
2900 wpa_cli_reconnect();
4a3ade4e
JM
2901 if (mon_conn)
2902 wpa_cli_recv_pending(mon_conn, 1, 0);
1cc84c1c 2903 alarm(ping_interval);
6fc6879b
JM
2904}
2905#endif /* CONFIG_NATIVE_WINDOWS */
2906
2907
2908static char * wpa_cli_get_default_ifname(void)
2909{
2910 char *ifname = NULL;
2911
2912#ifdef CONFIG_CTRL_IFACE_UNIX
2913 struct dirent *dent;
2914 DIR *dir = opendir(ctrl_iface_dir);
2915 if (!dir)
2916 return NULL;
2917 while ((dent = readdir(dir))) {
2918#ifdef _DIRENT_HAVE_D_TYPE
2919 /*
2920 * Skip the file if it is not a socket. Also accept
2921 * DT_UNKNOWN (0) in case the C library or underlying
2922 * file system does not support d_type.
2923 */
2924 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2925 continue;
2926#endif /* _DIRENT_HAVE_D_TYPE */
2927 if (os_strcmp(dent->d_name, ".") == 0 ||
2928 os_strcmp(dent->d_name, "..") == 0)
2929 continue;
2930 printf("Selected interface '%s'\n", dent->d_name);
2931 ifname = os_strdup(dent->d_name);
2932 break;
2933 }
2934 closedir(dir);
2935#endif /* CONFIG_CTRL_IFACE_UNIX */
2936
2937#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2938 char buf[2048], *pos;
2939 size_t len;
2940 struct wpa_ctrl *ctrl;
2941 int ret;
2942
2943 ctrl = wpa_ctrl_open(NULL);
2944 if (ctrl == NULL)
2945 return NULL;
2946
2947 len = sizeof(buf) - 1;
2948 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2949 if (ret >= 0) {
2950 buf[len] = '\0';
2951 pos = os_strchr(buf, '\n');
2952 if (pos)
2953 *pos = '\0';
2954 ifname = os_strdup(buf);
2955 }
2956 wpa_ctrl_close(ctrl);
2957#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2958
2959 return ifname;
2960}
2961
2962
2963int main(int argc, char *argv[])
2964{
6fc6879b
JM
2965 int warning_displayed = 0;
2966 int c;
2967 int daemonize = 0;
2968 int ret = 0;
2969 const char *global = NULL;
2970
2971 if (os_program_init())
2972 return -1;
2973
2974 for (;;) {
1cc84c1c 2975 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
2976 if (c < 0)
2977 break;
2978 switch (c) {
2979 case 'a':
2980 action_file = optarg;
2981 break;
2982 case 'B':
2983 daemonize = 1;
2984 break;
2985 case 'g':
2986 global = optarg;
2987 break;
1cc84c1c
JM
2988 case 'G':
2989 ping_interval = atoi(optarg);
2990 break;
6fc6879b
JM
2991 case 'h':
2992 usage();
2993 return 0;
2994 case 'v':
2995 printf("%s\n", wpa_cli_version);
2996 return 0;
2997 case 'i':
2998 os_free(ctrl_ifname);
2999 ctrl_ifname = os_strdup(optarg);
3000 break;
3001 case 'p':
3002 ctrl_iface_dir = optarg;
3003 break;
3004 case 'P':
3005 pid_file = optarg;
3006 break;
3007 default:
3008 usage();
3009 return -1;
3010 }
3011 }
3012
3013 interactive = (argc == optind) && (action_file == NULL);
3014
3015 if (interactive)
3016 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3017
3018 if (global) {
3019#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3020 ctrl_conn = wpa_ctrl_open(NULL);
3021#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3022 ctrl_conn = wpa_ctrl_open(global);
3023#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3024 if (ctrl_conn == NULL) {
3025 perror("Failed to connect to wpa_supplicant - "
3026 "wpa_ctrl_open");
3027 return -1;
3028 }
3029 }
3030
6fc6879b
JM
3031#ifndef _WIN32_WCE
3032 signal(SIGINT, wpa_cli_terminate);
3033 signal(SIGTERM, wpa_cli_terminate);
3034#endif /* _WIN32_WCE */
3035#ifndef CONFIG_NATIVE_WINDOWS
3036 signal(SIGALRM, wpa_cli_alarm);
3037#endif /* CONFIG_NATIVE_WINDOWS */
dd63f314
JM
3038#ifdef CONFIG_WPA_CLI_FORK
3039 signal(SIGUSR1, wpa_cli_usr1);
3040#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b 3041
4a3ade4e
JM
3042 if (ctrl_ifname == NULL)
3043 ctrl_ifname = wpa_cli_get_default_ifname();
3044
3045 if (interactive) {
3046 for (; !global;) {
3047 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3048 if (warning_displayed)
3049 printf("Connection established.\n");
3050 break;
3051 }
3052
3053 if (!warning_displayed) {
3054 printf("Could not connect to wpa_supplicant - "
3055 "re-trying\n");
3056 warning_displayed = 1;
3057 }
3058 os_sleep(1, 0);
3059 continue;
3060 }
3061 } else {
3062 if (!global &&
3063 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3064 perror("Failed to connect to wpa_supplicant - "
3065 "wpa_ctrl_open");
3066 return -1;
3067 }
3068
3069 if (action_file) {
3070 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3071 wpa_cli_attached = 1;
3072 } else {
3073 printf("Warning: Failed to attach to "
3074 "wpa_supplicant.\n");
6fc6879b 3075 return -1;
4a3ade4e 3076 }
6fc6879b
JM
3077 }
3078 }
3079
3080 if (daemonize && os_daemonize(pid_file))
3081 return -1;
3082
3083 if (interactive)
3084 wpa_cli_interactive();
3085 else if (action_file)
3086 wpa_cli_action(ctrl_conn);
3087 else
3088 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3089
3090 os_free(ctrl_ifname);
3091 wpa_cli_cleanup();
3092
3093 return ret;
3094}
3095
3096#else /* CONFIG_CTRL_IFACE */
3097int main(int argc, char *argv[])
3098{
3099 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3100 return -1;
3101}
3102#endif /* CONFIG_CTRL_IFACE */