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