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