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