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