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