]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/blob - wpa_supplicant/wpa_cli.c
Re-initialize hostapd/wpa_supplicant git repository based on 0.6.3 release
[build-utilities/hostap.git] / wpa_supplicant / wpa_cli.c
1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2008, 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 */
27 #include "wpa_ctrl.h"
28 #include "common.h"
29 #include "version.h"
32 static const char *wpa_cli_version =
33 "wpa_cli v" VERSION_STR "\n"
34 "Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> and contributors";
37 static const char *wpa_cli_license =
38 "This program is free software. You can distribute it and/or modify it\n"
39 "under the terms of the GNU General Public License version 2.\n"
40 "\n"
41 "Alternatively, this software may be distributed under the terms of the\n"
42 "BSD license. See README and COPYING for more details.\n";
44 static const char *wpa_cli_full_license =
45 "This program is free software; you can redistribute it and/or modify\n"
46 "it under the terms of the GNU General Public License version 2 as\n"
47 "published by the Free Software Foundation.\n"
48 "\n"
49 "This program is distributed in the hope that it will be useful,\n"
50 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
52 "GNU General Public License for more details.\n"
53 "\n"
54 "You should have received a copy of the GNU General Public License\n"
55 "along with this program; if not, write to the Free Software\n"
56 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
57 "\n"
58 "Alternatively, this software may be distributed under the terms of the\n"
59 "BSD license.\n"
60 "\n"
61 "Redistribution and use in source and binary forms, with or without\n"
62 "modification, are permitted provided that the following conditions are\n"
63 "met:\n"
64 "\n"
65 "1. Redistributions of source code must retain the above copyright\n"
66 "   notice, this list of conditions and the following disclaimer.\n"
67 "\n"
68 "2. Redistributions in binary form must reproduce the above copyright\n"
69 "   notice, this list of conditions and the following disclaimer in the\n"
70 "   documentation and/or other materials provided with the distribution.\n"
71 "\n"
72 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73 "   names of its contributors may be used to endorse or promote products\n"
74 "   derived from this software without specific prior written permission.\n"
75 "\n"
76 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
87 "\n";
89 static const char *commands_help =
90 "commands:\n"
91 "  status [verbose] = get current WPA/EAPOL/EAP status\n"
92 "  mib = get MIB variables (dot1x, dot11)\n"
93 "  help = show this usage help\n"
94 "  interface [ifname] = show interfaces/select interface\n"
95 "  level <debug level> = change debug level\n"
96 "  license = show full wpa_cli license\n"
97 "  logoff = IEEE 802.1X EAPOL state machine logoff\n"
98 "  logon = IEEE 802.1X EAPOL state machine logon\n"
99 "  set = set variables (shows list of variables when run without arguments)\n"
100 "  pmksa = show PMKSA cache\n"
101 "  reassociate = force reassociation\n"
102 "  reconfigure = force wpa_supplicant to re-read its configuration file\n"
103 "  preauthenticate <BSSID> = force preauthentication\n"
104 "  identity <network id> <identity> = configure identity for an SSID\n"
105 "  password <network id> <password> = configure password for an SSID\n"
106 "  new_password <network id> <password> = change password for an SSID\n"
107 "  pin <network id> <pin> = configure pin for an SSID\n"
108 "  otp <network id> <password> = configure one-time-password for an SSID\n"
109 "  passphrase <network id> <passphrase> = configure private key passphrase\n"
110 "    for an SSID\n"
111 "  bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
112 "  list_networks = list configured networks\n"
113 "  select_network <network id> = select a network (disable others)\n"
114 "  enable_network <network id> = enable a network\n"
115 "  disable_network <network id> = disable a network\n"
116 "  add_network = add a network\n"
117 "  remove_network <network id> = remove a network\n"
118 "  set_network <network id> <variable> <value> = set network variables "
119 "(shows\n"
120 "    list of variables when run without arguments)\n"
121 "  get_network <network id> <variable> = get network variables\n"
122 "  save_config = save the current configuration\n"
123 "  disconnect = disconnect and wait for reassociate/reconnect command before\n "
124 "    connecting\n"
125 "  reconnect = like reassociate, but only takes effect if already "
126 "disconnected\n"
127 "  scan = request new BSS scan\n"
128 "  scan_results = get latest scan results\n"
129 "  bss <<idx> | <bssid>> = get detailed scan result info\n"
130 "  get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
131 "get capabilies\n"
132 "  ap_scan <value> = set ap_scan parameter\n"
133 "  stkstart <addr> = request STK negotiation with <addr>\n"
134 "  ft_ds <addr> = request over-the-DS FT with <addr>\n"
135 "  terminate = terminate wpa_supplicant\n"
136 "  quit = exit wpa_cli\n";
138 static struct wpa_ctrl *ctrl_conn;
139 static int wpa_cli_quit = 0;
140 static int wpa_cli_attached = 0;
141 static int wpa_cli_connected = 0;
142 static int wpa_cli_last_id = 0;
143 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
144 static char *ctrl_ifname = NULL;
145 static const char *pid_file = NULL;
146 static const char *action_file = NULL;
149 static void usage(void)
151         printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
152                "[-a<action file>] \\\n"
153                "        [-P<pid file>] [-g<global ctrl>]  [command..]\n"
154                "  -h = help (show this usage text)\n"
155                "  -v = shown version information\n"
156                "  -a = run in daemon mode executing the action file based on "
157                "events from\n"
158                "       wpa_supplicant\n"
159                "  -B = run a daemon in the background\n"
160                "  default path: /var/run/wpa_supplicant\n"
161                "  default interface: first interface found in socket path\n"
162                "%s",
163                commands_help);
167 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
169 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
170         ctrl_conn = wpa_ctrl_open(ifname);
171         return ctrl_conn;
172 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
173         char *cfile;
174         int flen, res;
176         if (ifname == NULL)
177                 return NULL;
179         flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
180         cfile = os_malloc(flen);
181         if (cfile == NULL)
182                 return NULL;
183         res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
184         if (res < 0 || res >= flen) {
185                 os_free(cfile);
186                 return NULL;
187         }
189         ctrl_conn = wpa_ctrl_open(cfile);
190         os_free(cfile);
191         return ctrl_conn;
192 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
196 static void wpa_cli_close_connection(void)
198         if (ctrl_conn == NULL)
199                 return;
201         if (wpa_cli_attached) {
202                 wpa_ctrl_detach(ctrl_conn);
203                 wpa_cli_attached = 0;
204         }
205         wpa_ctrl_close(ctrl_conn);
206         ctrl_conn = NULL;
210 static void wpa_cli_msg_cb(char *msg, size_t len)
212         printf("%s\n", msg);
216 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
218         char buf[2048];
219         size_t len;
220         int ret;
222         if (ctrl_conn == NULL) {
223                 printf("Not connected to wpa_supplicant - command dropped.\n");
224                 return -1;
225         }
226         len = sizeof(buf) - 1;
227         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
228                                wpa_cli_msg_cb);
229         if (ret == -2) {
230                 printf("'%s' command timed out.\n", cmd);
231                 return -2;
232         } else if (ret < 0) {
233                 printf("'%s' command failed.\n", cmd);
234                 return -1;
235         }
236         if (print) {
237                 buf[len] = '\0';
238                 printf("%s", buf);
239         }
240         return 0;
244 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
246         return _wpa_ctrl_command(ctrl, cmd, 1);
250 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
252         int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
253         return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
257 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
259         return wpa_ctrl_command(ctrl, "PING");
263 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
265         return wpa_ctrl_command(ctrl, "MIB");
269 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
271         return wpa_ctrl_command(ctrl, "PMKSA");
275 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
277         printf("%s", commands_help);
278         return 0;
282 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
284         printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
285         return 0;
289 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
291         wpa_cli_quit = 1;
292         return 0;
296 static void wpa_cli_show_variables(void)
298         printf("set variables:\n"
299                "  EAPOL::heldPeriod (EAPOL state machine held period, "
300                "in seconds)\n"
301                "  EAPOL::authPeriod (EAPOL state machine authentication "
302                "period, in seconds)\n"
303                "  EAPOL::startPeriod (EAPOL state machine start period, in "
304                "seconds)\n"
305                "  EAPOL::maxStart (EAPOL state machine maximum start "
306                "attempts)\n");
307         printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
308                "seconds)\n"
309                "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
310                " threshold\n\tpercentage)\n"
311                "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
312                "security\n\tassociation in seconds)\n");
316 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
318         char cmd[256];
319         int res;
321         if (argc == 0) {
322                 wpa_cli_show_variables();
323                 return 0;
324         }
326         if (argc != 2) {
327                 printf("Invalid SET command: needs two arguments (variable "
328                        "name and value)\n");
329                 return -1;
330         }
332         res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
333         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
334                 printf("Too long SET command.\n");
335                 return -1;
336         }
337         return wpa_ctrl_command(ctrl, cmd);
341 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
343         return wpa_ctrl_command(ctrl, "LOGOFF");
347 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
349         return wpa_ctrl_command(ctrl, "LOGON");
353 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
354                                    char *argv[])
356         return wpa_ctrl_command(ctrl, "REASSOCIATE");
360 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
361                                        char *argv[])
363         char cmd[256];
364         int res;
366         if (argc != 1) {
367                 printf("Invalid PREAUTH command: needs one argument "
368                        "(BSSID)\n");
369                 return -1;
370         }
372         res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
373         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
374                 printf("Too long PREAUTH command.\n");
375                 return -1;
376         }
377         return wpa_ctrl_command(ctrl, cmd);
381 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
383         char cmd[256];
384         int res;
386         if (argc != 1) {
387                 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
388                        "value)\n");
389                 return -1;
390         }
391         res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
392         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
393                 printf("Too long AP_SCAN command.\n");
394                 return -1;
395         }
396         return wpa_ctrl_command(ctrl, cmd);
400 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
401                                 char *argv[])
403         char cmd[256];
404         int res;
406         if (argc != 1) {
407                 printf("Invalid STKSTART command: needs one argument "
408                        "(Peer STA MAC address)\n");
409                 return -1;
410         }
412         res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
413         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
414                 printf("Too long STKSTART command.\n");
415                 return -1;
416         }
417         return wpa_ctrl_command(ctrl, cmd);
421 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
423         char cmd[256];
424         int res;
426         if (argc != 1) {
427                 printf("Invalid FT_DS command: needs one argument "
428                        "(Target AP MAC address)\n");
429                 return -1;
430         }
432         res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
433         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
434                 printf("Too long FT_DS command.\n");
435                 return -1;
436         }
437         return wpa_ctrl_command(ctrl, cmd);
441 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
443         char cmd[256];
444         int res;
446         if (argc != 1) {
447                 printf("Invalid LEVEL command: needs one argument (debug "
448                        "level)\n");
449                 return -1;
450         }
451         res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
452         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
453                 printf("Too long LEVEL command.\n");
454                 return -1;
455         }
456         return wpa_ctrl_command(ctrl, cmd);
460 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
462         char cmd[256], *pos, *end;
463         int i, ret;
465         if (argc < 2) {
466                 printf("Invalid IDENTITY command: needs two arguments "
467                        "(network id and identity)\n");
468                 return -1;
469         }
471         end = cmd + sizeof(cmd);
472         pos = cmd;
473         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
474                           argv[0], argv[1]);
475         if (ret < 0 || ret >= end - pos) {
476                 printf("Too long IDENTITY command.\n");
477                 return -1;
478         }
479         pos += ret;
480         for (i = 2; i < argc; i++) {
481                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
482                 if (ret < 0 || ret >= end - pos) {
483                         printf("Too long IDENTITY command.\n");
484                         return -1;
485                 }
486                 pos += ret;
487         }
489         return wpa_ctrl_command(ctrl, cmd);
493 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
495         char cmd[256], *pos, *end;
496         int i, ret;
498         if (argc < 2) {
499                 printf("Invalid PASSWORD command: needs two arguments "
500                        "(network id and password)\n");
501                 return -1;
502         }
504         end = cmd + sizeof(cmd);
505         pos = cmd;
506         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
507                           argv[0], argv[1]);
508         if (ret < 0 || ret >= end - pos) {
509                 printf("Too long PASSWORD command.\n");
510                 return -1;
511         }
512         pos += ret;
513         for (i = 2; i < argc; i++) {
514                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
515                 if (ret < 0 || ret >= end - pos) {
516                         printf("Too long PASSWORD command.\n");
517                         return -1;
518                 }
519                 pos += ret;
520         }
522         return wpa_ctrl_command(ctrl, cmd);
526 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
527                                     char *argv[])
529         char cmd[256], *pos, *end;
530         int i, ret;
532         if (argc < 2) {
533                 printf("Invalid NEW_PASSWORD command: needs two arguments "
534                        "(network id and password)\n");
535                 return -1;
536         }
538         end = cmd + sizeof(cmd);
539         pos = cmd;
540         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
541                           argv[0], argv[1]);
542         if (ret < 0 || ret >= end - pos) {
543                 printf("Too long NEW_PASSWORD command.\n");
544                 return -1;
545         }
546         pos += ret;
547         for (i = 2; i < argc; i++) {
548                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
549                 if (ret < 0 || ret >= end - pos) {
550                         printf("Too long NEW_PASSWORD command.\n");
551                         return -1;
552                 }
553                 pos += ret;
554         }
556         return wpa_ctrl_command(ctrl, cmd);
560 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
562         char cmd[256], *pos, *end;
563         int i, ret;
565         if (argc < 2) {
566                 printf("Invalid PIN command: needs two arguments "
567                        "(network id and pin)\n");
568                 return -1;
569         }
571         end = cmd + sizeof(cmd);
572         pos = cmd;
573         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
574                           argv[0], argv[1]);
575         if (ret < 0 || ret >= end - pos) {
576                 printf("Too long PIN command.\n");
577                 return -1;
578         }
579         pos += ret;
580         for (i = 2; i < argc; i++) {
581                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
582                 if (ret < 0 || ret >= end - pos) {
583                         printf("Too long PIN command.\n");
584                         return -1;
585                 }
586                 pos += ret;
587         }
588         return wpa_ctrl_command(ctrl, cmd);
592 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
594         char cmd[256], *pos, *end;
595         int i, ret;
597         if (argc < 2) {
598                 printf("Invalid OTP command: needs two arguments (network "
599                        "id and password)\n");
600                 return -1;
601         }
603         end = cmd + sizeof(cmd);
604         pos = cmd;
605         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
606                           argv[0], argv[1]);
607         if (ret < 0 || ret >= end - pos) {
608                 printf("Too long OTP command.\n");
609                 return -1;
610         }
611         pos += ret;
612         for (i = 2; i < argc; i++) {
613                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
614                 if (ret < 0 || ret >= end - pos) {
615                         printf("Too long OTP command.\n");
616                         return -1;
617                 }
618                 pos += ret;
619         }
621         return wpa_ctrl_command(ctrl, cmd);
625 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
626                                   char *argv[])
628         char cmd[256], *pos, *end;
629         int i, ret;
631         if (argc < 2) {
632                 printf("Invalid PASSPHRASE command: needs two arguments "
633                        "(network id and passphrase)\n");
634                 return -1;
635         }
637         end = cmd + sizeof(cmd);
638         pos = cmd;
639         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
640                           argv[0], argv[1]);
641         if (ret < 0 || ret >= end - pos) {
642                 printf("Too long PASSPHRASE command.\n");
643                 return -1;
644         }
645         pos += ret;
646         for (i = 2; i < argc; i++) {
647                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
648                 if (ret < 0 || ret >= end - pos) {
649                         printf("Too long PASSPHRASE command.\n");
650                         return -1;
651                 }
652                 pos += ret;
653         }
655         return wpa_ctrl_command(ctrl, cmd);
659 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
661         char cmd[256], *pos, *end;
662         int i, ret;
664         if (argc < 2) {
665                 printf("Invalid BSSID command: needs two arguments (network "
666                        "id and BSSID)\n");
667                 return -1;
668         }
670         end = cmd + sizeof(cmd);
671         pos = cmd;
672         ret = os_snprintf(pos, end - pos, "BSSID");
673         if (ret < 0 || ret >= end - pos) {
674                 printf("Too long BSSID command.\n");
675                 return -1;
676         }
677         pos += ret;
678         for (i = 0; i < argc; i++) {
679                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
680                 if (ret < 0 || ret >= end - pos) {
681                         printf("Too long BSSID command.\n");
682                         return -1;
683                 }
684                 pos += ret;
685         }
687         return wpa_ctrl_command(ctrl, cmd);
691 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
692                                      char *argv[])
694         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
698 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
699                                       char *argv[])
701         char cmd[32];
702         int res;
704         if (argc < 1) {
705                 printf("Invalid SELECT_NETWORK command: needs one argument "
706                        "(network id)\n");
707                 return -1;
708         }
710         res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
711         if (res < 0 || (size_t) res >= sizeof(cmd))
712                 return -1;
713         cmd[sizeof(cmd) - 1] = '\0';
715         return wpa_ctrl_command(ctrl, cmd);
719 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
720                                       char *argv[])
722         char cmd[32];
723         int res;
725         if (argc < 1) {
726                 printf("Invalid ENABLE_NETWORK command: needs one argument "
727                        "(network id)\n");
728                 return -1;
729         }
731         res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
732         if (res < 0 || (size_t) res >= sizeof(cmd))
733                 return -1;
734         cmd[sizeof(cmd) - 1] = '\0';
736         return wpa_ctrl_command(ctrl, cmd);
740 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
741                                        char *argv[])
743         char cmd[32];
744         int res;
746         if (argc < 1) {
747                 printf("Invalid DISABLE_NETWORK command: needs one argument "
748                        "(network id)\n");
749                 return -1;
750         }
752         res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
753         if (res < 0 || (size_t) res >= sizeof(cmd))
754                 return -1;
755         cmd[sizeof(cmd) - 1] = '\0';
757         return wpa_ctrl_command(ctrl, cmd);
761 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
762                                    char *argv[])
764         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
768 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
769                                       char *argv[])
771         char cmd[32];
772         int res;
774         if (argc < 1) {
775                 printf("Invalid REMOVE_NETWORK command: needs one argument "
776                        "(network id)\n");
777                 return -1;
778         }
780         res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
781         if (res < 0 || (size_t) res >= sizeof(cmd))
782                 return -1;
783         cmd[sizeof(cmd) - 1] = '\0';
785         return wpa_ctrl_command(ctrl, cmd);
789 static void wpa_cli_show_network_variables(void)
791         printf("set_network variables:\n"
792                "  ssid (network name, SSID)\n"
793                "  psk (WPA passphrase or pre-shared key)\n"
794                "  key_mgmt (key management protocol)\n"
795                "  identity (EAP identity)\n"
796                "  password (EAP password)\n"
797                "  ...\n"
798                "\n"
799                "Note: Values are entered in the same format as the "
800                "configuration file is using,\n"
801                "i.e., strings values need to be inside double quotation "
802                "marks.\n"
803                "For example: set_network 1 ssid \"network name\"\n"
804                "\n"
805                "Please see wpa_supplicant.conf documentation for full list "
806                "of\navailable variables.\n");
810 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
811                                    char *argv[])
813         char cmd[256];
814         int res;
816         if (argc == 0) {
817                 wpa_cli_show_network_variables();
818                 return 0;
819         }
821         if (argc != 3) {
822                 printf("Invalid SET_NETWORK command: needs three arguments\n"
823                        "(network id, variable name, and value)\n");
824                 return -1;
825         }
827         res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
828                           argv[0], argv[1], argv[2]);
829         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
830                 printf("Too long SET_NETWORK command.\n");
831                 return -1;
832         }
833         return wpa_ctrl_command(ctrl, cmd);
837 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
838                                    char *argv[])
840         char cmd[256];
841         int res;
843         if (argc == 0) {
844                 wpa_cli_show_network_variables();
845                 return 0;
846         }
848         if (argc != 2) {
849                 printf("Invalid GET_NETWORK command: needs two arguments\n"
850                        "(network id and variable name)\n");
851                 return -1;
852         }
854         res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
855                           argv[0], argv[1]);
856         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
857                 printf("Too long GET_NETWORK command.\n");
858                 return -1;
859         }
860         return wpa_ctrl_command(ctrl, cmd);
864 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
865                                   char *argv[])
867         return wpa_ctrl_command(ctrl, "DISCONNECT");
871 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
872                                   char *argv[])
874         return wpa_ctrl_command(ctrl, "RECONNECT");
878 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
879                                    char *argv[])
881         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
885 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
887         return wpa_ctrl_command(ctrl, "SCAN");
891 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
892                                     char *argv[])
894         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
898 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
900         char cmd[64];
901         int res;
903         if (argc != 1) {
904                 printf("Invalid BSS command: need one argument (index or "
905                        "BSSID)\n");
906                 return -1;
907         }
909         res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
910         if (res < 0 || (size_t) res >= sizeof(cmd))
911                 return -1;
912         cmd[sizeof(cmd) - 1] = '\0';
914         return wpa_ctrl_command(ctrl, cmd);
918 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
919                                       char *argv[])
921         char cmd[64];
922         int res;
924         if (argc < 1 || argc > 2) {
925                 printf("Invalid GET_CAPABILITY command: need either one or "
926                        "two arguments\n");
927                 return -1;
928         }
930         if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
931                 printf("Invalid GET_CAPABILITY command: second argument, "
932                        "if any, must be 'strict'\n");
933                 return -1;
934         }
936         res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
937                           (argc == 2) ? " strict" : "");
938         if (res < 0 || (size_t) res >= sizeof(cmd))
939                 return -1;
940         cmd[sizeof(cmd) - 1] = '\0';
942         return wpa_ctrl_command(ctrl, cmd);
946 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
948         printf("Available interfaces:\n");
949         return wpa_ctrl_command(ctrl, "INTERFACES");
953 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
955         if (argc < 1) {
956                 wpa_cli_list_interfaces(ctrl);
957                 return 0;
958         }
960         wpa_cli_close_connection();
961         os_free(ctrl_ifname);
962         ctrl_ifname = os_strdup(argv[0]);
964         if (wpa_cli_open_connection(ctrl_ifname)) {
965                 printf("Connected to interface '%s.\n", ctrl_ifname);
966                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
967                         wpa_cli_attached = 1;
968                 } else {
969                         printf("Warning: Failed to attach to "
970                                "wpa_supplicant.\n");
971                 }
972         } else {
973                 printf("Could not connect to interface '%s' - re-trying\n",
974                        ctrl_ifname);
975         }
976         return 0;
980 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
981                                    char *argv[])
983         return wpa_ctrl_command(ctrl, "RECONFIGURE");
987 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
988                                  char *argv[])
990         return wpa_ctrl_command(ctrl, "TERMINATE");
994 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
995                                      char *argv[])
997         char cmd[256];
998         int res;
1000         if (argc < 1) {
1001                 printf("Invalid INTERFACE_ADD command: needs at least one "
1002                        "argument (interface name)\n"
1003                        "All arguments: ifname confname driver ctrl_interface "
1004                        "driver_param bridge_name\n");
1005                 return -1;
1006         }
1008         /*
1009          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1010          * <driver_param>TAB<bridge_name>
1011          */
1012         res = os_snprintf(cmd, sizeof(cmd),
1013                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1014                           argv[0],
1015                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1016                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1017                           argc > 5 ? argv[5] : "");
1018         if (res < 0 || (size_t) res >= sizeof(cmd))
1019                 return -1;
1020         cmd[sizeof(cmd) - 1] = '\0';
1021         return wpa_ctrl_command(ctrl, cmd);
1025 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1026                                         char *argv[])
1028         char cmd[128];
1029         int res;
1031         if (argc != 1) {
1032                 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1033                        "(interface name)\n");
1034                 return -1;
1035         }
1037         res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1038         if (res < 0 || (size_t) res >= sizeof(cmd))
1039                 return -1;
1040         cmd[sizeof(cmd) - 1] = '\0';
1041         return wpa_ctrl_command(ctrl, cmd);
1045 struct wpa_cli_cmd {
1046         const char *cmd;
1047         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1048 };
1050 static struct wpa_cli_cmd wpa_cli_commands[] = {
1051         { "status", wpa_cli_cmd_status },
1052         { "ping", wpa_cli_cmd_ping },
1053         { "mib", wpa_cli_cmd_mib },
1054         { "help", wpa_cli_cmd_help },
1055         { "interface", wpa_cli_cmd_interface },
1056         { "level", wpa_cli_cmd_level },
1057         { "license", wpa_cli_cmd_license },
1058         { "quit", wpa_cli_cmd_quit },
1059         { "set", wpa_cli_cmd_set },
1060         { "logon", wpa_cli_cmd_logon },
1061         { "logoff", wpa_cli_cmd_logoff },
1062         { "pmksa", wpa_cli_cmd_pmksa },
1063         { "reassociate", wpa_cli_cmd_reassociate },
1064         { "preauthenticate", wpa_cli_cmd_preauthenticate },
1065         { "identity", wpa_cli_cmd_identity },
1066         { "password", wpa_cli_cmd_password },
1067         { "new_password", wpa_cli_cmd_new_password },
1068         { "pin", wpa_cli_cmd_pin },
1069         { "otp", wpa_cli_cmd_otp },
1070         { "passphrase", wpa_cli_cmd_passphrase },
1071         { "bssid", wpa_cli_cmd_bssid },
1072         { "list_networks", wpa_cli_cmd_list_networks },
1073         { "select_network", wpa_cli_cmd_select_network },
1074         { "enable_network", wpa_cli_cmd_enable_network },
1075         { "disable_network", wpa_cli_cmd_disable_network },
1076         { "add_network", wpa_cli_cmd_add_network },
1077         { "remove_network", wpa_cli_cmd_remove_network },
1078         { "set_network", wpa_cli_cmd_set_network },
1079         { "get_network", wpa_cli_cmd_get_network },
1080         { "save_config", wpa_cli_cmd_save_config },
1081         { "disconnect", wpa_cli_cmd_disconnect },
1082         { "reconnect", wpa_cli_cmd_reconnect },
1083         { "scan", wpa_cli_cmd_scan },
1084         { "scan_results", wpa_cli_cmd_scan_results },
1085         { "bss", wpa_cli_cmd_bss },
1086         { "get_capability", wpa_cli_cmd_get_capability },
1087         { "reconfigure", wpa_cli_cmd_reconfigure },
1088         { "terminate", wpa_cli_cmd_terminate },
1089         { "interface_add", wpa_cli_cmd_interface_add },
1090         { "interface_remove", wpa_cli_cmd_interface_remove },
1091         { "ap_scan", wpa_cli_cmd_ap_scan },
1092         { "stkstart", wpa_cli_cmd_stkstart },
1093         { "ft_ds", wpa_cli_cmd_ft_ds },
1094         { NULL, NULL }
1095 };
1098 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1100         struct wpa_cli_cmd *cmd, *match = NULL;
1101         int count;
1102         int ret = 0;
1104         count = 0;
1105         cmd = wpa_cli_commands;
1106         while (cmd->cmd) {
1107                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1108                 {
1109                         match = cmd;
1110                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1111                                 /* we have an exact match */
1112                                 count = 1;
1113                                 break;
1114                         }
1115                         count++;
1116                 }
1117                 cmd++;
1118         }
1120         if (count > 1) {
1121                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1122                 cmd = wpa_cli_commands;
1123                 while (cmd->cmd) {
1124                         if (os_strncasecmp(cmd->cmd, argv[0],
1125                                            os_strlen(argv[0])) == 0) {
1126                                 printf(" %s", cmd->cmd);
1127                         }
1128                         cmd++;
1129                 }
1130                 printf("\n");
1131                 ret = 1;
1132         } else if (count == 0) {
1133                 printf("Unknown command '%s'\n", argv[0]);
1134                 ret = 1;
1135         } else {
1136                 ret = match->handler(ctrl, argc - 1, &argv[1]);
1137         }
1139         return ret;
1143 static int str_match(const char *a, const char *b)
1145         return os_strncmp(a, b, os_strlen(b)) == 0;
1149 static int wpa_cli_exec(const char *program, const char *arg1,
1150                         const char *arg2)
1152         char *cmd;
1153         size_t len;
1154         int res;
1156         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1157         cmd = os_malloc(len);
1158         if (cmd == NULL)
1159                 return -1;
1160         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1161         if (res < 0 || (size_t) res >= len) {
1162                 os_free(cmd);
1163                 return -1;
1164         }
1165         cmd[len - 1] = '\0';
1166 #ifndef _WIN32_WCE
1167         system(cmd);
1168 #endif /* _WIN32_WCE */
1169         os_free(cmd);
1171         return 0;
1175 static void wpa_cli_action_process(const char *msg)
1177         const char *pos;
1178         char *copy = NULL, *id, *pos2;
1180         pos = msg;
1181         if (*pos == '<') {
1182                 /* skip priority */
1183                 pos = os_strchr(pos, '>');
1184                 if (pos)
1185                         pos++;
1186                 else
1187                         pos = msg;
1188         }
1190         if (str_match(pos, WPA_EVENT_CONNECTED)) {
1191                 int new_id = -1;
1192                 os_unsetenv("WPA_ID");
1193                 os_unsetenv("WPA_ID_STR");
1194                 os_unsetenv("WPA_CTRL_DIR");
1196                 pos = os_strstr(pos, "[id=");
1197                 if (pos)
1198                         copy = os_strdup(pos + 4);
1200                 if (copy) {
1201                         pos2 = id = copy;
1202                         while (*pos2 && *pos2 != ' ')
1203                                 pos2++;
1204                         *pos2++ = '\0';
1205                         new_id = atoi(id);
1206                         os_setenv("WPA_ID", id, 1);
1207                         while (*pos2 && *pos2 != '=')
1208                                 pos2++;
1209                         if (*pos2 == '=')
1210                                 pos2++;
1211                         id = pos2;
1212                         while (*pos2 && *pos2 != ']')
1213                                 pos2++;
1214                         *pos2 = '\0';
1215                         os_setenv("WPA_ID_STR", id, 1);
1216                         os_free(copy);
1217                 }
1219                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1221                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1222                         wpa_cli_connected = 1;
1223                         wpa_cli_last_id = new_id;
1224                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1225                 }
1226         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1227                 if (wpa_cli_connected) {
1228                         wpa_cli_connected = 0;
1229                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1230                 }
1231         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1232                 printf("wpa_supplicant is terminating - stop monitoring\n");
1233                 wpa_cli_quit = 1;
1234         }
1238 #ifndef CONFIG_ANSI_C_EXTRA
1239 static void wpa_cli_action_cb(char *msg, size_t len)
1241         wpa_cli_action_process(msg);
1243 #endif /* CONFIG_ANSI_C_EXTRA */
1246 static void wpa_cli_reconnect(void)
1248         wpa_cli_close_connection();
1249         ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1250         if (ctrl_conn) {
1251                 printf("Connection to wpa_supplicant re-established\n");
1252                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1253                         wpa_cli_attached = 1;
1254                 } else {
1255                         printf("Warning: Failed to attach to "
1256                                "wpa_supplicant.\n");
1257                 }
1258         }
1262 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1263                                  int action_monitor)
1265         int first = 1;
1266         if (ctrl_conn == NULL) {
1267                 wpa_cli_reconnect();
1268                 return;
1269         }
1270         while (wpa_ctrl_pending(ctrl) > 0) {
1271                 char buf[256];
1272                 size_t len = sizeof(buf) - 1;
1273                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1274                         buf[len] = '\0';
1275                         if (action_monitor)
1276                                 wpa_cli_action_process(buf);
1277                         else {
1278                                 if (in_read && first)
1279                                         printf("\n");
1280                                 first = 0;
1281                                 printf("%s\n", buf);
1282                         }
1283                 } else {
1284                         printf("Could not read pending message.\n");
1285                         break;
1286                 }
1287         }
1289         if (wpa_ctrl_pending(ctrl) < 0) {
1290                 printf("Connection to wpa_supplicant lost - trying to "
1291                        "reconnect\n");
1292                 wpa_cli_reconnect();
1293         }
1297 #ifdef CONFIG_READLINE
1298 static char * wpa_cli_cmd_gen(const char *text, int state)
1300         static int i, len;
1301         const char *cmd;
1303         if (state == 0) {
1304                 i = 0;
1305                 len = os_strlen(text);
1306         }
1308         while ((cmd = wpa_cli_commands[i].cmd)) {
1309                 i++;
1310                 if (os_strncasecmp(cmd, text, len) == 0)
1311                         return os_strdup(cmd);
1312         }
1314         return NULL;
1318 static char * wpa_cli_dummy_gen(const char *text, int state)
1320         return NULL;
1324 static char ** wpa_cli_completion(const char *text, int start, int end)
1326         return rl_completion_matches(text, start == 0 ?
1327                                      wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1329 #endif /* CONFIG_READLINE */
1332 static void wpa_cli_interactive(void)
1334 #define max_args 10
1335         char cmdbuf[256], *cmd, *argv[max_args], *pos;
1336         int argc;
1337 #ifdef CONFIG_READLINE
1338         char *home, *hfile = NULL;
1339 #endif /* CONFIG_READLINE */
1341         printf("\nInteractive mode\n\n");
1343 #ifdef CONFIG_READLINE
1344         rl_attempted_completion_function = wpa_cli_completion;
1345         home = getenv("HOME");
1346         if (home) {
1347                 const char *fname = ".wpa_cli_history";
1348                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1349                 hfile = os_malloc(hfile_len);
1350                 if (hfile) {
1351                         int res;
1352                         res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1353                                           fname);
1354                         if (res >= 0 && res < hfile_len) {
1355                                 hfile[hfile_len - 1] = '\0';
1356                                 read_history(hfile);
1357                                 stifle_history(100);
1358                         }
1359                 }
1360         }
1361 #endif /* CONFIG_READLINE */
1363         do {
1364                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1365 #ifndef CONFIG_NATIVE_WINDOWS
1366                 alarm(1);
1367 #endif /* CONFIG_NATIVE_WINDOWS */
1368 #ifdef CONFIG_READLINE
1369                 cmd = readline("> ");
1370                 if (cmd && *cmd) {
1371                         HIST_ENTRY *h;
1372                         while (next_history())
1373                                 ;
1374                         h = previous_history();
1375                         if (h == NULL || os_strcmp(cmd, h->line) != 0)
1376                                 add_history(cmd);
1377                         next_history();
1378                 }
1379 #else /* CONFIG_READLINE */
1380                 printf("> ");
1381                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1382 #endif /* CONFIG_READLINE */
1383 #ifndef CONFIG_NATIVE_WINDOWS
1384                 alarm(0);
1385 #endif /* CONFIG_NATIVE_WINDOWS */
1386                 if (cmd == NULL)
1387                         break;
1388                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1389                 pos = cmd;
1390                 while (*pos != '\0') {
1391                         if (*pos == '\n') {
1392                                 *pos = '\0';
1393                                 break;
1394                         }
1395                         pos++;
1396                 }
1397                 argc = 0;
1398                 pos = cmd;
1399                 for (;;) {
1400                         while (*pos == ' ')
1401                                 pos++;
1402                         if (*pos == '\0')
1403                                 break;
1404                         argv[argc] = pos;
1405                         argc++;
1406                         if (argc == max_args)
1407                                 break;
1408                         if (*pos == '"') {
1409                                 char *pos2 = os_strrchr(pos, '"');
1410                                 if (pos2)
1411                                         pos = pos2 + 1;
1412                         }
1413                         while (*pos != '\0' && *pos != ' ')
1414                                 pos++;
1415                         if (*pos == ' ')
1416                                 *pos++ = '\0';
1417                 }
1418                 if (argc)
1419                         wpa_request(ctrl_conn, argc, argv);
1421                 if (cmd != cmdbuf)
1422                         os_free(cmd);
1423         } while (!wpa_cli_quit);
1425 #ifdef CONFIG_READLINE
1426         if (hfile) {
1427                 /* Save command history, excluding lines that may contain
1428                  * passwords. */
1429                 HIST_ENTRY *h;
1430                 history_set_pos(0);
1431                 h = next_history();
1432                 while (h) {
1433                         char *p = h->line;
1434                         while (*p == ' ' || *p == '\t')
1435                                 p++;
1436                         if (os_strncasecmp(p, "pa", 2) == 0 ||
1437                             os_strncasecmp(p, "o", 1) == 0 ||
1438                             os_strncasecmp(p, "n", 1)) {
1439                                 h = remove_history(where_history());
1440                                 if (h) {
1441                                         os_free(h->line);
1442                                         os_free(h->data);
1443                                         os_free(h);
1444                                 }
1445                                 h = current_history();
1446                         } else {
1447                                 h = next_history();
1448                         }
1449                 }
1450                 write_history(hfile);
1451                 os_free(hfile);
1452         }
1453 #endif /* CONFIG_READLINE */
1457 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1459 #ifdef CONFIG_ANSI_C_EXTRA
1460         /* TODO: ANSI C version(?) */
1461         printf("Action processing not supported in ANSI C build.\n");
1462 #else /* CONFIG_ANSI_C_EXTRA */
1463         fd_set rfds;
1464         int fd, res;
1465         struct timeval tv;
1466         char buf[256]; /* note: large enough to fit in unsolicited messages */
1467         size_t len;
1469         fd = wpa_ctrl_get_fd(ctrl);
1471         while (!wpa_cli_quit) {
1472                 FD_ZERO(&rfds);
1473                 FD_SET(fd, &rfds);
1474                 tv.tv_sec = 2;
1475                 tv.tv_usec = 0;
1476                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1477                 if (res < 0 && errno != EINTR) {
1478                         perror("select");
1479                         break;
1480                 }
1482                 if (FD_ISSET(fd, &rfds))
1483                         wpa_cli_recv_pending(ctrl, 0, 1);
1484                 else {
1485                         /* verify that connection is still working */
1486                         len = sizeof(buf) - 1;
1487                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1488                                              wpa_cli_action_cb) < 0 ||
1489                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1490                                 printf("wpa_supplicant did not reply to PING "
1491                                        "command - exiting\n");
1492                                 break;
1493                         }
1494                 }
1495         }
1496 #endif /* CONFIG_ANSI_C_EXTRA */
1500 static void wpa_cli_cleanup(void)
1502         wpa_cli_close_connection();
1503         if (pid_file)
1504                 os_daemonize_terminate(pid_file);
1506         os_program_deinit();
1509 static void wpa_cli_terminate(int sig)
1511         wpa_cli_cleanup();
1512         exit(0);
1516 #ifndef CONFIG_NATIVE_WINDOWS
1517 static void wpa_cli_alarm(int sig)
1519         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1520                 printf("Connection to wpa_supplicant lost - trying to "
1521                        "reconnect\n");
1522                 wpa_cli_close_connection();
1523         }
1524         if (!ctrl_conn)
1525                 wpa_cli_reconnect();
1526         if (ctrl_conn)
1527                 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1528         alarm(1);
1530 #endif /* CONFIG_NATIVE_WINDOWS */
1533 static char * wpa_cli_get_default_ifname(void)
1535         char *ifname = NULL;
1537 #ifdef CONFIG_CTRL_IFACE_UNIX
1538         struct dirent *dent;
1539         DIR *dir = opendir(ctrl_iface_dir);
1540         if (!dir)
1541                 return NULL;
1542         while ((dent = readdir(dir))) {
1543 #ifdef _DIRENT_HAVE_D_TYPE
1544                 /*
1545                  * Skip the file if it is not a socket. Also accept
1546                  * DT_UNKNOWN (0) in case the C library or underlying
1547                  * file system does not support d_type.
1548                  */
1549                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1550                         continue;
1551 #endif /* _DIRENT_HAVE_D_TYPE */
1552                 if (os_strcmp(dent->d_name, ".") == 0 ||
1553                     os_strcmp(dent->d_name, "..") == 0)
1554                         continue;
1555                 printf("Selected interface '%s'\n", dent->d_name);
1556                 ifname = os_strdup(dent->d_name);
1557                 break;
1558         }
1559         closedir(dir);
1560 #endif /* CONFIG_CTRL_IFACE_UNIX */
1562 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1563         char buf[2048], *pos;
1564         size_t len;
1565         struct wpa_ctrl *ctrl;
1566         int ret;
1568         ctrl = wpa_ctrl_open(NULL);
1569         if (ctrl == NULL)
1570                 return NULL;
1572         len = sizeof(buf) - 1;
1573         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1574         if (ret >= 0) {
1575                 buf[len] = '\0';
1576                 pos = os_strchr(buf, '\n');
1577                 if (pos)
1578                         *pos = '\0';
1579                 ifname = os_strdup(buf);
1580         }
1581         wpa_ctrl_close(ctrl);
1582 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1584         return ifname;
1588 int main(int argc, char *argv[])
1590         int interactive;
1591         int warning_displayed = 0;
1592         int c;
1593         int daemonize = 0;
1594         int ret = 0;
1595         const char *global = NULL;
1597         if (os_program_init())
1598                 return -1;
1600         for (;;) {
1601                 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1602                 if (c < 0)
1603                         break;
1604                 switch (c) {
1605                 case 'a':
1606                         action_file = optarg;
1607                         break;
1608                 case 'B':
1609                         daemonize = 1;
1610                         break;
1611                 case 'g':
1612                         global = optarg;
1613                         break;
1614                 case 'h':
1615                         usage();
1616                         return 0;
1617                 case 'v':
1618                         printf("%s\n", wpa_cli_version);
1619                         return 0;
1620                 case 'i':
1621                         os_free(ctrl_ifname);
1622                         ctrl_ifname = os_strdup(optarg);
1623                         break;
1624                 case 'p':
1625                         ctrl_iface_dir = optarg;
1626                         break;
1627                 case 'P':
1628                         pid_file = optarg;
1629                         break;
1630                 default:
1631                         usage();
1632                         return -1;
1633                 }
1634         }
1636         interactive = (argc == optind) && (action_file == NULL);
1638         if (interactive)
1639                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1641         if (global) {
1642 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1643                 ctrl_conn = wpa_ctrl_open(NULL);
1644 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1645                 ctrl_conn = wpa_ctrl_open(global);
1646 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1647                 if (ctrl_conn == NULL) {
1648                         perror("Failed to connect to wpa_supplicant - "
1649                                "wpa_ctrl_open");
1650                         return -1;
1651                 }
1652         }
1654         for (; !global;) {
1655                 if (ctrl_ifname == NULL)
1656                         ctrl_ifname = wpa_cli_get_default_ifname();
1657                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1658                 if (ctrl_conn) {
1659                         if (warning_displayed)
1660                                 printf("Connection established.\n");
1661                         break;
1662                 }
1664                 if (!interactive) {
1665                         perror("Failed to connect to wpa_supplicant - "
1666                                "wpa_ctrl_open");
1667                         return -1;
1668                 }
1670                 if (!warning_displayed) {
1671                         printf("Could not connect to wpa_supplicant - "
1672                                "re-trying\n");
1673                         warning_displayed = 1;
1674                 }
1675                 os_sleep(1, 0);
1676                 continue;
1677         }
1679 #ifndef _WIN32_WCE
1680         signal(SIGINT, wpa_cli_terminate);
1681         signal(SIGTERM, wpa_cli_terminate);
1682 #endif /* _WIN32_WCE */
1683 #ifndef CONFIG_NATIVE_WINDOWS
1684         signal(SIGALRM, wpa_cli_alarm);
1685 #endif /* CONFIG_NATIVE_WINDOWS */
1687         if (interactive || action_file) {
1688                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1689                         wpa_cli_attached = 1;
1690                 } else {
1691                         printf("Warning: Failed to attach to "
1692                                "wpa_supplicant.\n");
1693                         if (!interactive)
1694                                 return -1;
1695                 }
1696         }
1698         if (daemonize && os_daemonize(pid_file))
1699                 return -1;
1701         if (interactive)
1702                 wpa_cli_interactive();
1703         else if (action_file)
1704                 wpa_cli_action(ctrl_conn);
1705         else
1706                 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1708         os_free(ctrl_ifname);
1709         wpa_cli_cleanup();
1711         return ret;
1714 #else /* CONFIG_CTRL_IFACE */
1715 int main(int argc, char *argv[])
1717         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1718         return -1;
1720 #endif /* CONFIG_CTRL_IFACE */