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