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