]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
WPS ER: Add initial documentation for External Registrar functionality
[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
cbf78558 130#ifdef CONFIG_WPA_CLI_FORK
dd63f314
JM
131static int in_query = 0;
132
133static void wpa_cli_monitor_sig(int sig)
134{
135 if (sig == SIGUSR1)
136 in_query = 1;
137 else if (sig == SIGUSR2)
138 in_query = 0;
139}
140
cbf78558
JM
141static void wpa_cli_monitor(void)
142{
143 char buf[256];
144 size_t len = sizeof(buf) - 1;
145 struct timeval tv;
146 fd_set rfds;
147
dd63f314
JM
148 signal(SIGUSR1, wpa_cli_monitor_sig);
149 signal(SIGUSR2, wpa_cli_monitor_sig);
150
cbf78558
JM
151 while (mon_conn) {
152 int s = wpa_ctrl_get_fd(mon_conn);
153 tv.tv_sec = 5;
154 tv.tv_usec = 0;
155 FD_ZERO(&rfds);
156 FD_SET(s, &rfds);
157 if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) {
dd63f314
JM
158 if (errno == EINTR)
159 continue;
cbf78558
JM
160 perror("select");
161 break;
162 }
163 if (mon_conn == NULL)
164 break;
165 if (FD_ISSET(s, &rfds)) {
166 len = sizeof(buf) - 1;
167 int res = wpa_ctrl_recv(mon_conn, buf, &len);
168 if (res < 0) {
169 perror("wpa_ctrl_recv");
170 break;
171 }
172 buf[len] = '\0';
dd63f314
JM
173 if (in_query)
174 printf("\r");
cbf78558 175 printf("%s\n", buf);
dd63f314 176 kill(getppid(), SIGUSR1);
cbf78558
JM
177 }
178 }
179}
180#endif /* CONFIG_WPA_CLI_FORK */
181
182
4a3ade4e 183static int wpa_cli_open_connection(const char *ifname, int attach)
6fc6879b
JM
184{
185#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
186 ctrl_conn = wpa_ctrl_open(ifname);
4a3ade4e
JM
187 if (ctrl_conn == NULL)
188 return -1;
189
190 if (attach && interactive)
191 mon_conn = wpa_ctrl_open(ifname);
192 else
193 mon_conn = NULL;
6fc6879b
JM
194#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
195 char *cfile;
196 int flen, res;
197
198 if (ifname == NULL)
4a3ade4e 199 return -1;
6fc6879b
JM
200
201 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
202 cfile = os_malloc(flen);
203 if (cfile == NULL)
4a3ade4e 204 return -1L;
6fc6879b
JM
205 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
206 if (res < 0 || res >= flen) {
207 os_free(cfile);
4a3ade4e 208 return -1;
6fc6879b
JM
209 }
210
211 ctrl_conn = wpa_ctrl_open(cfile);
4a3ade4e
JM
212 if (ctrl_conn == NULL) {
213 os_free(cfile);
214 return -1;
215 }
216
217 if (attach && interactive)
218 mon_conn = wpa_ctrl_open(cfile);
219 else
220 mon_conn = NULL;
6fc6879b 221 os_free(cfile);
6fc6879b 222#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
4a3ade4e
JM
223
224 if (mon_conn) {
225 if (wpa_ctrl_attach(mon_conn) == 0) {
226 wpa_cli_attached = 1;
227 } else {
228 printf("Warning: Failed to attach to "
229 "wpa_supplicant.\n");
230 return -1;
231 }
cbf78558
JM
232
233#ifdef CONFIG_WPA_CLI_FORK
234 {
235 pid_t p = fork();
236 if (p < 0) {
237 perror("fork");
238 return -1;
239 }
240 if (p == 0) {
241 wpa_cli_monitor();
242 exit(0);
243 } else
244 mon_pid = p;
245 }
246#endif /* CONFIG_WPA_CLI_FORK */
4a3ade4e
JM
247 }
248
249 return 0;
6fc6879b
JM
250}
251
252
253static void wpa_cli_close_connection(void)
254{
255 if (ctrl_conn == NULL)
256 return;
257
037f83eb
JM
258#ifdef CONFIG_WPA_CLI_FORK
259 if (mon_pid) {
260 int status;
261 kill(mon_pid, SIGPIPE);
262 wait(&status);
263 mon_pid = 0;
264 }
265#endif /* CONFIG_WPA_CLI_FORK */
266
6fc6879b 267 if (wpa_cli_attached) {
4a3ade4e 268 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
6fc6879b
JM
269 wpa_cli_attached = 0;
270 }
271 wpa_ctrl_close(ctrl_conn);
272 ctrl_conn = NULL;
4a3ade4e
JM
273 if (mon_conn) {
274 wpa_ctrl_close(mon_conn);
275 mon_conn = NULL;
276 }
6fc6879b
JM
277}
278
279
280static void wpa_cli_msg_cb(char *msg, size_t len)
281{
282 printf("%s\n", msg);
283}
284
285
286static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
287{
288 char buf[2048];
289 size_t len;
290 int ret;
291
292 if (ctrl_conn == NULL) {
293 printf("Not connected to wpa_supplicant - command dropped.\n");
294 return -1;
295 }
296 len = sizeof(buf) - 1;
297 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
298 wpa_cli_msg_cb);
299 if (ret == -2) {
300 printf("'%s' command timed out.\n", cmd);
301 return -2;
302 } else if (ret < 0) {
303 printf("'%s' command failed.\n", cmd);
304 return -1;
305 }
306 if (print) {
307 buf[len] = '\0';
308 printf("%s", buf);
309 }
310 return 0;
311}
312
313
314static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
315{
316 return _wpa_ctrl_command(ctrl, cmd, 1);
317}
318
319
320static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
321{
322 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
323 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
324}
325
326
327static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
328{
329 return wpa_ctrl_command(ctrl, "PING");
330}
331
332
333static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
334{
335 return wpa_ctrl_command(ctrl, "MIB");
336}
337
338
339static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
340{
341 return wpa_ctrl_command(ctrl, "PMKSA");
342}
343
344
345static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
346{
dfa141b1 347 print_help();
6fc6879b
JM
348 return 0;
349}
350
351
352static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
353{
354 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
355 return 0;
356}
357
358
359static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
360{
361 wpa_cli_quit = 1;
362 return 0;
363}
364
365
366static void wpa_cli_show_variables(void)
367{
368 printf("set variables:\n"
369 " EAPOL::heldPeriod (EAPOL state machine held period, "
370 "in seconds)\n"
371 " EAPOL::authPeriod (EAPOL state machine authentication "
372 "period, in seconds)\n"
373 " EAPOL::startPeriod (EAPOL state machine start period, in "
374 "seconds)\n"
375 " EAPOL::maxStart (EAPOL state machine maximum start "
376 "attempts)\n");
377 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
378 "seconds)\n"
379 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
380 " threshold\n\tpercentage)\n"
381 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
382 "security\n\tassociation in seconds)\n");
383}
384
385
386static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
387{
388 char cmd[256];
389 int res;
390
391 if (argc == 0) {
392 wpa_cli_show_variables();
393 return 0;
394 }
395
396 if (argc != 2) {
397 printf("Invalid SET command: needs two arguments (variable "
398 "name and value)\n");
399 return -1;
400 }
401
402 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
403 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
404 printf("Too long SET command.\n");
405 return -1;
406 }
407 return wpa_ctrl_command(ctrl, cmd);
408}
409
410
411static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
412{
413 return wpa_ctrl_command(ctrl, "LOGOFF");
414}
415
416
417static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
418{
419 return wpa_ctrl_command(ctrl, "LOGON");
420}
421
422
423static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
424 char *argv[])
425{
426 return wpa_ctrl_command(ctrl, "REASSOCIATE");
427}
428
429
430static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
431 char *argv[])
432{
433 char cmd[256];
434 int res;
435
436 if (argc != 1) {
437 printf("Invalid PREAUTH command: needs one argument "
438 "(BSSID)\n");
439 return -1;
440 }
441
442 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
443 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
444 printf("Too long PREAUTH command.\n");
445 return -1;
446 }
447 return wpa_ctrl_command(ctrl, cmd);
448}
449
450
451static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
452{
453 char cmd[256];
454 int res;
455
456 if (argc != 1) {
457 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
458 "value)\n");
459 return -1;
460 }
461 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
462 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
463 printf("Too long AP_SCAN command.\n");
464 return -1;
465 }
466 return wpa_ctrl_command(ctrl, cmd);
467}
468
469
470static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
471 char *argv[])
472{
473 char cmd[256];
474 int res;
475
476 if (argc != 1) {
477 printf("Invalid STKSTART command: needs one argument "
478 "(Peer STA MAC address)\n");
479 return -1;
480 }
481
482 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
483 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
484 printf("Too long STKSTART command.\n");
485 return -1;
486 }
487 return wpa_ctrl_command(ctrl, cmd);
488}
489
490
491static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
492{
493 char cmd[256];
494 int res;
495
496 if (argc != 1) {
497 printf("Invalid FT_DS command: needs one argument "
498 "(Target AP MAC address)\n");
499 return -1;
500 }
501
502 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
503 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
504 printf("Too long FT_DS command.\n");
505 return -1;
506 }
507 return wpa_ctrl_command(ctrl, cmd);
508}
509
510
fcc60db4
JM
511static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 char cmd[256];
514 int res;
515
516 if (argc == 0) {
517 /* Any BSSID */
518 return wpa_ctrl_command(ctrl, "WPS_PBC");
519 }
520
521 /* Specific BSSID */
522 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
523 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
524 printf("Too long WPS_PBC command.\n");
525 return -1;
526 }
527 return wpa_ctrl_command(ctrl, cmd);
528}
529
530
531static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
532{
533 char cmd[256];
534 int res;
535
536 if (argc == 0) {
537 printf("Invalid WPS_PIN command: need one or two arguments:\n"
538 "- BSSID: use 'any' to select any\n"
539 "- PIN: optional, used only with devices that have no "
540 "display\n");
541 return -1;
542 }
543
544 if (argc == 1) {
545 /* Use dynamically generated PIN (returned as reply) */
546 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
547 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
548 printf("Too long WPS_PIN command.\n");
549 return -1;
550 }
551 return wpa_ctrl_command(ctrl, cmd);
552 }
553
554 /* Use hardcoded PIN from a label */
555 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
556 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
557 printf("Too long WPS_PIN command.\n");
558 return -1;
559 }
560 return wpa_ctrl_command(ctrl, cmd);
561}
562
563
116f7bb0 564#ifdef CONFIG_WPS_OOB
46bdb83a
MH
565static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
566{
567 char cmd[256];
568 int res;
569
e1ee6b60
MH
570 if (argc != 3 && argc != 4) {
571 printf("Invalid WPS_OOB command: need three or four "
572 "arguments:\n"
573 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
574 "- PATH: path of OOB device like '/mnt'\n"
575 "- METHOD: OOB method 'pin-e' or 'pin-r', "
576 "'cred'\n"
577 "- DEV_NAME: (only for NFC) device name like "
578 "'pn531'\n");
46bdb83a
MH
579 return -1;
580 }
581
e1ee6b60
MH
582 if (argc == 3)
583 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
584 argv[0], argv[1], argv[2]);
585 else
586 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
587 argv[0], argv[1], argv[2], argv[3]);
46bdb83a
MH
588 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
589 printf("Too long WPS_OOB command.\n");
590 return -1;
591 }
592 return wpa_ctrl_command(ctrl, cmd);
593}
116f7bb0 594#endif /* CONFIG_WPS_OOB */
46bdb83a
MH
595
596
fcc60db4
JM
597static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
598{
599 char cmd[256];
600 int res;
601
52eb293d
JM
602 if (argc == 2)
603 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
604 argv[0], argv[1]);
605 else if (argc == 6) {
606 char ssid_hex[2 * 32 + 1];
607 char key_hex[2 * 64 + 1];
608 int i;
609
610 ssid_hex[0] = '\0';
611 for (i = 0; i < 32; i++) {
612 if (argv[2][i] == '\0')
613 break;
614 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
615 }
616
617 key_hex[0] = '\0';
618 for (i = 0; i < 64; i++) {
619 if (argv[5][i] == '\0')
620 break;
621 os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
622 }
623
624 res = os_snprintf(cmd, sizeof(cmd),
625 "WPS_REG %s %s %s %s %s %s",
626 argv[0], argv[1], ssid_hex, argv[3], argv[4],
627 key_hex);
628 } else {
fcc60db4
JM
629 printf("Invalid WPS_REG command: need two arguments:\n"
630 "- BSSID: use 'any' to select any\n"
631 "- AP PIN\n");
52eb293d
JM
632 printf("Alternatively, six arguments can be used to "
633 "reconfigure the AP:\n"
634 "- BSSID: use 'any' to select any\n"
635 "- AP PIN\n"
636 "- new SSID\n"
637 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
638 "- new encr (NONE, WEP, TKIP, CCMP)\n"
639 "- new key\n");
fcc60db4
JM
640 return -1;
641 }
642
fcc60db4
JM
643 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
644 printf("Too long WPS_REG command.\n");
645 return -1;
646 }
647 return wpa_ctrl_command(ctrl, cmd);
648}
649
650
e9bcfebf
JM
651static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
652 char *argv[])
653{
08486685
JM
654 char cmd[100];
655 if (argc > 0) {
656 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
657 return wpa_ctrl_command(ctrl, cmd);
658 }
e9bcfebf 659 return wpa_ctrl_command(ctrl, "WPS_ER_START");
e9bcfebf
JM
660}
661
662
663static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
664 char *argv[])
665{
666 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
667
668}
669
670
72df2f5f
JM
671static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
672 char *argv[])
673{
674 char cmd[256];
675 int res;
676
677 if (argc != 2) {
678 printf("Invalid WPS_ER_PIN command: need two arguments:\n"
679 "- UUID: use 'any' to select any\n"
680 "- PIN: Enrollee PIN\n");
681 return -1;
682 }
683
684 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
685 argv[0], argv[1]);
686 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
687 printf("Too long WPS_ER_PIN command.\n");
688 return -1;
689 }
690 return wpa_ctrl_command(ctrl, cmd);
691}
692
693
564cd7fa
JM
694static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
695 char *argv[])
696{
697 char cmd[256];
698 int res;
699
700 if (argc != 1) {
701 printf("Invalid WPS_ER_PBC command: need one argument:\n"
702 "- UUID: Specify the Enrollee\n");
703 return -1;
704 }
705
706 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
707 argv[0]);
708 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
709 printf("Too long WPS_ER_PBC command.\n");
710 return -1;
711 }
712 return wpa_ctrl_command(ctrl, cmd);
713}
714
715
e64dcfd5
JM
716static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
717 char *argv[])
718{
719 char cmd[256];
720 int res;
721
722 if (argc != 2) {
723 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
724 "- UUID: specify which AP to use\n"
725 "- PIN: AP PIN\n");
726 return -1;
727 }
728
729 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
730 argv[0], argv[1]);
731 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
732 printf("Too long WPS_ER_LEARN command.\n");
733 return -1;
734 }
735 return wpa_ctrl_command(ctrl, cmd);
736}
737
738
11ef8d35
JM
739static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
740{
741 char cmd[256];
742 int res;
743
744 if (argc != 1) {
745 printf("Invalid IBSS_RSN command: needs one argument "
746 "(Peer STA MAC address)\n");
747 return -1;
748 }
749
750 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
751 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
752 printf("Too long IBSS_RSN command.\n");
753 return -1;
754 }
755 return wpa_ctrl_command(ctrl, cmd);
756}
757
758
6fc6879b
JM
759static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
760{
761 char cmd[256];
762 int res;
763
764 if (argc != 1) {
765 printf("Invalid LEVEL command: needs one argument (debug "
766 "level)\n");
767 return -1;
768 }
769 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
770 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
771 printf("Too long LEVEL command.\n");
772 return -1;
773 }
774 return wpa_ctrl_command(ctrl, cmd);
775}
776
777
778static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
779{
780 char cmd[256], *pos, *end;
781 int i, ret;
782
783 if (argc < 2) {
784 printf("Invalid IDENTITY command: needs two arguments "
785 "(network id and identity)\n");
786 return -1;
787 }
788
789 end = cmd + sizeof(cmd);
790 pos = cmd;
791 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
792 argv[0], argv[1]);
793 if (ret < 0 || ret >= end - pos) {
794 printf("Too long IDENTITY command.\n");
795 return -1;
796 }
797 pos += ret;
798 for (i = 2; i < argc; i++) {
799 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
800 if (ret < 0 || ret >= end - pos) {
801 printf("Too long IDENTITY command.\n");
802 return -1;
803 }
804 pos += ret;
805 }
806
807 return wpa_ctrl_command(ctrl, cmd);
808}
809
810
811static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
812{
813 char cmd[256], *pos, *end;
814 int i, ret;
815
816 if (argc < 2) {
817 printf("Invalid PASSWORD command: needs two arguments "
818 "(network id and password)\n");
819 return -1;
820 }
821
822 end = cmd + sizeof(cmd);
823 pos = cmd;
824 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
825 argv[0], argv[1]);
826 if (ret < 0 || ret >= end - pos) {
827 printf("Too long PASSWORD command.\n");
828 return -1;
829 }
830 pos += ret;
831 for (i = 2; i < argc; i++) {
832 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
833 if (ret < 0 || ret >= end - pos) {
834 printf("Too long PASSWORD command.\n");
835 return -1;
836 }
837 pos += ret;
838 }
839
840 return wpa_ctrl_command(ctrl, cmd);
841}
842
843
844static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
845 char *argv[])
846{
847 char cmd[256], *pos, *end;
848 int i, ret;
849
850 if (argc < 2) {
851 printf("Invalid NEW_PASSWORD command: needs two arguments "
852 "(network id and password)\n");
853 return -1;
854 }
855
856 end = cmd + sizeof(cmd);
857 pos = cmd;
858 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
859 argv[0], argv[1]);
860 if (ret < 0 || ret >= end - pos) {
861 printf("Too long NEW_PASSWORD command.\n");
862 return -1;
863 }
864 pos += ret;
865 for (i = 2; i < argc; i++) {
866 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
867 if (ret < 0 || ret >= end - pos) {
868 printf("Too long NEW_PASSWORD command.\n");
869 return -1;
870 }
871 pos += ret;
872 }
873
874 return wpa_ctrl_command(ctrl, cmd);
875}
876
877
878static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
879{
880 char cmd[256], *pos, *end;
881 int i, ret;
882
883 if (argc < 2) {
884 printf("Invalid PIN command: needs two arguments "
885 "(network id and pin)\n");
886 return -1;
887 }
888
889 end = cmd + sizeof(cmd);
890 pos = cmd;
891 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
892 argv[0], argv[1]);
893 if (ret < 0 || ret >= end - pos) {
894 printf("Too long PIN command.\n");
895 return -1;
896 }
897 pos += ret;
898 for (i = 2; i < argc; i++) {
899 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
900 if (ret < 0 || ret >= end - pos) {
901 printf("Too long PIN command.\n");
902 return -1;
903 }
904 pos += ret;
905 }
906 return wpa_ctrl_command(ctrl, cmd);
907}
908
909
910static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
911{
912 char cmd[256], *pos, *end;
913 int i, ret;
914
915 if (argc < 2) {
916 printf("Invalid OTP command: needs two arguments (network "
917 "id and password)\n");
918 return -1;
919 }
920
921 end = cmd + sizeof(cmd);
922 pos = cmd;
923 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
924 argv[0], argv[1]);
925 if (ret < 0 || ret >= end - pos) {
926 printf("Too long OTP command.\n");
927 return -1;
928 }
929 pos += ret;
930 for (i = 2; i < argc; i++) {
931 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
932 if (ret < 0 || ret >= end - pos) {
933 printf("Too long OTP command.\n");
934 return -1;
935 }
936 pos += ret;
937 }
938
939 return wpa_ctrl_command(ctrl, cmd);
940}
941
942
943static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
944 char *argv[])
945{
946 char cmd[256], *pos, *end;
947 int i, ret;
948
949 if (argc < 2) {
950 printf("Invalid PASSPHRASE command: needs two arguments "
951 "(network id and passphrase)\n");
952 return -1;
953 }
954
955 end = cmd + sizeof(cmd);
956 pos = cmd;
957 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
958 argv[0], argv[1]);
959 if (ret < 0 || ret >= end - pos) {
960 printf("Too long PASSPHRASE command.\n");
961 return -1;
962 }
963 pos += ret;
964 for (i = 2; i < argc; i++) {
965 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
966 if (ret < 0 || ret >= end - pos) {
967 printf("Too long PASSPHRASE command.\n");
968 return -1;
969 }
970 pos += ret;
971 }
972
973 return wpa_ctrl_command(ctrl, cmd);
974}
975
976
977static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
978{
979 char cmd[256], *pos, *end;
980 int i, ret;
981
982 if (argc < 2) {
983 printf("Invalid BSSID command: needs two arguments (network "
984 "id and BSSID)\n");
985 return -1;
986 }
987
988 end = cmd + sizeof(cmd);
989 pos = cmd;
990 ret = os_snprintf(pos, end - pos, "BSSID");
991 if (ret < 0 || ret >= end - pos) {
992 printf("Too long BSSID command.\n");
993 return -1;
994 }
995 pos += ret;
996 for (i = 0; i < argc; i++) {
997 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
998 if (ret < 0 || ret >= end - pos) {
999 printf("Too long BSSID command.\n");
1000 return -1;
1001 }
1002 pos += ret;
1003 }
1004
1005 return wpa_ctrl_command(ctrl, cmd);
1006}
1007
1008
1009static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1010 char *argv[])
1011{
1012 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1013}
1014
1015
1016static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1017 char *argv[])
1018{
1019 char cmd[32];
1020 int res;
1021
1022 if (argc < 1) {
1023 printf("Invalid SELECT_NETWORK command: needs one argument "
1024 "(network id)\n");
1025 return -1;
1026 }
1027
1028 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1029 if (res < 0 || (size_t) res >= sizeof(cmd))
1030 return -1;
1031 cmd[sizeof(cmd) - 1] = '\0';
1032
1033 return wpa_ctrl_command(ctrl, cmd);
1034}
1035
1036
1037static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1038 char *argv[])
1039{
1040 char cmd[32];
1041 int res;
1042
1043 if (argc < 1) {
1044 printf("Invalid ENABLE_NETWORK command: needs one argument "
1045 "(network id)\n");
1046 return -1;
1047 }
1048
1049 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1050 if (res < 0 || (size_t) res >= sizeof(cmd))
1051 return -1;
1052 cmd[sizeof(cmd) - 1] = '\0';
1053
1054 return wpa_ctrl_command(ctrl, cmd);
1055}
1056
1057
1058static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1059 char *argv[])
1060{
1061 char cmd[32];
1062 int res;
1063
1064 if (argc < 1) {
1065 printf("Invalid DISABLE_NETWORK command: needs one argument "
1066 "(network id)\n");
1067 return -1;
1068 }
1069
1070 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1071 if (res < 0 || (size_t) res >= sizeof(cmd))
1072 return -1;
1073 cmd[sizeof(cmd) - 1] = '\0';
1074
1075 return wpa_ctrl_command(ctrl, cmd);
1076}
1077
1078
1079static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1080 char *argv[])
1081{
1082 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1083}
1084
1085
1086static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1087 char *argv[])
1088{
1089 char cmd[32];
1090 int res;
1091
1092 if (argc < 1) {
1093 printf("Invalid REMOVE_NETWORK command: needs one argument "
1094 "(network id)\n");
1095 return -1;
1096 }
1097
1098 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1099 if (res < 0 || (size_t) res >= sizeof(cmd))
1100 return -1;
1101 cmd[sizeof(cmd) - 1] = '\0';
1102
1103 return wpa_ctrl_command(ctrl, cmd);
1104}
1105
1106
1107static void wpa_cli_show_network_variables(void)
1108{
1109 printf("set_network variables:\n"
1110 " ssid (network name, SSID)\n"
1111 " psk (WPA passphrase or pre-shared key)\n"
1112 " key_mgmt (key management protocol)\n"
1113 " identity (EAP identity)\n"
1114 " password (EAP password)\n"
1115 " ...\n"
1116 "\n"
1117 "Note: Values are entered in the same format as the "
1118 "configuration file is using,\n"
1119 "i.e., strings values need to be inside double quotation "
1120 "marks.\n"
1121 "For example: set_network 1 ssid \"network name\"\n"
1122 "\n"
1123 "Please see wpa_supplicant.conf documentation for full list "
1124 "of\navailable variables.\n");
1125}
1126
1127
1128static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1129 char *argv[])
1130{
1131 char cmd[256];
1132 int res;
1133
1134 if (argc == 0) {
1135 wpa_cli_show_network_variables();
1136 return 0;
1137 }
1138
1139 if (argc != 3) {
1140 printf("Invalid SET_NETWORK command: needs three arguments\n"
1141 "(network id, variable name, and value)\n");
1142 return -1;
1143 }
1144
1145 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1146 argv[0], argv[1], argv[2]);
1147 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1148 printf("Too long SET_NETWORK command.\n");
1149 return -1;
1150 }
1151 return wpa_ctrl_command(ctrl, cmd);
1152}
1153
1154
1155static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1156 char *argv[])
1157{
1158 char cmd[256];
1159 int res;
1160
1161 if (argc == 0) {
1162 wpa_cli_show_network_variables();
1163 return 0;
1164 }
1165
1166 if (argc != 2) {
1167 printf("Invalid GET_NETWORK command: needs two arguments\n"
1168 "(network id and variable name)\n");
1169 return -1;
1170 }
1171
1172 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1173 argv[0], argv[1]);
1174 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1175 printf("Too long GET_NETWORK command.\n");
1176 return -1;
1177 }
1178 return wpa_ctrl_command(ctrl, cmd);
1179}
1180
1181
1182static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1183 char *argv[])
1184{
1185 return wpa_ctrl_command(ctrl, "DISCONNECT");
1186}
1187
1188
1189static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1190 char *argv[])
1191{
1192 return wpa_ctrl_command(ctrl, "RECONNECT");
1193}
1194
1195
1196static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1197 char *argv[])
1198{
1199 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1200}
1201
1202
1203static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1204{
1205 return wpa_ctrl_command(ctrl, "SCAN");
1206}
1207
1208
1209static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1210 char *argv[])
1211{
1212 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1213}
1214
1215
1216static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1217{
1218 char cmd[64];
1219 int res;
1220
1221 if (argc != 1) {
1222 printf("Invalid BSS command: need one argument (index or "
1223 "BSSID)\n");
1224 return -1;
1225 }
1226
1227 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1228 if (res < 0 || (size_t) res >= sizeof(cmd))
1229 return -1;
1230 cmd[sizeof(cmd) - 1] = '\0';
1231
1232 return wpa_ctrl_command(ctrl, cmd);
1233}
1234
1235
1236static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1237 char *argv[])
1238{
1239 char cmd[64];
1240 int res;
1241
1242 if (argc < 1 || argc > 2) {
1243 printf("Invalid GET_CAPABILITY command: need either one or "
1244 "two arguments\n");
1245 return -1;
1246 }
1247
1248 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1249 printf("Invalid GET_CAPABILITY command: second argument, "
1250 "if any, must be 'strict'\n");
1251 return -1;
1252 }
1253
1254 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1255 (argc == 2) ? " strict" : "");
1256 if (res < 0 || (size_t) res >= sizeof(cmd))
1257 return -1;
1258 cmd[sizeof(cmd) - 1] = '\0';
1259
1260 return wpa_ctrl_command(ctrl, cmd);
1261}
1262
1263
1264static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1265{
1266 printf("Available interfaces:\n");
1267 return wpa_ctrl_command(ctrl, "INTERFACES");
1268}
1269
1270
1271static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1272{
1273 if (argc < 1) {
1274 wpa_cli_list_interfaces(ctrl);
1275 return 0;
1276 }
1277
1278 wpa_cli_close_connection();
1279 os_free(ctrl_ifname);
1280 ctrl_ifname = os_strdup(argv[0]);
1281
4a3ade4e 1282 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
6fc6879b 1283 printf("Connected to interface '%s.\n", ctrl_ifname);
6fc6879b
JM
1284 } else {
1285 printf("Could not connect to interface '%s' - re-trying\n",
1286 ctrl_ifname);
1287 }
1288 return 0;
1289}
1290
1291
1292static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1293 char *argv[])
1294{
1295 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1296}
1297
1298
1299static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1300 char *argv[])
1301{
1302 return wpa_ctrl_command(ctrl, "TERMINATE");
1303}
1304
1305
1306static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1307 char *argv[])
1308{
1309 char cmd[256];
1310 int res;
1311
1312 if (argc < 1) {
1313 printf("Invalid INTERFACE_ADD command: needs at least one "
1314 "argument (interface name)\n"
1315 "All arguments: ifname confname driver ctrl_interface "
1316 "driver_param bridge_name\n");
1317 return -1;
1318 }
1319
1320 /*
1321 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1322 * <driver_param>TAB<bridge_name>
1323 */
1324 res = os_snprintf(cmd, sizeof(cmd),
1325 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1326 argv[0],
1327 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1328 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1329 argc > 5 ? argv[5] : "");
1330 if (res < 0 || (size_t) res >= sizeof(cmd))
1331 return -1;
1332 cmd[sizeof(cmd) - 1] = '\0';
1333 return wpa_ctrl_command(ctrl, cmd);
1334}
1335
1336
1337static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1338 char *argv[])
1339{
1340 char cmd[128];
1341 int res;
1342
1343 if (argc != 1) {
1344 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1345 "(interface name)\n");
1346 return -1;
1347 }
1348
1349 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1350 if (res < 0 || (size_t) res >= sizeof(cmd))
1351 return -1;
1352 cmd[sizeof(cmd) - 1] = '\0';
1353 return wpa_ctrl_command(ctrl, cmd);
1354}
1355
1356
4b4a8ae5
JM
1357static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1358 char *argv[])
1359{
1360 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1361}
1362
1363
e653b622
JM
1364#ifdef CONFIG_AP
1365static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1366{
1367 char buf[64];
1368 if (argc != 1) {
1369 printf("Invalid 'sta' command - exactly one argument, STA "
1370 "address, is required.\n");
1371 return -1;
1372 }
e824cc46 1373 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
e653b622
JM
1374 return wpa_ctrl_command(ctrl, buf);
1375}
1376
1377
1378static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1379 char *addr, size_t addr_len)
1380{
1381 char buf[4096], *pos;
1382 size_t len;
1383 int ret;
1384
1385 if (ctrl_conn == NULL) {
1386 printf("Not connected to hostapd - command dropped.\n");
1387 return -1;
1388 }
1389 len = sizeof(buf) - 1;
1390 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1391 wpa_cli_msg_cb);
1392 if (ret == -2) {
1393 printf("'%s' command timed out.\n", cmd);
1394 return -2;
1395 } else if (ret < 0) {
1396 printf("'%s' command failed.\n", cmd);
1397 return -1;
1398 }
1399
1400 buf[len] = '\0';
1401 if (memcmp(buf, "FAIL", 4) == 0)
1402 return -1;
1403 printf("%s", buf);
1404
1405 pos = buf;
1406 while (*pos != '\0' && *pos != '\n')
1407 pos++;
1408 *pos = '\0';
1409 os_strlcpy(addr, buf, addr_len);
1410 return 0;
1411}
1412
1413
1414static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1415{
1416 char addr[32], cmd[64];
1417
1418 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1419 return 0;
1420 do {
e824cc46 1421 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
e653b622
JM
1422 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1423
1424 return -1;
1425}
1426#endif /* CONFIG_AP */
1427
1428
207ef3fb
JM
1429static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1430{
1431 return wpa_ctrl_command(ctrl, "SUSPEND");
1432}
1433
1434
1435static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1436{
1437 return wpa_ctrl_command(ctrl, "RESUME");
1438}
1439
1440
32d5295f
JM
1441static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1442{
1443 return wpa_ctrl_command(ctrl, "DROP_SA");
1444}
1445
1446
86d4f806
JM
1447static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1448{
1449 char cmd[128];
1450 int res;
1451
1452 if (argc != 1) {
1453 printf("Invalid ROAM command: needs one argument "
1454 "(target AP's BSSID)\n");
1455 return -1;
1456 }
1457
1458 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1459 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1460 printf("Too long ROAM command.\n");
1461 return -1;
1462 }
1463 return wpa_ctrl_command(ctrl, cmd);
1464}
1465
1466
40fd868c
ER
1467enum wpa_cli_cmd_flags {
1468 cli_cmd_flag_none = 0x00,
1469 cli_cmd_flag_sensitive = 0x01
1470};
1471
6fc6879b
JM
1472struct wpa_cli_cmd {
1473 const char *cmd;
1474 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 1475 enum wpa_cli_cmd_flags flags;
dfa141b1 1476 const char *usage;
6fc6879b
JM
1477};
1478
1479static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 1480 { "status", wpa_cli_cmd_status,
dfa141b1
ER
1481 cli_cmd_flag_none,
1482 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 1483 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
1484 cli_cmd_flag_none,
1485 "= pings wpa_supplicant" },
40fd868c 1486 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
1487 cli_cmd_flag_none,
1488 "= get MIB variables (dot1x, dot11)" },
40fd868c 1489 { "help", wpa_cli_cmd_help,
dfa141b1
ER
1490 cli_cmd_flag_none,
1491 "= show this usage help" },
40fd868c 1492 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
1493 cli_cmd_flag_none,
1494 "[ifname] = show interfaces/select interface" },
40fd868c 1495 { "level", wpa_cli_cmd_level,
dfa141b1
ER
1496 cli_cmd_flag_none,
1497 "<debug level> = change debug level" },
40fd868c 1498 { "license", wpa_cli_cmd_license,
dfa141b1
ER
1499 cli_cmd_flag_none,
1500 "= show full wpa_cli license" },
40fd868c 1501 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
1502 cli_cmd_flag_none,
1503 "= exit wpa_cli" },
40fd868c 1504 { "set", wpa_cli_cmd_set,
dfa141b1
ER
1505 cli_cmd_flag_none,
1506 "= set variables (shows list of variables when run without "
1507 "arguments)" },
40fd868c 1508 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
1509 cli_cmd_flag_none,
1510 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 1511 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
1512 cli_cmd_flag_none,
1513 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 1514 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
1515 cli_cmd_flag_none,
1516 "= show PMKSA cache" },
40fd868c 1517 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
1518 cli_cmd_flag_none,
1519 "= force reassociation" },
40fd868c 1520 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
1521 cli_cmd_flag_none,
1522 "<BSSID> = force preauthentication" },
40fd868c 1523 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
1524 cli_cmd_flag_none,
1525 "<network id> <identity> = configure identity for an SSID" },
40fd868c 1526 { "password", wpa_cli_cmd_password,
dfa141b1
ER
1527 cli_cmd_flag_sensitive,
1528 "<network id> <password> = configure password for an SSID" },
40fd868c 1529 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
1530 cli_cmd_flag_sensitive,
1531 "<network id> <password> = change password for an SSID" },
40fd868c 1532 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
1533 cli_cmd_flag_sensitive,
1534 "<network id> <pin> = configure pin for an SSID" },
40fd868c 1535 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
1536 cli_cmd_flag_sensitive,
1537 "<network id> <password> = configure one-time-password for an SSID"
1538 },
40fd868c 1539 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
1540 cli_cmd_flag_sensitive,
1541 "<network id> <passphrase> = configure private key passphrase\n"
1542 " for an SSID" },
40fd868c 1543 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
1544 cli_cmd_flag_none,
1545 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 1546 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
1547 cli_cmd_flag_none,
1548 "= list configured networks" },
40fd868c 1549 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
1550 cli_cmd_flag_none,
1551 "<network id> = select a network (disable others)" },
40fd868c 1552 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
1553 cli_cmd_flag_none,
1554 "<network id> = enable a network" },
40fd868c 1555 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
1556 cli_cmd_flag_none,
1557 "<network id> = disable a network" },
40fd868c 1558 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
1559 cli_cmd_flag_none,
1560 "= add a network" },
40fd868c 1561 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
1562 cli_cmd_flag_none,
1563 "<network id> = remove a network" },
40fd868c 1564 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
1565 cli_cmd_flag_sensitive,
1566 "<network id> <variable> <value> = set network variables (shows\n"
1567 " list of variables when run without arguments)" },
40fd868c 1568 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
1569 cli_cmd_flag_none,
1570 "<network id> <variable> = get network variables" },
40fd868c 1571 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
1572 cli_cmd_flag_none,
1573 "= save the current configuration" },
40fd868c 1574 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
1575 cli_cmd_flag_none,
1576 "= disconnect and wait for reassociate/reconnect command before\n"
1577 " connecting" },
40fd868c 1578 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
1579 cli_cmd_flag_none,
1580 "= like reassociate, but only takes effect if already disconnected"
1581 },
40fd868c 1582 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
1583 cli_cmd_flag_none,
1584 "= request new BSS scan" },
40fd868c 1585 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
1586 cli_cmd_flag_none,
1587 "= get latest scan results" },
40fd868c 1588 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
1589 cli_cmd_flag_none,
1590 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 1591 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
1592 cli_cmd_flag_none,
1593 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 1594 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
1595 cli_cmd_flag_none,
1596 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 1597 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
1598 cli_cmd_flag_none,
1599 "= terminate wpa_supplicant" },
40fd868c 1600 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
1601 cli_cmd_flag_none,
1602 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1603 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1604 " are optional" },
40fd868c 1605 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
1606 cli_cmd_flag_none,
1607 "<ifname> = removes the interface" },
40fd868c 1608 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
1609 cli_cmd_flag_none,
1610 "= list available interfaces" },
40fd868c 1611 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
1612 cli_cmd_flag_none,
1613 "<value> = set ap_scan parameter" },
40fd868c 1614 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
1615 cli_cmd_flag_none,
1616 "<addr> = request STK negotiation with <addr>" },
40fd868c 1617 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
1618 cli_cmd_flag_none,
1619 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 1620 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
1621 cli_cmd_flag_none,
1622 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 1623 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
1624 cli_cmd_flag_sensitive,
1625 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1626 "hardcoded)" },
116f7bb0 1627#ifdef CONFIG_WPS_OOB
46bdb83a
MH
1628 { "wps_oob", wpa_cli_cmd_wps_oob,
1629 cli_cmd_flag_sensitive,
e1ee6b60 1630 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 1631#endif /* CONFIG_WPS_OOB */
40fd868c 1632 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
1633 cli_cmd_flag_sensitive,
1634 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
e9bcfebf
JM
1635 { "wps_er_start", wpa_cli_cmd_wps_er_start,
1636 cli_cmd_flag_none,
08486685 1637 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
e9bcfebf
JM
1638 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1639 cli_cmd_flag_none,
1640 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
1641 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1642 cli_cmd_flag_sensitive,
1643 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
1644 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
1645 cli_cmd_flag_none,
1646 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
1647 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
1648 cli_cmd_flag_sensitive,
1649 "<UUID> <PIN> = learn AP configuration" },
11ef8d35
JM
1650 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1651 cli_cmd_flag_none,
1652 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
1653#ifdef CONFIG_AP
1654 { "sta", wpa_cli_cmd_sta,
1655 cli_cmd_flag_none,
1656 "<addr> = get information about an associated station (AP)" },
1657 { "all_sta", wpa_cli_cmd_all_sta,
1658 cli_cmd_flag_none,
1659 "= get information about all associated stations (AP)" },
1660#endif /* CONFIG_AP */
207ef3fb
JM
1661 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
1662 "= notification of suspend/hibernate" },
1663 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
1664 "= notification of resume/thaw" },
32d5295f
JM
1665 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
1666 "= drop SA without deauth/disassoc (test command)" },
86d4f806
JM
1667 { "roam", wpa_cli_cmd_roam,
1668 cli_cmd_flag_none,
1669 "<addr> = roam to the specified BSS" },
dfa141b1 1670 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
1671};
1672
1673
dfa141b1
ER
1674/*
1675 * Prints command usage, lines are padded with the specified string.
1676 */
1677static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1678{
1679 char c;
1680 size_t n;
1681
1682 printf("%s%s ", pad, cmd->cmd);
1683 for (n = 0; (c = cmd->usage[n]); n++) {
1684 printf("%c", c);
1685 if (c == '\n')
1686 printf("%s", pad);
1687 }
1688 printf("\n");
1689}
1690
1691
1692static void print_help(void)
1693{
1694 int n;
1695 printf("commands:\n");
1696 for (n = 0; wpa_cli_commands[n].cmd; n++)
1697 print_cmd_help(&wpa_cli_commands[n], " ");
1698}
1699
1700
40fd868c
ER
1701#ifdef CONFIG_READLINE
1702static int cmd_has_sensitive_data(const char *cmd)
1703{
1704 const char *c, *delim;
1705 int n;
1706 size_t len;
1707
1708 delim = os_strchr(cmd, ' ');
1709 if (delim)
1710 len = delim - cmd;
1711 else
1712 len = os_strlen(cmd);
1713
1714 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1715 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1716 return (wpa_cli_commands[n].flags &
1717 cli_cmd_flag_sensitive);
1718 }
1719 return 0;
1720}
1721#endif /* CONFIG_READLINE */
1722
1723
6fc6879b
JM
1724static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1725{
1726 struct wpa_cli_cmd *cmd, *match = NULL;
1727 int count;
1728 int ret = 0;
1729
1730 count = 0;
1731 cmd = wpa_cli_commands;
1732 while (cmd->cmd) {
1733 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1734 {
1735 match = cmd;
1736 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1737 /* we have an exact match */
1738 count = 1;
1739 break;
1740 }
1741 count++;
1742 }
1743 cmd++;
1744 }
1745
1746 if (count > 1) {
1747 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1748 cmd = wpa_cli_commands;
1749 while (cmd->cmd) {
1750 if (os_strncasecmp(cmd->cmd, argv[0],
1751 os_strlen(argv[0])) == 0) {
1752 printf(" %s", cmd->cmd);
1753 }
1754 cmd++;
1755 }
1756 printf("\n");
1757 ret = 1;
1758 } else if (count == 0) {
1759 printf("Unknown command '%s'\n", argv[0]);
1760 ret = 1;
1761 } else {
1762 ret = match->handler(ctrl, argc - 1, &argv[1]);
1763 }
1764
1765 return ret;
1766}
1767
1768
1769static int str_match(const char *a, const char *b)
1770{
1771 return os_strncmp(a, b, os_strlen(b)) == 0;
1772}
1773
1774
1775static int wpa_cli_exec(const char *program, const char *arg1,
1776 const char *arg2)
1777{
1778 char *cmd;
1779 size_t len;
1780 int res;
308a4ec8 1781 int ret = 0;
6fc6879b
JM
1782
1783 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1784 cmd = os_malloc(len);
1785 if (cmd == NULL)
1786 return -1;
1787 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1788 if (res < 0 || (size_t) res >= len) {
1789 os_free(cmd);
1790 return -1;
1791 }
1792 cmd[len - 1] = '\0';
1793#ifndef _WIN32_WCE
308a4ec8
JM
1794 if (system(cmd) < 0)
1795 ret = -1;
6fc6879b
JM
1796#endif /* _WIN32_WCE */
1797 os_free(cmd);
1798
308a4ec8 1799 return ret;
6fc6879b
JM
1800}
1801
1802
1803static void wpa_cli_action_process(const char *msg)
1804{
1805 const char *pos;
1806 char *copy = NULL, *id, *pos2;
1807
1808 pos = msg;
1809 if (*pos == '<') {
1810 /* skip priority */
1811 pos = os_strchr(pos, '>');
1812 if (pos)
1813 pos++;
1814 else
1815 pos = msg;
1816 }
1817
1818 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1819 int new_id = -1;
1820 os_unsetenv("WPA_ID");
1821 os_unsetenv("WPA_ID_STR");
1822 os_unsetenv("WPA_CTRL_DIR");
1823
1824 pos = os_strstr(pos, "[id=");
1825 if (pos)
1826 copy = os_strdup(pos + 4);
1827
1828 if (copy) {
1829 pos2 = id = copy;
1830 while (*pos2 && *pos2 != ' ')
1831 pos2++;
1832 *pos2++ = '\0';
1833 new_id = atoi(id);
1834 os_setenv("WPA_ID", id, 1);
1835 while (*pos2 && *pos2 != '=')
1836 pos2++;
1837 if (*pos2 == '=')
1838 pos2++;
1839 id = pos2;
1840 while (*pos2 && *pos2 != ']')
1841 pos2++;
1842 *pos2 = '\0';
1843 os_setenv("WPA_ID_STR", id, 1);
1844 os_free(copy);
1845 }
1846
1847 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1848
1849 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1850 wpa_cli_connected = 1;
1851 wpa_cli_last_id = new_id;
1852 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1853 }
1854 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1855 if (wpa_cli_connected) {
1856 wpa_cli_connected = 0;
1857 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1858 }
1859 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1860 printf("wpa_supplicant is terminating - stop monitoring\n");
1861 wpa_cli_quit = 1;
1862 }
1863}
1864
1865
1866#ifndef CONFIG_ANSI_C_EXTRA
1867static void wpa_cli_action_cb(char *msg, size_t len)
1868{
1869 wpa_cli_action_process(msg);
1870}
1871#endif /* CONFIG_ANSI_C_EXTRA */
1872
1873
1874static void wpa_cli_reconnect(void)
1875{
1876 wpa_cli_close_connection();
4a3ade4e 1877 wpa_cli_open_connection(ctrl_ifname, 1);
6fc6879b
JM
1878}
1879
1880
1881static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1882 int action_monitor)
1883{
1884 int first = 1;
1885 if (ctrl_conn == NULL) {
1886 wpa_cli_reconnect();
1887 return;
1888 }
1889 while (wpa_ctrl_pending(ctrl) > 0) {
1890 char buf[256];
1891 size_t len = sizeof(buf) - 1;
1892 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1893 buf[len] = '\0';
1894 if (action_monitor)
1895 wpa_cli_action_process(buf);
1896 else {
1897 if (in_read && first)
dd63f314 1898 printf("\r");
6fc6879b
JM
1899 first = 0;
1900 printf("%s\n", buf);
dd63f314
JM
1901#ifdef CONFIG_READLINE
1902 rl_on_new_line();
1903 rl_redisplay();
1904#endif /* CONFIG_READLINE */
6fc6879b
JM
1905 }
1906 } else {
1907 printf("Could not read pending message.\n");
1908 break;
1909 }
1910 }
1911
1912 if (wpa_ctrl_pending(ctrl) < 0) {
1913 printf("Connection to wpa_supplicant lost - trying to "
1914 "reconnect\n");
1915 wpa_cli_reconnect();
1916 }
1917}
1918
1919
1920#ifdef CONFIG_READLINE
1921static char * wpa_cli_cmd_gen(const char *text, int state)
1922{
1923 static int i, len;
1924 const char *cmd;
1925
1926 if (state == 0) {
1927 i = 0;
1928 len = os_strlen(text);
1929 }
1930
1931 while ((cmd = wpa_cli_commands[i].cmd)) {
1932 i++;
1933 if (os_strncasecmp(cmd, text, len) == 0)
d566f415 1934 return strdup(cmd);
6fc6879b
JM
1935 }
1936
1937 return NULL;
1938}
1939
1940
1941static char * wpa_cli_dummy_gen(const char *text, int state)
1942{
a7918ec7
JM
1943 int i;
1944
1945 for (i = 0; wpa_cli_commands[i].cmd; i++) {
1946 const char *cmd = wpa_cli_commands[i].cmd;
1947 size_t len = os_strlen(cmd);
1948 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
1949 rl_line_buffer[len] == ' ') {
1950 printf("\n%s\n", wpa_cli_commands[i].usage);
1951 rl_on_new_line();
1952 rl_redisplay();
1953 break;
1954 }
1955 }
1956
1957 rl_attempted_completion_over = 1;
1958 return NULL;
1959}
1960
1961
1962static char * wpa_cli_status_gen(const char *text, int state)
1963{
1964 static int i, len;
1965 char *options[] = {
1966 "verbose", NULL
1967 };
1968 char *t;
1969
1970 if (state == 0) {
1971 i = 0;
1972 len = os_strlen(text);
1973 }
1974
1975 while ((t = options[i])) {
1976 i++;
1977 if (os_strncasecmp(t, text, len) == 0)
1978 return strdup(t);
1979 }
1980
1981 rl_attempted_completion_over = 1;
6fc6879b
JM
1982 return NULL;
1983}
1984
1985
1986static char ** wpa_cli_completion(const char *text, int start, int end)
1987{
a7918ec7
JM
1988 char * (*func)(const char *text, int state);
1989
1990 if (start == 0)
1991 func = wpa_cli_cmd_gen;
1992 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
1993 func = wpa_cli_status_gen;
1994 else
1995 func = wpa_cli_dummy_gen;
1996 return rl_completion_matches(text, func);
6fc6879b
JM
1997}
1998#endif /* CONFIG_READLINE */
1999
2000
2001static void wpa_cli_interactive(void)
2002{
2003#define max_args 10
2004 char cmdbuf[256], *cmd, *argv[max_args], *pos;
2005 int argc;
2006#ifdef CONFIG_READLINE
2007 char *home, *hfile = NULL;
2008#endif /* CONFIG_READLINE */
2009
2010 printf("\nInteractive mode\n\n");
2011
2012#ifdef CONFIG_READLINE
2013 rl_attempted_completion_function = wpa_cli_completion;
2014 home = getenv("HOME");
2015 if (home) {
2016 const char *fname = ".wpa_cli_history";
2017 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2018 hfile = os_malloc(hfile_len);
2019 if (hfile) {
2020 int res;
2021 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2022 fname);
2023 if (res >= 0 && res < hfile_len) {
2024 hfile[hfile_len - 1] = '\0';
2025 read_history(hfile);
2026 stifle_history(100);
2027 }
2028 }
2029 }
2030#endif /* CONFIG_READLINE */
2031
2032 do {
4a3ade4e 2033 wpa_cli_recv_pending(mon_conn, 0, 0);
6fc6879b 2034#ifndef CONFIG_NATIVE_WINDOWS
1cc84c1c 2035 alarm(ping_interval);
6fc6879b 2036#endif /* CONFIG_NATIVE_WINDOWS */
dd63f314
JM
2037#ifdef CONFIG_WPA_CLI_FORK
2038 if (mon_pid)
2039 kill(mon_pid, SIGUSR1);
2040#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
2041#ifdef CONFIG_READLINE
2042 cmd = readline("> ");
2043 if (cmd && *cmd) {
2044 HIST_ENTRY *h;
2045 while (next_history())
2046 ;
2047 h = previous_history();
2048 if (h == NULL || os_strcmp(cmd, h->line) != 0)
2049 add_history(cmd);
2050 next_history();
2051 }
2052#else /* CONFIG_READLINE */
2053 printf("> ");
2054 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2055#endif /* CONFIG_READLINE */
2056#ifndef CONFIG_NATIVE_WINDOWS
2057 alarm(0);
2058#endif /* CONFIG_NATIVE_WINDOWS */
2059 if (cmd == NULL)
2060 break;
4a3ade4e 2061 wpa_cli_recv_pending(mon_conn, 0, 0);
6fc6879b
JM
2062 pos = cmd;
2063 while (*pos != '\0') {
2064 if (*pos == '\n') {
2065 *pos = '\0';
2066 break;
2067 }
2068 pos++;
2069 }
2070 argc = 0;
2071 pos = cmd;
2072 for (;;) {
2073 while (*pos == ' ')
2074 pos++;
2075 if (*pos == '\0')
2076 break;
2077 argv[argc] = pos;
2078 argc++;
2079 if (argc == max_args)
2080 break;
2081 if (*pos == '"') {
2082 char *pos2 = os_strrchr(pos, '"');
2083 if (pos2)
2084 pos = pos2 + 1;
2085 }
2086 while (*pos != '\0' && *pos != ' ')
2087 pos++;
2088 if (*pos == ' ')
2089 *pos++ = '\0';
2090 }
2091 if (argc)
2092 wpa_request(ctrl_conn, argc, argv);
2093
2094 if (cmd != cmdbuf)
a24eb842 2095 free(cmd);
dd63f314
JM
2096#ifdef CONFIG_WPA_CLI_FORK
2097 if (mon_pid)
2098 kill(mon_pid, SIGUSR2);
2099#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
2100 } while (!wpa_cli_quit);
2101
2102#ifdef CONFIG_READLINE
2103 if (hfile) {
2104 /* Save command history, excluding lines that may contain
2105 * passwords. */
2106 HIST_ENTRY *h;
2107 history_set_pos(0);
413653e8 2108 while ((h = current_history())) {
6fc6879b
JM
2109 char *p = h->line;
2110 while (*p == ' ' || *p == '\t')
2111 p++;
40fd868c 2112 if (cmd_has_sensitive_data(p)) {
6fc6879b
JM
2113 h = remove_history(where_history());
2114 if (h) {
2115 os_free(h->line);
2116 os_free(h->data);
2117 os_free(h);
413653e8
ER
2118 } else
2119 next_history();
2120 } else
2121 next_history();
6fc6879b
JM
2122 }
2123 write_history(hfile);
2124 os_free(hfile);
2125 }
2126#endif /* CONFIG_READLINE */
2127}
2128
2129
2130static void wpa_cli_action(struct wpa_ctrl *ctrl)
2131{
2132#ifdef CONFIG_ANSI_C_EXTRA
2133 /* TODO: ANSI C version(?) */
2134 printf("Action processing not supported in ANSI C build.\n");
2135#else /* CONFIG_ANSI_C_EXTRA */
2136 fd_set rfds;
2137 int fd, res;
2138 struct timeval tv;
2139 char buf[256]; /* note: large enough to fit in unsolicited messages */
2140 size_t len;
2141
2142 fd = wpa_ctrl_get_fd(ctrl);
2143
2144 while (!wpa_cli_quit) {
2145 FD_ZERO(&rfds);
2146 FD_SET(fd, &rfds);
1cc84c1c 2147 tv.tv_sec = ping_interval;
6fc6879b
JM
2148 tv.tv_usec = 0;
2149 res = select(fd + 1, &rfds, NULL, NULL, &tv);
2150 if (res < 0 && errno != EINTR) {
2151 perror("select");
2152 break;
2153 }
2154
2155 if (FD_ISSET(fd, &rfds))
2156 wpa_cli_recv_pending(ctrl, 0, 1);
2157 else {
2158 /* verify that connection is still working */
2159 len = sizeof(buf) - 1;
2160 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2161 wpa_cli_action_cb) < 0 ||
2162 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2163 printf("wpa_supplicant did not reply to PING "
2164 "command - exiting\n");
2165 break;
2166 }
2167 }
2168 }
2169#endif /* CONFIG_ANSI_C_EXTRA */
2170}
2171
2172
2173static void wpa_cli_cleanup(void)
2174{
2175 wpa_cli_close_connection();
2176 if (pid_file)
2177 os_daemonize_terminate(pid_file);
2178
2179 os_program_deinit();
2180}
2181
2182static void wpa_cli_terminate(int sig)
2183{
2184 wpa_cli_cleanup();
2185 exit(0);
2186}
2187
2188
dd63f314
JM
2189#ifdef CONFIG_WPA_CLI_FORK
2190static void wpa_cli_usr1(int sig)
2191{
2192#ifdef CONFIG_READLINE
2193 rl_on_new_line();
2194 rl_redisplay();
2195#endif /* CONFIG_READLINE */
2196}
2197#endif /* CONFIG_WPA_CLI_FORK */
2198
2199
6fc6879b
JM
2200#ifndef CONFIG_NATIVE_WINDOWS
2201static void wpa_cli_alarm(int sig)
2202{
2203 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2204 printf("Connection to wpa_supplicant lost - trying to "
2205 "reconnect\n");
2206 wpa_cli_close_connection();
2207 }
2208 if (!ctrl_conn)
2209 wpa_cli_reconnect();
4a3ade4e
JM
2210 if (mon_conn)
2211 wpa_cli_recv_pending(mon_conn, 1, 0);
1cc84c1c 2212 alarm(ping_interval);
6fc6879b
JM
2213}
2214#endif /* CONFIG_NATIVE_WINDOWS */
2215
2216
2217static char * wpa_cli_get_default_ifname(void)
2218{
2219 char *ifname = NULL;
2220
2221#ifdef CONFIG_CTRL_IFACE_UNIX
2222 struct dirent *dent;
2223 DIR *dir = opendir(ctrl_iface_dir);
2224 if (!dir)
2225 return NULL;
2226 while ((dent = readdir(dir))) {
2227#ifdef _DIRENT_HAVE_D_TYPE
2228 /*
2229 * Skip the file if it is not a socket. Also accept
2230 * DT_UNKNOWN (0) in case the C library or underlying
2231 * file system does not support d_type.
2232 */
2233 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2234 continue;
2235#endif /* _DIRENT_HAVE_D_TYPE */
2236 if (os_strcmp(dent->d_name, ".") == 0 ||
2237 os_strcmp(dent->d_name, "..") == 0)
2238 continue;
2239 printf("Selected interface '%s'\n", dent->d_name);
2240 ifname = os_strdup(dent->d_name);
2241 break;
2242 }
2243 closedir(dir);
2244#endif /* CONFIG_CTRL_IFACE_UNIX */
2245
2246#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2247 char buf[2048], *pos;
2248 size_t len;
2249 struct wpa_ctrl *ctrl;
2250 int ret;
2251
2252 ctrl = wpa_ctrl_open(NULL);
2253 if (ctrl == NULL)
2254 return NULL;
2255
2256 len = sizeof(buf) - 1;
2257 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2258 if (ret >= 0) {
2259 buf[len] = '\0';
2260 pos = os_strchr(buf, '\n');
2261 if (pos)
2262 *pos = '\0';
2263 ifname = os_strdup(buf);
2264 }
2265 wpa_ctrl_close(ctrl);
2266#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2267
2268 return ifname;
2269}
2270
2271
2272int main(int argc, char *argv[])
2273{
6fc6879b
JM
2274 int warning_displayed = 0;
2275 int c;
2276 int daemonize = 0;
2277 int ret = 0;
2278 const char *global = NULL;
2279
2280 if (os_program_init())
2281 return -1;
2282
2283 for (;;) {
1cc84c1c 2284 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
2285 if (c < 0)
2286 break;
2287 switch (c) {
2288 case 'a':
2289 action_file = optarg;
2290 break;
2291 case 'B':
2292 daemonize = 1;
2293 break;
2294 case 'g':
2295 global = optarg;
2296 break;
1cc84c1c
JM
2297 case 'G':
2298 ping_interval = atoi(optarg);
2299 break;
6fc6879b
JM
2300 case 'h':
2301 usage();
2302 return 0;
2303 case 'v':
2304 printf("%s\n", wpa_cli_version);
2305 return 0;
2306 case 'i':
2307 os_free(ctrl_ifname);
2308 ctrl_ifname = os_strdup(optarg);
2309 break;
2310 case 'p':
2311 ctrl_iface_dir = optarg;
2312 break;
2313 case 'P':
2314 pid_file = optarg;
2315 break;
2316 default:
2317 usage();
2318 return -1;
2319 }
2320 }
2321
2322 interactive = (argc == optind) && (action_file == NULL);
2323
2324 if (interactive)
2325 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2326
2327 if (global) {
2328#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2329 ctrl_conn = wpa_ctrl_open(NULL);
2330#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2331 ctrl_conn = wpa_ctrl_open(global);
2332#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2333 if (ctrl_conn == NULL) {
2334 perror("Failed to connect to wpa_supplicant - "
2335 "wpa_ctrl_open");
2336 return -1;
2337 }
2338 }
2339
6fc6879b
JM
2340#ifndef _WIN32_WCE
2341 signal(SIGINT, wpa_cli_terminate);
2342 signal(SIGTERM, wpa_cli_terminate);
2343#endif /* _WIN32_WCE */
2344#ifndef CONFIG_NATIVE_WINDOWS
2345 signal(SIGALRM, wpa_cli_alarm);
2346#endif /* CONFIG_NATIVE_WINDOWS */
dd63f314
JM
2347#ifdef CONFIG_WPA_CLI_FORK
2348 signal(SIGUSR1, wpa_cli_usr1);
2349#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b 2350
4a3ade4e
JM
2351 if (ctrl_ifname == NULL)
2352 ctrl_ifname = wpa_cli_get_default_ifname();
2353
2354 if (interactive) {
2355 for (; !global;) {
2356 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
2357 if (warning_displayed)
2358 printf("Connection established.\n");
2359 break;
2360 }
2361
2362 if (!warning_displayed) {
2363 printf("Could not connect to wpa_supplicant - "
2364 "re-trying\n");
2365 warning_displayed = 1;
2366 }
2367 os_sleep(1, 0);
2368 continue;
2369 }
2370 } else {
2371 if (!global &&
2372 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
2373 perror("Failed to connect to wpa_supplicant - "
2374 "wpa_ctrl_open");
2375 return -1;
2376 }
2377
2378 if (action_file) {
2379 if (wpa_ctrl_attach(ctrl_conn) == 0) {
2380 wpa_cli_attached = 1;
2381 } else {
2382 printf("Warning: Failed to attach to "
2383 "wpa_supplicant.\n");
6fc6879b 2384 return -1;
4a3ade4e 2385 }
6fc6879b
JM
2386 }
2387 }
2388
2389 if (daemonize && os_daemonize(pid_file))
2390 return -1;
2391
2392 if (interactive)
2393 wpa_cli_interactive();
2394 else if (action_file)
2395 wpa_cli_action(ctrl_conn);
2396 else
2397 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2398
2399 os_free(ctrl_ifname);
2400 wpa_cli_cleanup();
2401
2402 return ret;
2403}
2404
2405#else /* CONFIG_CTRL_IFACE */
2406int main(int argc, char *argv[])
2407{
2408 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2409 return -1;
2410}
2411#endif /* CONFIG_CTRL_IFACE */