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