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