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