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