Remove the unwanted Windows console from the Windows binary version of wpa_gui
[libeap.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  */
14
15 #include "includes.h"
16
17 #ifdef CONFIG_CTRL_IFACE
18
19 #ifdef CONFIG_CTRL_IFACE_UNIX
20 #include <dirent.h>
21 #endif /* CONFIG_CTRL_IFACE_UNIX */
22 #ifdef CONFIG_READLINE
23 #include <readline/readline.h>
24 #include <readline/history.h>
25 #endif /* CONFIG_READLINE */
26
27 #include "wpa_ctrl.h"
28 #include "common.h"
29 #include "version.h"
30
31
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";
35
36
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";
43
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";
88
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";
137
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;
147
148
149 static void usage(void)
150 {
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);
164 }
165
166
167 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
168 {
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;
175
176         if (ifname == NULL)
177                 return NULL;
178
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         }
188
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 */
193 }
194
195
196 static void wpa_cli_close_connection(void)
197 {
198         if (ctrl_conn == NULL)
199                 return;
200
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;
207 }
208
209
210 static void wpa_cli_msg_cb(char *msg, size_t len)
211 {
212         printf("%s\n", msg);
213 }
214
215
216 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
217 {
218         char buf[2048];
219         size_t len;
220         int ret;
221
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;
241 }
242
243
244 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
245 {
246         return _wpa_ctrl_command(ctrl, cmd, 1);
247 }
248
249
250 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
251 {
252         int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
253         return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
254 }
255
256
257 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
258 {
259         return wpa_ctrl_command(ctrl, "PING");
260 }
261
262
263 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
264 {
265         return wpa_ctrl_command(ctrl, "MIB");
266 }
267
268
269 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
270 {
271         return wpa_ctrl_command(ctrl, "PMKSA");
272 }
273
274
275 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
276 {
277         printf("%s", commands_help);
278         return 0;
279 }
280
281
282 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
283 {
284         printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
285         return 0;
286 }
287
288
289 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
290 {
291         wpa_cli_quit = 1;
292         return 0;
293 }
294
295
296 static void wpa_cli_show_variables(void)
297 {
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");
313 }
314
315
316 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
317 {
318         char cmd[256];
319         int res;
320
321         if (argc == 0) {
322                 wpa_cli_show_variables();
323                 return 0;
324         }
325
326         if (argc != 2) {
327                 printf("Invalid SET command: needs two arguments (variable "
328                        "name and value)\n");
329                 return -1;
330         }
331
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);
338 }
339
340
341 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
342 {
343         return wpa_ctrl_command(ctrl, "LOGOFF");
344 }
345
346
347 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
348 {
349         return wpa_ctrl_command(ctrl, "LOGON");
350 }
351
352
353 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
354                                    char *argv[])
355 {
356         return wpa_ctrl_command(ctrl, "REASSOCIATE");
357 }
358
359
360 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
361                                        char *argv[])
362 {
363         char cmd[256];
364         int res;
365
366         if (argc != 1) {
367                 printf("Invalid PREAUTH command: needs one argument "
368                        "(BSSID)\n");
369                 return -1;
370         }
371
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);
378 }
379
380
381 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
382 {
383         char cmd[256];
384         int res;
385
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);
397 }
398
399
400 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
401                                 char *argv[])
402 {
403         char cmd[256];
404         int res;
405
406         if (argc != 1) {
407                 printf("Invalid STKSTART command: needs one argument "
408                        "(Peer STA MAC address)\n");
409                 return -1;
410         }
411
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);
418 }
419
420
421 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
422 {
423         char cmd[256];
424         int res;
425
426         if (argc != 1) {
427                 printf("Invalid FT_DS command: needs one argument "
428                        "(Target AP MAC address)\n");
429                 return -1;
430         }
431
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);
438 }
439
440
441 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
442 {
443         char cmd[256];
444         int res;
445
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);
457 }
458
459
460 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
461 {
462         char cmd[256], *pos, *end;
463         int i, ret;
464
465         if (argc < 2) {
466                 printf("Invalid IDENTITY command: needs two arguments "
467                        "(network id and identity)\n");
468                 return -1;
469         }
470
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         }
488
489         return wpa_ctrl_command(ctrl, cmd);
490 }
491
492
493 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
494 {
495         char cmd[256], *pos, *end;
496         int i, ret;
497
498         if (argc < 2) {
499                 printf("Invalid PASSWORD command: needs two arguments "
500                        "(network id and password)\n");
501                 return -1;
502         }
503
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         }
521
522         return wpa_ctrl_command(ctrl, cmd);
523 }
524
525
526 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
527                                     char *argv[])
528 {
529         char cmd[256], *pos, *end;
530         int i, ret;
531
532         if (argc < 2) {
533                 printf("Invalid NEW_PASSWORD command: needs two arguments "
534                        "(network id and password)\n");
535                 return -1;
536         }
537
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         }
555
556         return wpa_ctrl_command(ctrl, cmd);
557 }
558
559
560 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
561 {
562         char cmd[256], *pos, *end;
563         int i, ret;
564
565         if (argc < 2) {
566                 printf("Invalid PIN command: needs two arguments "
567                        "(network id and pin)\n");
568                 return -1;
569         }
570
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);
589 }
590
591
592 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
593 {
594         char cmd[256], *pos, *end;
595         int i, ret;
596
597         if (argc < 2) {
598                 printf("Invalid OTP command: needs two arguments (network "
599                        "id and password)\n");
600                 return -1;
601         }
602
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         }
620
621         return wpa_ctrl_command(ctrl, cmd);
622 }
623
624
625 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
626                                   char *argv[])
627 {
628         char cmd[256], *pos, *end;
629         int i, ret;
630
631         if (argc < 2) {
632                 printf("Invalid PASSPHRASE command: needs two arguments "
633                        "(network id and passphrase)\n");
634                 return -1;
635         }
636
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         }
654
655         return wpa_ctrl_command(ctrl, cmd);
656 }
657
658
659 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
660 {
661         char cmd[256], *pos, *end;
662         int i, ret;
663
664         if (argc < 2) {
665                 printf("Invalid BSSID command: needs two arguments (network "
666                        "id and BSSID)\n");
667                 return -1;
668         }
669
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         }
686
687         return wpa_ctrl_command(ctrl, cmd);
688 }
689
690
691 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
692                                      char *argv[])
693 {
694         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
695 }
696
697
698 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
699                                       char *argv[])
700 {
701         char cmd[32];
702         int res;
703
704         if (argc < 1) {
705                 printf("Invalid SELECT_NETWORK command: needs one argument "
706                        "(network id)\n");
707                 return -1;
708         }
709
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';
714
715         return wpa_ctrl_command(ctrl, cmd);
716 }
717
718
719 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
720                                       char *argv[])
721 {
722         char cmd[32];
723         int res;
724
725         if (argc < 1) {
726                 printf("Invalid ENABLE_NETWORK command: needs one argument "
727                        "(network id)\n");
728                 return -1;
729         }
730
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';
735
736         return wpa_ctrl_command(ctrl, cmd);
737 }
738
739
740 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
741                                        char *argv[])
742 {
743         char cmd[32];
744         int res;
745
746         if (argc < 1) {
747                 printf("Invalid DISABLE_NETWORK command: needs one argument "
748                        "(network id)\n");
749                 return -1;
750         }
751
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';
756
757         return wpa_ctrl_command(ctrl, cmd);
758 }
759
760
761 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
762                                    char *argv[])
763 {
764         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
765 }
766
767
768 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
769                                       char *argv[])
770 {
771         char cmd[32];
772         int res;
773
774         if (argc < 1) {
775                 printf("Invalid REMOVE_NETWORK command: needs one argument "
776                        "(network id)\n");
777                 return -1;
778         }
779
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';
784
785         return wpa_ctrl_command(ctrl, cmd);
786 }
787
788
789 static void wpa_cli_show_network_variables(void)
790 {
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");
807 }
808
809
810 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
811                                    char *argv[])
812 {
813         char cmd[256];
814         int res;
815
816         if (argc == 0) {
817                 wpa_cli_show_network_variables();
818                 return 0;
819         }
820
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         }
826
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);
834 }
835
836
837 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
838                                    char *argv[])
839 {
840         char cmd[256];
841         int res;
842
843         if (argc == 0) {
844                 wpa_cli_show_network_variables();
845                 return 0;
846         }
847
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         }
853
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);
861 }
862
863
864 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
865                                   char *argv[])
866 {
867         return wpa_ctrl_command(ctrl, "DISCONNECT");
868 }
869
870
871 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
872                                   char *argv[])
873 {
874         return wpa_ctrl_command(ctrl, "RECONNECT");
875 }
876
877
878 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
879                                    char *argv[])
880 {
881         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
882 }
883
884
885 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
886 {
887         return wpa_ctrl_command(ctrl, "SCAN");
888 }
889
890
891 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
892                                     char *argv[])
893 {
894         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
895 }
896
897
898 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
899 {
900         char cmd[64];
901         int res;
902
903         if (argc != 1) {
904                 printf("Invalid BSS command: need one argument (index or "
905                        "BSSID)\n");
906                 return -1;
907         }
908
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';
913
914         return wpa_ctrl_command(ctrl, cmd);
915 }
916
917
918 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
919                                       char *argv[])
920 {
921         char cmd[64];
922         int res;
923
924         if (argc < 1 || argc > 2) {
925                 printf("Invalid GET_CAPABILITY command: need either one or "
926                        "two arguments\n");
927                 return -1;
928         }
929
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         }
935
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';
941
942         return wpa_ctrl_command(ctrl, cmd);
943 }
944
945
946 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
947 {
948         printf("Available interfaces:\n");
949         return wpa_ctrl_command(ctrl, "INTERFACES");
950 }
951
952
953 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
954 {
955         if (argc < 1) {
956                 wpa_cli_list_interfaces(ctrl);
957                 return 0;
958         }
959
960         wpa_cli_close_connection();
961         os_free(ctrl_ifname);
962         ctrl_ifname = os_strdup(argv[0]);
963
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;
977 }
978
979
980 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
981                                    char *argv[])
982 {
983         return wpa_ctrl_command(ctrl, "RECONFIGURE");
984 }
985
986
987 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
988                                  char *argv[])
989 {
990         return wpa_ctrl_command(ctrl, "TERMINATE");
991 }
992
993
994 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
995                                      char *argv[])
996 {
997         char cmd[256];
998         int res;
999
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         }
1007
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);
1022 }
1023
1024
1025 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1026                                         char *argv[])
1027 {
1028         char cmd[128];
1029         int res;
1030
1031         if (argc != 1) {
1032                 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1033                        "(interface name)\n");
1034                 return -1;
1035         }
1036
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);
1042 }
1043
1044
1045 struct wpa_cli_cmd {
1046         const char *cmd;
1047         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1048 };
1049
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 };
1096
1097
1098 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099 {
1100         struct wpa_cli_cmd *cmd, *match = NULL;
1101         int count;
1102         int ret = 0;
1103
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         }
1119
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         }
1138
1139         return ret;
1140 }
1141
1142
1143 static int str_match(const char *a, const char *b)
1144 {
1145         return os_strncmp(a, b, os_strlen(b)) == 0;
1146 }
1147
1148
1149 static int wpa_cli_exec(const char *program, const char *arg1,
1150                         const char *arg2)
1151 {
1152         char *cmd;
1153         size_t len;
1154         int res;
1155         int ret = 0;
1156
1157         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1158         cmd = os_malloc(len);
1159         if (cmd == NULL)
1160                 return -1;
1161         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1162         if (res < 0 || (size_t) res >= len) {
1163                 os_free(cmd);
1164                 return -1;
1165         }
1166         cmd[len - 1] = '\0';
1167 #ifndef _WIN32_WCE
1168         if (system(cmd) < 0)
1169                 ret = -1;
1170 #endif /* _WIN32_WCE */
1171         os_free(cmd);
1172
1173         return ret;
1174 }
1175
1176
1177 static void wpa_cli_action_process(const char *msg)
1178 {
1179         const char *pos;
1180         char *copy = NULL, *id, *pos2;
1181
1182         pos = msg;
1183         if (*pos == '<') {
1184                 /* skip priority */
1185                 pos = os_strchr(pos, '>');
1186                 if (pos)
1187                         pos++;
1188                 else
1189                         pos = msg;
1190         }
1191
1192         if (str_match(pos, WPA_EVENT_CONNECTED)) {
1193                 int new_id = -1;
1194                 os_unsetenv("WPA_ID");
1195                 os_unsetenv("WPA_ID_STR");
1196                 os_unsetenv("WPA_CTRL_DIR");
1197
1198                 pos = os_strstr(pos, "[id=");
1199                 if (pos)
1200                         copy = os_strdup(pos + 4);
1201
1202                 if (copy) {
1203                         pos2 = id = copy;
1204                         while (*pos2 && *pos2 != ' ')
1205                                 pos2++;
1206                         *pos2++ = '\0';
1207                         new_id = atoi(id);
1208                         os_setenv("WPA_ID", id, 1);
1209                         while (*pos2 && *pos2 != '=')
1210                                 pos2++;
1211                         if (*pos2 == '=')
1212                                 pos2++;
1213                         id = pos2;
1214                         while (*pos2 && *pos2 != ']')
1215                                 pos2++;
1216                         *pos2 = '\0';
1217                         os_setenv("WPA_ID_STR", id, 1);
1218                         os_free(copy);
1219                 }
1220
1221                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1222
1223                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1224                         wpa_cli_connected = 1;
1225                         wpa_cli_last_id = new_id;
1226                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1227                 }
1228         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1229                 if (wpa_cli_connected) {
1230                         wpa_cli_connected = 0;
1231                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1232                 }
1233         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1234                 printf("wpa_supplicant is terminating - stop monitoring\n");
1235                 wpa_cli_quit = 1;
1236         }
1237 }
1238
1239
1240 #ifndef CONFIG_ANSI_C_EXTRA
1241 static void wpa_cli_action_cb(char *msg, size_t len)
1242 {
1243         wpa_cli_action_process(msg);
1244 }
1245 #endif /* CONFIG_ANSI_C_EXTRA */
1246
1247
1248 static void wpa_cli_reconnect(void)
1249 {
1250         wpa_cli_close_connection();
1251         ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1252         if (ctrl_conn) {
1253                 printf("Connection to wpa_supplicant re-established\n");
1254                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1255                         wpa_cli_attached = 1;
1256                 } else {
1257                         printf("Warning: Failed to attach to "
1258                                "wpa_supplicant.\n");
1259                 }
1260         }
1261 }
1262
1263
1264 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1265                                  int action_monitor)
1266 {
1267         int first = 1;
1268         if (ctrl_conn == NULL) {
1269                 wpa_cli_reconnect();
1270                 return;
1271         }
1272         while (wpa_ctrl_pending(ctrl) > 0) {
1273                 char buf[256];
1274                 size_t len = sizeof(buf) - 1;
1275                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1276                         buf[len] = '\0';
1277                         if (action_monitor)
1278                                 wpa_cli_action_process(buf);
1279                         else {
1280                                 if (in_read && first)
1281                                         printf("\n");
1282                                 first = 0;
1283                                 printf("%s\n", buf);
1284                         }
1285                 } else {
1286                         printf("Could not read pending message.\n");
1287                         break;
1288                 }
1289         }
1290
1291         if (wpa_ctrl_pending(ctrl) < 0) {
1292                 printf("Connection to wpa_supplicant lost - trying to "
1293                        "reconnect\n");
1294                 wpa_cli_reconnect();
1295         }
1296 }
1297
1298
1299 #ifdef CONFIG_READLINE
1300 static char * wpa_cli_cmd_gen(const char *text, int state)
1301 {
1302         static int i, len;
1303         const char *cmd;
1304
1305         if (state == 0) {
1306                 i = 0;
1307                 len = os_strlen(text);
1308         }
1309
1310         while ((cmd = wpa_cli_commands[i].cmd)) {
1311                 i++;
1312                 if (os_strncasecmp(cmd, text, len) == 0)
1313                         return os_strdup(cmd);
1314         }
1315
1316         return NULL;
1317 }
1318
1319
1320 static char * wpa_cli_dummy_gen(const char *text, int state)
1321 {
1322         return NULL;
1323 }
1324
1325
1326 static char ** wpa_cli_completion(const char *text, int start, int end)
1327 {
1328         return rl_completion_matches(text, start == 0 ?
1329                                      wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1330 }
1331 #endif /* CONFIG_READLINE */
1332
1333
1334 static void wpa_cli_interactive(void)
1335 {
1336 #define max_args 10
1337         char cmdbuf[256], *cmd, *argv[max_args], *pos;
1338         int argc;
1339 #ifdef CONFIG_READLINE
1340         char *home, *hfile = NULL;
1341 #endif /* CONFIG_READLINE */
1342
1343         printf("\nInteractive mode\n\n");
1344
1345 #ifdef CONFIG_READLINE
1346         rl_attempted_completion_function = wpa_cli_completion;
1347         home = getenv("HOME");
1348         if (home) {
1349                 const char *fname = ".wpa_cli_history";
1350                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1351                 hfile = os_malloc(hfile_len);
1352                 if (hfile) {
1353                         int res;
1354                         res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1355                                           fname);
1356                         if (res >= 0 && res < hfile_len) {
1357                                 hfile[hfile_len - 1] = '\0';
1358                                 read_history(hfile);
1359                                 stifle_history(100);
1360                         }
1361                 }
1362         }
1363 #endif /* CONFIG_READLINE */
1364
1365         do {
1366                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1367 #ifndef CONFIG_NATIVE_WINDOWS
1368                 alarm(1);
1369 #endif /* CONFIG_NATIVE_WINDOWS */
1370 #ifdef CONFIG_READLINE
1371                 cmd = readline("> ");
1372                 if (cmd && *cmd) {
1373                         HIST_ENTRY *h;
1374                         while (next_history())
1375                                 ;
1376                         h = previous_history();
1377                         if (h == NULL || os_strcmp(cmd, h->line) != 0)
1378                                 add_history(cmd);
1379                         next_history();
1380                 }
1381 #else /* CONFIG_READLINE */
1382                 printf("> ");
1383                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1384 #endif /* CONFIG_READLINE */
1385 #ifndef CONFIG_NATIVE_WINDOWS
1386                 alarm(0);
1387 #endif /* CONFIG_NATIVE_WINDOWS */
1388                 if (cmd == NULL)
1389                         break;
1390                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1391                 pos = cmd;
1392                 while (*pos != '\0') {
1393                         if (*pos == '\n') {
1394                                 *pos = '\0';
1395                                 break;
1396                         }
1397                         pos++;
1398                 }
1399                 argc = 0;
1400                 pos = cmd;
1401                 for (;;) {
1402                         while (*pos == ' ')
1403                                 pos++;
1404                         if (*pos == '\0')
1405                                 break;
1406                         argv[argc] = pos;
1407                         argc++;
1408                         if (argc == max_args)
1409                                 break;
1410                         if (*pos == '"') {
1411                                 char *pos2 = os_strrchr(pos, '"');
1412                                 if (pos2)
1413                                         pos = pos2 + 1;
1414                         }
1415                         while (*pos != '\0' && *pos != ' ')
1416                                 pos++;
1417                         if (*pos == ' ')
1418                                 *pos++ = '\0';
1419                 }
1420                 if (argc)
1421                         wpa_request(ctrl_conn, argc, argv);
1422
1423                 if (cmd != cmdbuf)
1424                         os_free(cmd);
1425         } while (!wpa_cli_quit);
1426
1427 #ifdef CONFIG_READLINE
1428         if (hfile) {
1429                 /* Save command history, excluding lines that may contain
1430                  * passwords. */
1431                 HIST_ENTRY *h;
1432                 history_set_pos(0);
1433                 h = next_history();
1434                 while (h) {
1435                         char *p = h->line;
1436                         while (*p == ' ' || *p == '\t')
1437                                 p++;
1438                         if (os_strncasecmp(p, "pa", 2) == 0 ||
1439                             os_strncasecmp(p, "o", 1) == 0 ||
1440                             os_strncasecmp(p, "n", 1)) {
1441                                 h = remove_history(where_history());
1442                                 if (h) {
1443                                         os_free(h->line);
1444                                         os_free(h->data);
1445                                         os_free(h);
1446                                 }
1447                                 h = current_history();
1448                         } else {
1449                                 h = next_history();
1450                         }
1451                 }
1452                 write_history(hfile);
1453                 os_free(hfile);
1454         }
1455 #endif /* CONFIG_READLINE */
1456 }
1457
1458
1459 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1460 {
1461 #ifdef CONFIG_ANSI_C_EXTRA
1462         /* TODO: ANSI C version(?) */
1463         printf("Action processing not supported in ANSI C build.\n");
1464 #else /* CONFIG_ANSI_C_EXTRA */
1465         fd_set rfds;
1466         int fd, res;
1467         struct timeval tv;
1468         char buf[256]; /* note: large enough to fit in unsolicited messages */
1469         size_t len;
1470
1471         fd = wpa_ctrl_get_fd(ctrl);
1472
1473         while (!wpa_cli_quit) {
1474                 FD_ZERO(&rfds);
1475                 FD_SET(fd, &rfds);
1476                 tv.tv_sec = 2;
1477                 tv.tv_usec = 0;
1478                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1479                 if (res < 0 && errno != EINTR) {
1480                         perror("select");
1481                         break;
1482                 }
1483
1484                 if (FD_ISSET(fd, &rfds))
1485                         wpa_cli_recv_pending(ctrl, 0, 1);
1486                 else {
1487                         /* verify that connection is still working */
1488                         len = sizeof(buf) - 1;
1489                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1490                                              wpa_cli_action_cb) < 0 ||
1491                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1492                                 printf("wpa_supplicant did not reply to PING "
1493                                        "command - exiting\n");
1494                                 break;
1495                         }
1496                 }
1497         }
1498 #endif /* CONFIG_ANSI_C_EXTRA */
1499 }
1500
1501
1502 static void wpa_cli_cleanup(void)
1503 {
1504         wpa_cli_close_connection();
1505         if (pid_file)
1506                 os_daemonize_terminate(pid_file);
1507
1508         os_program_deinit();
1509 }
1510
1511 static void wpa_cli_terminate(int sig)
1512 {
1513         wpa_cli_cleanup();
1514         exit(0);
1515 }
1516
1517
1518 #ifndef CONFIG_NATIVE_WINDOWS
1519 static void wpa_cli_alarm(int sig)
1520 {
1521         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1522                 printf("Connection to wpa_supplicant lost - trying to "
1523                        "reconnect\n");
1524                 wpa_cli_close_connection();
1525         }
1526         if (!ctrl_conn)
1527                 wpa_cli_reconnect();
1528         if (ctrl_conn)
1529                 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1530         alarm(1);
1531 }
1532 #endif /* CONFIG_NATIVE_WINDOWS */
1533
1534
1535 static char * wpa_cli_get_default_ifname(void)
1536 {
1537         char *ifname = NULL;
1538
1539 #ifdef CONFIG_CTRL_IFACE_UNIX
1540         struct dirent *dent;
1541         DIR *dir = opendir(ctrl_iface_dir);
1542         if (!dir)
1543                 return NULL;
1544         while ((dent = readdir(dir))) {
1545 #ifdef _DIRENT_HAVE_D_TYPE
1546                 /*
1547                  * Skip the file if it is not a socket. Also accept
1548                  * DT_UNKNOWN (0) in case the C library or underlying
1549                  * file system does not support d_type.
1550                  */
1551                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1552                         continue;
1553 #endif /* _DIRENT_HAVE_D_TYPE */
1554                 if (os_strcmp(dent->d_name, ".") == 0 ||
1555                     os_strcmp(dent->d_name, "..") == 0)
1556                         continue;
1557                 printf("Selected interface '%s'\n", dent->d_name);
1558                 ifname = os_strdup(dent->d_name);
1559                 break;
1560         }
1561         closedir(dir);
1562 #endif /* CONFIG_CTRL_IFACE_UNIX */
1563
1564 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1565         char buf[2048], *pos;
1566         size_t len;
1567         struct wpa_ctrl *ctrl;
1568         int ret;
1569
1570         ctrl = wpa_ctrl_open(NULL);
1571         if (ctrl == NULL)
1572                 return NULL;
1573
1574         len = sizeof(buf) - 1;
1575         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1576         if (ret >= 0) {
1577                 buf[len] = '\0';
1578                 pos = os_strchr(buf, '\n');
1579                 if (pos)
1580                         *pos = '\0';
1581                 ifname = os_strdup(buf);
1582         }
1583         wpa_ctrl_close(ctrl);
1584 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1585
1586         return ifname;
1587 }
1588
1589
1590 int main(int argc, char *argv[])
1591 {
1592         int interactive;
1593         int warning_displayed = 0;
1594         int c;
1595         int daemonize = 0;
1596         int ret = 0;
1597         const char *global = NULL;
1598
1599         if (os_program_init())
1600                 return -1;
1601
1602         for (;;) {
1603                 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1604                 if (c < 0)
1605                         break;
1606                 switch (c) {
1607                 case 'a':
1608                         action_file = optarg;
1609                         break;
1610                 case 'B':
1611                         daemonize = 1;
1612                         break;
1613                 case 'g':
1614                         global = optarg;
1615                         break;
1616                 case 'h':
1617                         usage();
1618                         return 0;
1619                 case 'v':
1620                         printf("%s\n", wpa_cli_version);
1621                         return 0;
1622                 case 'i':
1623                         os_free(ctrl_ifname);
1624                         ctrl_ifname = os_strdup(optarg);
1625                         break;
1626                 case 'p':
1627                         ctrl_iface_dir = optarg;
1628                         break;
1629                 case 'P':
1630                         pid_file = optarg;
1631                         break;
1632                 default:
1633                         usage();
1634                         return -1;
1635                 }
1636         }
1637
1638         interactive = (argc == optind) && (action_file == NULL);
1639
1640         if (interactive)
1641                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1642
1643         if (global) {
1644 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1645                 ctrl_conn = wpa_ctrl_open(NULL);
1646 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1647                 ctrl_conn = wpa_ctrl_open(global);
1648 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1649                 if (ctrl_conn == NULL) {
1650                         perror("Failed to connect to wpa_supplicant - "
1651                                "wpa_ctrl_open");
1652                         return -1;
1653                 }
1654         }
1655
1656         for (; !global;) {
1657                 if (ctrl_ifname == NULL)
1658                         ctrl_ifname = wpa_cli_get_default_ifname();
1659                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1660                 if (ctrl_conn) {
1661                         if (warning_displayed)
1662                                 printf("Connection established.\n");
1663                         break;
1664                 }
1665
1666                 if (!interactive) {
1667                         perror("Failed to connect to wpa_supplicant - "
1668                                "wpa_ctrl_open");
1669                         return -1;
1670                 }
1671
1672                 if (!warning_displayed) {
1673                         printf("Could not connect to wpa_supplicant - "
1674                                "re-trying\n");
1675                         warning_displayed = 1;
1676                 }
1677                 os_sleep(1, 0);
1678                 continue;
1679         }
1680
1681 #ifndef _WIN32_WCE
1682         signal(SIGINT, wpa_cli_terminate);
1683         signal(SIGTERM, wpa_cli_terminate);
1684 #endif /* _WIN32_WCE */
1685 #ifndef CONFIG_NATIVE_WINDOWS
1686         signal(SIGALRM, wpa_cli_alarm);
1687 #endif /* CONFIG_NATIVE_WINDOWS */
1688
1689         if (interactive || action_file) {
1690                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1691                         wpa_cli_attached = 1;
1692                 } else {
1693                         printf("Warning: Failed to attach to "
1694                                "wpa_supplicant.\n");
1695                         if (!interactive)
1696                                 return -1;
1697                 }
1698         }
1699
1700         if (daemonize && os_daemonize(pid_file))
1701                 return -1;
1702
1703         if (interactive)
1704                 wpa_cli_interactive();
1705         else if (action_file)
1706                 wpa_cli_action(ctrl_conn);
1707         else
1708                 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1709
1710         os_free(ctrl_ifname);
1711         wpa_cli_cleanup();
1712
1713         return ret;
1714 }
1715
1716 #else /* CONFIG_CTRL_IFACE */
1717 int main(int argc, char *argv[])
1718 {
1719         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1720         return -1;
1721 }
1722 #endif /* CONFIG_CTRL_IFACE */