]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/blob - wpa_supplicant/wpa_cli.c
Add ctrl_iface command for triggering a roam to a specific BSS
[build-utilities/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  */
15 #include "includes.h"
17 #ifdef CONFIG_CTRL_IFACE
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 */
30 #include "common/wpa_ctrl.h"
31 #include "common.h"
32 #include "common/version.h"
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";
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";
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";
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;
109 static void print_help();
112 static void usage(void)
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();
130 #ifdef CONFIG_WPA_CLI_FORK
131 static int in_query = 0;
133 static void wpa_cli_monitor_sig(int sig)
135         if (sig == SIGUSR1)
136                 in_query = 1;
137         else if (sig == SIGUSR2)
138                 in_query = 0;
141 static void wpa_cli_monitor(void)
143         char buf[256];
144         size_t len = sizeof(buf) - 1;
145         struct timeval tv;
146         fd_set rfds;
148         signal(SIGUSR1, wpa_cli_monitor_sig);
149         signal(SIGUSR2, wpa_cli_monitor_sig);
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         }
180 #endif /* CONFIG_WPA_CLI_FORK */
183 static int wpa_cli_open_connection(const char *ifname, int attach)
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;
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;
198         if (ifname == NULL)
199                 return -1;
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         }
211         ctrl_conn = wpa_ctrl_open(cfile);
212         if (ctrl_conn == NULL) {
213                 os_free(cfile);
214                 return -1;
215         }
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 */
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                 }
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         }
249         return 0;
253 static void wpa_cli_close_connection(void)
255         if (ctrl_conn == NULL)
256                 return;
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 */
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         }
280 static void wpa_cli_msg_cb(char *msg, size_t len)
282         printf("%s\n", msg);
286 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
288         char buf[2048];
289         size_t len;
290         int ret;
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;
314 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
316         return _wpa_ctrl_command(ctrl, cmd, 1);
320 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
322         int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
323         return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
327 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
329         return wpa_ctrl_command(ctrl, "PING");
333 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
335         return wpa_ctrl_command(ctrl, "MIB");
339 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
341         return wpa_ctrl_command(ctrl, "PMKSA");
345 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
347         print_help();
348         return 0;
352 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
354         printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
355         return 0;
359 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
361         wpa_cli_quit = 1;
362         return 0;
366 static void wpa_cli_show_variables(void)
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");
386 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
388         char cmd[256];
389         int res;
391         if (argc == 0) {
392                 wpa_cli_show_variables();
393                 return 0;
394         }
396         if (argc != 2) {
397                 printf("Invalid SET command: needs two arguments (variable "
398                        "name and value)\n");
399                 return -1;
400         }
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);
411 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
413         return wpa_ctrl_command(ctrl, "LOGOFF");
417 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
419         return wpa_ctrl_command(ctrl, "LOGON");
423 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
424                                    char *argv[])
426         return wpa_ctrl_command(ctrl, "REASSOCIATE");
430 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
431                                        char *argv[])
433         char cmd[256];
434         int res;
436         if (argc != 1) {
437                 printf("Invalid PREAUTH command: needs one argument "
438                        "(BSSID)\n");
439                 return -1;
440         }
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);
451 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
453         char cmd[256];
454         int res;
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);
470 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
471                                 char *argv[])
473         char cmd[256];
474         int res;
476         if (argc != 1) {
477                 printf("Invalid STKSTART command: needs one argument "
478                        "(Peer STA MAC address)\n");
479                 return -1;
480         }
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);
491 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
493         char cmd[256];
494         int res;
496         if (argc != 1) {
497                 printf("Invalid FT_DS command: needs one argument "
498                        "(Target AP MAC address)\n");
499                 return -1;
500         }
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);
511 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
513         char cmd[256];
514         int res;
516         if (argc == 0) {
517                 /* Any BSSID */
518                 return wpa_ctrl_command(ctrl, "WPS_PBC");
519         }
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);
531 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
533         char cmd[256];
534         int res;
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         }
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         }
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);
564 #ifdef CONFIG_WPS_OOB
565 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
567         char cmd[256];
568         int res;
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         }
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);
594 #endif /* CONFIG_WPS_OOB */
597 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
599         char cmd[256];
600         int res;
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;
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                 }
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                 }
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         }
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);
651 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
652                                     char *argv[])
654         return wpa_ctrl_command(ctrl, "WPS_ER_START");
659 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
660                                    char *argv[])
662         return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
667 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
668                                   char *argv[])
670         char cmd[256];
671         int res;
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         }
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);
690 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
691                                   char *argv[])
693         char cmd[256];
694         int res;
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         }
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);
712 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
713                                     char *argv[])
715         char cmd[256];
716         int res;
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         }
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);
735 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
737         char cmd[256];
738         int res;
740         if (argc != 1) {
741                 printf("Invalid IBSS_RSN command: needs one argument "
742                        "(Peer STA MAC address)\n");
743                 return -1;
744         }
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);
755 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
757         char cmd[256];
758         int res;
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);
774 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
776         char cmd[256], *pos, *end;
777         int i, ret;
779         if (argc < 2) {
780                 printf("Invalid IDENTITY command: needs two arguments "
781                        "(network id and identity)\n");
782                 return -1;
783         }
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         }
803         return wpa_ctrl_command(ctrl, cmd);
807 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
809         char cmd[256], *pos, *end;
810         int i, ret;
812         if (argc < 2) {
813                 printf("Invalid PASSWORD command: needs two arguments "
814                        "(network id and password)\n");
815                 return -1;
816         }
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         }
836         return wpa_ctrl_command(ctrl, cmd);
840 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
841                                     char *argv[])
843         char cmd[256], *pos, *end;
844         int i, ret;
846         if (argc < 2) {
847                 printf("Invalid NEW_PASSWORD command: needs two arguments "
848                        "(network id and password)\n");
849                 return -1;
850         }
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         }
870         return wpa_ctrl_command(ctrl, cmd);
874 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
876         char cmd[256], *pos, *end;
877         int i, ret;
879         if (argc < 2) {
880                 printf("Invalid PIN command: needs two arguments "
881                        "(network id and pin)\n");
882                 return -1;
883         }
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);
906 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
908         char cmd[256], *pos, *end;
909         int i, ret;
911         if (argc < 2) {
912                 printf("Invalid OTP command: needs two arguments (network "
913                        "id and password)\n");
914                 return -1;
915         }
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         }
935         return wpa_ctrl_command(ctrl, cmd);
939 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
940                                   char *argv[])
942         char cmd[256], *pos, *end;
943         int i, ret;
945         if (argc < 2) {
946                 printf("Invalid PASSPHRASE command: needs two arguments "
947                        "(network id and passphrase)\n");
948                 return -1;
949         }
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         }
969         return wpa_ctrl_command(ctrl, cmd);
973 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
975         char cmd[256], *pos, *end;
976         int i, ret;
978         if (argc < 2) {
979                 printf("Invalid BSSID command: needs two arguments (network "
980                        "id and BSSID)\n");
981                 return -1;
982         }
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         }
1001         return wpa_ctrl_command(ctrl, cmd);
1005 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1006                                      char *argv[])
1008         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1012 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1013                                       char *argv[])
1015         char cmd[32];
1016         int res;
1018         if (argc < 1) {
1019                 printf("Invalid SELECT_NETWORK command: needs one argument "
1020                        "(network id)\n");
1021                 return -1;
1022         }
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';
1029         return wpa_ctrl_command(ctrl, cmd);
1033 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1034                                       char *argv[])
1036         char cmd[32];
1037         int res;
1039         if (argc < 1) {
1040                 printf("Invalid ENABLE_NETWORK command: needs one argument "
1041                        "(network id)\n");
1042                 return -1;
1043         }
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';
1050         return wpa_ctrl_command(ctrl, cmd);
1054 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1055                                        char *argv[])
1057         char cmd[32];
1058         int res;
1060         if (argc < 1) {
1061                 printf("Invalid DISABLE_NETWORK command: needs one argument "
1062                        "(network id)\n");
1063                 return -1;
1064         }
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';
1071         return wpa_ctrl_command(ctrl, cmd);
1075 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1076                                    char *argv[])
1078         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1082 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1083                                       char *argv[])
1085         char cmd[32];
1086         int res;
1088         if (argc < 1) {
1089                 printf("Invalid REMOVE_NETWORK command: needs one argument "
1090                        "(network id)\n");
1091                 return -1;
1092         }
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';
1099         return wpa_ctrl_command(ctrl, cmd);
1103 static void wpa_cli_show_network_variables(void)
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");
1124 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1125                                    char *argv[])
1127         char cmd[256];
1128         int res;
1130         if (argc == 0) {
1131                 wpa_cli_show_network_variables();
1132                 return 0;
1133         }
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         }
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);
1151 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1152                                    char *argv[])
1154         char cmd[256];
1155         int res;
1157         if (argc == 0) {
1158                 wpa_cli_show_network_variables();
1159                 return 0;
1160         }
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         }
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);
1178 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1179                                   char *argv[])
1181         return wpa_ctrl_command(ctrl, "DISCONNECT");
1185 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1186                                   char *argv[])
1188         return wpa_ctrl_command(ctrl, "RECONNECT");
1192 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1193                                    char *argv[])
1195         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1199 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1201         return wpa_ctrl_command(ctrl, "SCAN");
1205 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1206                                     char *argv[])
1208         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1212 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1214         char cmd[64];
1215         int res;
1217         if (argc != 1) {
1218                 printf("Invalid BSS command: need one argument (index or "
1219                        "BSSID)\n");
1220                 return -1;
1221         }
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';
1228         return wpa_ctrl_command(ctrl, cmd);
1232 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1233                                       char *argv[])
1235         char cmd[64];
1236         int res;
1238         if (argc < 1 || argc > 2) {
1239                 printf("Invalid GET_CAPABILITY command: need either one or "
1240                        "two arguments\n");
1241                 return -1;
1242         }
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         }
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';
1256         return wpa_ctrl_command(ctrl, cmd);
1260 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1262         printf("Available interfaces:\n");
1263         return wpa_ctrl_command(ctrl, "INTERFACES");
1267 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1269         if (argc < 1) {
1270                 wpa_cli_list_interfaces(ctrl);
1271                 return 0;
1272         }
1274         wpa_cli_close_connection();
1275         os_free(ctrl_ifname);
1276         ctrl_ifname = os_strdup(argv[0]);
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;
1288 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1289                                    char *argv[])
1291         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1295 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1296                                  char *argv[])
1298         return wpa_ctrl_command(ctrl, "TERMINATE");
1302 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1303                                      char *argv[])
1305         char cmd[256];
1306         int res;
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         }
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);
1333 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1334                                         char *argv[])
1336         char cmd[128];
1337         int res;
1339         if (argc != 1) {
1340                 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1341                        "(interface name)\n");
1342                 return -1;
1343         }
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);
1353 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1354                                       char *argv[])
1356         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1360 #ifdef CONFIG_AP
1361 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
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);
1374 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1375                                 char *addr, size_t addr_len)
1377         char buf[4096], *pos;
1378         size_t len;
1379         int ret;
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         }
1396         buf[len] = '\0';
1397         if (memcmp(buf, "FAIL", 4) == 0)
1398                 return -1;
1399         printf("%s", buf);
1401         pos = buf;
1402         while (*pos != '\0' && *pos != '\n')
1403                 pos++;
1404         *pos = '\0';
1405         os_strlcpy(addr, buf, addr_len);
1406         return 0;
1410 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1412         char addr[32], cmd[64];
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);
1420         return -1;
1422 #endif /* CONFIG_AP */
1425 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1427         return wpa_ctrl_command(ctrl, "SUSPEND");
1431 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1433         return wpa_ctrl_command(ctrl, "RESUME");
1437 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1439         return wpa_ctrl_command(ctrl, "DROP_SA");
1443 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1445         char cmd[128];
1446         int res;
1448         if (argc != 1) {
1449                 printf("Invalid ROAM command: needs one argument "
1450                        "(target AP's BSSID)\n");
1451                 return -1;
1452         }
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);
1463 enum wpa_cli_cmd_flags {
1464         cli_cmd_flag_none               = 0x00,
1465         cli_cmd_flag_sensitive          = 0x01
1466 };
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 };
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 };
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)
1675         char c;
1676         size_t n;
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");
1688 static void print_help(void)
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], "  ");
1697 #ifdef CONFIG_READLINE
1698 static int cmd_has_sensitive_data(const char *cmd)
1700         const char *c, *delim;
1701         int n;
1702         size_t len;
1704         delim = os_strchr(cmd, ' ');
1705         if (delim)
1706                 len = delim - cmd;
1707         else
1708                 len = os_strlen(cmd);
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;
1717 #endif /* CONFIG_READLINE */
1720 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1722         struct wpa_cli_cmd *cmd, *match = NULL;
1723         int count;
1724         int ret = 0;
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         }
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         }
1761         return ret;
1765 static int str_match(const char *a, const char *b)
1767         return os_strncmp(a, b, os_strlen(b)) == 0;
1771 static int wpa_cli_exec(const char *program, const char *arg1,
1772                         const char *arg2)
1774         char *cmd;
1775         size_t len;
1776         int res;
1777         int ret = 0;
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);
1795         return ret;
1799 static void wpa_cli_action_process(const char *msg)
1801         const char *pos;
1802         char *copy = NULL, *id, *pos2;
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         }
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");
1820                 pos = os_strstr(pos, "[id=");
1821                 if (pos)
1822                         copy = os_strdup(pos + 4);
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                 }
1843                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
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         }
1862 #ifndef CONFIG_ANSI_C_EXTRA
1863 static void wpa_cli_action_cb(char *msg, size_t len)
1865         wpa_cli_action_process(msg);
1867 #endif /* CONFIG_ANSI_C_EXTRA */
1870 static void wpa_cli_reconnect(void)
1872         wpa_cli_close_connection();
1873         wpa_cli_open_connection(ctrl_ifname, 1);
1877 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1878                                  int action_monitor)
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         }
1908         if (wpa_ctrl_pending(ctrl) < 0) {
1909                 printf("Connection to wpa_supplicant lost - trying to "
1910                        "reconnect\n");
1911                 wpa_cli_reconnect();
1912         }
1916 #ifdef CONFIG_READLINE
1917 static char * wpa_cli_cmd_gen(const char *text, int state)
1919         static int i, len;
1920         const char *cmd;
1922         if (state == 0) {
1923                 i = 0;
1924                 len = os_strlen(text);
1925         }
1927         while ((cmd = wpa_cli_commands[i].cmd)) {
1928                 i++;
1929                 if (os_strncasecmp(cmd, text, len) == 0)
1930                         return strdup(cmd);
1931         }
1933         return NULL;
1937 static char * wpa_cli_dummy_gen(const char *text, int state)
1939         int i;
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         }
1953         rl_attempted_completion_over = 1;
1954         return NULL;
1958 static char * wpa_cli_status_gen(const char *text, int state)
1960         static int i, len;
1961         char *options[] = {
1962                 "verbose", NULL
1963         };
1964         char *t;
1966         if (state == 0) {
1967                 i = 0;
1968                 len = os_strlen(text);
1969         }
1971         while ((t = options[i])) {
1972                 i++;
1973                 if (os_strncasecmp(t, text, len) == 0)
1974                         return strdup(t);
1975         }
1977         rl_attempted_completion_over = 1;
1978         return NULL;
1982 static char ** wpa_cli_completion(const char *text, int start, int end)
1984         char * (*func)(const char *text, int state);
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);
1994 #endif /* CONFIG_READLINE */
1997 static void wpa_cli_interactive(void)
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 */
2006         printf("\nInteractive mode\n\n");
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 */
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);
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);
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 */
2126 static void wpa_cli_action(struct wpa_ctrl *ctrl)
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;
2138         fd = wpa_ctrl_get_fd(ctrl);
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                 }
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 */
2169 static void wpa_cli_cleanup(void)
2171         wpa_cli_close_connection();
2172         if (pid_file)
2173                 os_daemonize_terminate(pid_file);
2175         os_program_deinit();
2178 static void wpa_cli_terminate(int sig)
2180         wpa_cli_cleanup();
2181         exit(0);
2185 #ifdef CONFIG_WPA_CLI_FORK
2186 static void wpa_cli_usr1(int sig)
2188 #ifdef CONFIG_READLINE
2189         rl_on_new_line();
2190         rl_redisplay();
2191 #endif /* CONFIG_READLINE */
2193 #endif /* CONFIG_WPA_CLI_FORK */
2196 #ifndef CONFIG_NATIVE_WINDOWS
2197 static void wpa_cli_alarm(int sig)
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);
2210 #endif /* CONFIG_NATIVE_WINDOWS */
2213 static char * wpa_cli_get_default_ifname(void)
2215         char *ifname = NULL;
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 */
2242 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2243         char buf[2048], *pos;
2244         size_t len;
2245         struct wpa_ctrl *ctrl;
2246         int ret;
2248         ctrl = wpa_ctrl_open(NULL);
2249         if (ctrl == NULL)
2250                 return NULL;
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 */
2264         return ifname;
2268 int main(int argc, char *argv[])
2270         int warning_displayed = 0;
2271         int c;
2272         int daemonize = 0;
2273         int ret = 0;
2274         const char *global = NULL;
2276         if (os_program_init())
2277                 return -1;
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         }
2318         interactive = (argc == optind) && (action_file == NULL);
2320         if (interactive)
2321                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
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         }
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 */
2347         if (ctrl_ifname == NULL)
2348                 ctrl_ifname = wpa_cli_get_default_ifname();
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                         }
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                 }
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         }
2385         if (daemonize && os_daemonize(pid_file))
2386                 return -1;
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]);
2395         os_free(ctrl_ifname);
2396         wpa_cli_cleanup();
2398         return ret;
2401 #else /* CONFIG_CTRL_IFACE */
2402 int main(int argc, char *argv[])
2404         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2405         return -1;
2407 #endif /* CONFIG_CTRL_IFACE */