Merge branch 'moonshot' of ssh://moonshot.suchdamage.org:822/srv/git/libeap into...
[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 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
619                                      char *argv[])
620 {
621         char cmd[256];
622         int res;
623
624         if (argc != 1 && argc != 2) {
625                 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
626                        "- PIN to be verified\n");
627                 return -1;
628         }
629
630         if (argc == 2)
631                 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
632                                   argv[0], argv[1]);
633         else
634                 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
635                                   argv[0]);
636         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
637                 printf("Too long WPS_CHECK_PIN command.\n");
638                 return -1;
639         }
640         return wpa_ctrl_command(ctrl, cmd);
641 }
642
643
644 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
645                                   char *argv[])
646 {
647         return wpa_ctrl_command(ctrl, "WPS_CANCEL");
648 }
649
650
651 #ifdef CONFIG_WPS_OOB
652 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
653 {
654         char cmd[256];
655         int res;
656
657         if (argc != 3 && argc != 4) {
658                 printf("Invalid WPS_OOB command: need three or four "
659                        "arguments:\n"
660                        "- DEV_TYPE: use 'ufd' or 'nfc'\n"
661                        "- PATH: path of OOB device like '/mnt'\n"
662                        "- METHOD: OOB method 'pin-e' or 'pin-r', "
663                        "'cred'\n"
664                        "- DEV_NAME: (only for NFC) device name like "
665                        "'pn531'\n");
666                 return -1;
667         }
668
669         if (argc == 3)
670                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
671                                   argv[0], argv[1], argv[2]);
672         else
673                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
674                                   argv[0], argv[1], argv[2], argv[3]);
675         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
676                 printf("Too long WPS_OOB command.\n");
677                 return -1;
678         }
679         return wpa_ctrl_command(ctrl, cmd);
680 }
681 #endif /* CONFIG_WPS_OOB */
682
683
684 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
685 {
686         char cmd[256];
687         int res;
688
689         if (argc == 2)
690                 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
691                                   argv[0], argv[1]);
692         else if (argc == 5 || argc == 6) {
693                 char ssid_hex[2 * 32 + 1];
694                 char key_hex[2 * 64 + 1];
695                 int i;
696
697                 ssid_hex[0] = '\0';
698                 for (i = 0; i < 32; i++) {
699                         if (argv[2][i] == '\0')
700                                 break;
701                         os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
702                 }
703
704                 key_hex[0] = '\0';
705                 if (argc == 6) {
706                         for (i = 0; i < 64; i++) {
707                                 if (argv[5][i] == '\0')
708                                         break;
709                                 os_snprintf(&key_hex[i * 2], 3, "%02x",
710                                             argv[5][i]);
711                         }
712                 }
713
714                 res = os_snprintf(cmd, sizeof(cmd),
715                                   "WPS_REG %s %s %s %s %s %s",
716                                   argv[0], argv[1], ssid_hex, argv[3], argv[4],
717                                   key_hex);
718         } else {
719                 printf("Invalid WPS_REG command: need two arguments:\n"
720                        "- BSSID: use 'any' to select any\n"
721                        "- AP PIN\n");
722                 printf("Alternatively, six arguments can be used to "
723                        "reconfigure the AP:\n"
724                        "- BSSID: use 'any' to select any\n"
725                        "- AP PIN\n"
726                        "- new SSID\n"
727                        "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
728                        "- new encr (NONE, WEP, TKIP, CCMP)\n"
729                        "- new key\n");
730                 return -1;
731         }
732
733         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
734                 printf("Too long WPS_REG command.\n");
735                 return -1;
736         }
737         return wpa_ctrl_command(ctrl, cmd);
738 }
739
740
741 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
742                                     char *argv[])
743 {
744         char cmd[100];
745         if (argc > 0) {
746                 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
747                 return wpa_ctrl_command(ctrl, cmd);
748         }
749         return wpa_ctrl_command(ctrl, "WPS_ER_START");
750 }
751
752
753 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
754                                    char *argv[])
755 {
756         return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
757
758 }
759
760
761 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
762                                   char *argv[])
763 {
764         char cmd[256];
765         int res;
766
767         if (argc < 2) {
768                 printf("Invalid WPS_ER_PIN command: need at least two "
769                        "arguments:\n"
770                        "- UUID: use 'any' to select any\n"
771                        "- PIN: Enrollee PIN\n"
772                        "optional: - Enrollee MAC address\n");
773                 return -1;
774         }
775
776         if (argc > 2)
777                 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
778                                   argv[0], argv[1], argv[2]);
779         else
780                 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
781                                   argv[0], argv[1]);
782         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
783                 printf("Too long WPS_ER_PIN command.\n");
784                 return -1;
785         }
786         return wpa_ctrl_command(ctrl, cmd);
787 }
788
789
790 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
791                                   char *argv[])
792 {
793         char cmd[256];
794         int res;
795
796         if (argc != 1) {
797                 printf("Invalid WPS_ER_PBC command: need one argument:\n"
798                        "- UUID: Specify the Enrollee\n");
799                 return -1;
800         }
801
802         res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
803                           argv[0]);
804         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
805                 printf("Too long WPS_ER_PBC command.\n");
806                 return -1;
807         }
808         return wpa_ctrl_command(ctrl, cmd);
809 }
810
811
812 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
813                                     char *argv[])
814 {
815         char cmd[256];
816         int res;
817
818         if (argc != 2) {
819                 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
820                        "- UUID: specify which AP to use\n"
821                        "- PIN: AP PIN\n");
822                 return -1;
823         }
824
825         res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
826                           argv[0], argv[1]);
827         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
828                 printf("Too long WPS_ER_LEARN command.\n");
829                 return -1;
830         }
831         return wpa_ctrl_command(ctrl, cmd);
832 }
833
834
835 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
836                                      char *argv[])
837 {
838         char cmd[256];
839         int res;
840
841         if (argc == 5 || argc == 6) {
842                 char ssid_hex[2 * 32 + 1];
843                 char key_hex[2 * 64 + 1];
844                 int i;
845
846                 ssid_hex[0] = '\0';
847                 for (i = 0; i < 32; i++) {
848                         if (argv[2][i] == '\0')
849                                 break;
850                         os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
851                 }
852
853                 key_hex[0] = '\0';
854                 if (argc == 6) {
855                         for (i = 0; i < 64; i++) {
856                                 if (argv[5][i] == '\0')
857                                         break;
858                                 os_snprintf(&key_hex[i * 2], 3, "%02x",
859                                             argv[5][i]);
860                         }
861                 }
862
863                 res = os_snprintf(cmd, sizeof(cmd),
864                                   "WPS_ER_CONFIG %s %s %s %s %s %s",
865                                   argv[0], argv[1], ssid_hex, argv[3], argv[4],
866                                   key_hex);
867         } else {
868                 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
869                        "- AP UUID\n"
870                        "- AP PIN\n"
871                        "- new SSID\n"
872                        "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
873                        "- new encr (NONE, WEP, TKIP, CCMP)\n"
874                        "- new key\n");
875                 return -1;
876         }
877
878         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
879                 printf("Too long WPS_ER_CONFIG command.\n");
880                 return -1;
881         }
882         return wpa_ctrl_command(ctrl, cmd);
883 }
884
885
886 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
887 {
888         char cmd[256];
889         int res;
890
891         if (argc != 1) {
892                 printf("Invalid IBSS_RSN command: needs one argument "
893                        "(Peer STA MAC address)\n");
894                 return -1;
895         }
896
897         res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
898         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
899                 printf("Too long IBSS_RSN command.\n");
900                 return -1;
901         }
902         return wpa_ctrl_command(ctrl, cmd);
903 }
904
905
906 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
907 {
908         char cmd[256];
909         int res;
910
911         if (argc != 1) {
912                 printf("Invalid LEVEL command: needs one argument (debug "
913                        "level)\n");
914                 return -1;
915         }
916         res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
917         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
918                 printf("Too long LEVEL command.\n");
919                 return -1;
920         }
921         return wpa_ctrl_command(ctrl, cmd);
922 }
923
924
925 static int wpa_cli_cmd_identity(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 IDENTITY command: needs two arguments "
932                        "(network id and identity)\n");
933                 return -1;
934         }
935
936         end = cmd + sizeof(cmd);
937         pos = cmd;
938         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
939                           argv[0], argv[1]);
940         if (ret < 0 || ret >= end - pos) {
941                 printf("Too long IDENTITY 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 IDENTITY 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_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
959 {
960         char cmd[256], *pos, *end;
961         int i, ret;
962
963         if (argc < 2) {
964                 printf("Invalid PASSWORD command: needs two arguments "
965                        "(network id and password)\n");
966                 return -1;
967         }
968
969         end = cmd + sizeof(cmd);
970         pos = cmd;
971         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
972                           argv[0], argv[1]);
973         if (ret < 0 || ret >= end - pos) {
974                 printf("Too long PASSWORD command.\n");
975                 return -1;
976         }
977         pos += ret;
978         for (i = 2; i < argc; i++) {
979                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
980                 if (ret < 0 || ret >= end - pos) {
981                         printf("Too long PASSWORD command.\n");
982                         return -1;
983                 }
984                 pos += ret;
985         }
986
987         return wpa_ctrl_command(ctrl, cmd);
988 }
989
990
991 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
992                                     char *argv[])
993 {
994         char cmd[256], *pos, *end;
995         int i, ret;
996
997         if (argc < 2) {
998                 printf("Invalid NEW_PASSWORD command: needs two arguments "
999                        "(network id and password)\n");
1000                 return -1;
1001         }
1002
1003         end = cmd + sizeof(cmd);
1004         pos = cmd;
1005         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1006                           argv[0], argv[1]);
1007         if (ret < 0 || ret >= end - pos) {
1008                 printf("Too long NEW_PASSWORD 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 NEW_PASSWORD command.\n");
1016                         return -1;
1017                 }
1018                 pos += ret;
1019         }
1020
1021         return wpa_ctrl_command(ctrl, cmd);
1022 }
1023
1024
1025 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1026 {
1027         char cmd[256], *pos, *end;
1028         int i, ret;
1029
1030         if (argc < 2) {
1031                 printf("Invalid PIN command: needs two arguments "
1032                        "(network id and pin)\n");
1033                 return -1;
1034         }
1035
1036         end = cmd + sizeof(cmd);
1037         pos = cmd;
1038         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1039                           argv[0], argv[1]);
1040         if (ret < 0 || ret >= end - pos) {
1041                 printf("Too long PIN command.\n");
1042                 return -1;
1043         }
1044         pos += ret;
1045         for (i = 2; i < argc; i++) {
1046                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1047                 if (ret < 0 || ret >= end - pos) {
1048                         printf("Too long PIN command.\n");
1049                         return -1;
1050                 }
1051                 pos += ret;
1052         }
1053         return wpa_ctrl_command(ctrl, cmd);
1054 }
1055
1056
1057 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1058 {
1059         char cmd[256], *pos, *end;
1060         int i, ret;
1061
1062         if (argc < 2) {
1063                 printf("Invalid OTP command: needs two arguments (network "
1064                        "id and password)\n");
1065                 return -1;
1066         }
1067
1068         end = cmd + sizeof(cmd);
1069         pos = cmd;
1070         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1071                           argv[0], argv[1]);
1072         if (ret < 0 || ret >= end - pos) {
1073                 printf("Too long OTP command.\n");
1074                 return -1;
1075         }
1076         pos += ret;
1077         for (i = 2; i < argc; i++) {
1078                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1079                 if (ret < 0 || ret >= end - pos) {
1080                         printf("Too long OTP command.\n");
1081                         return -1;
1082                 }
1083                 pos += ret;
1084         }
1085
1086         return wpa_ctrl_command(ctrl, cmd);
1087 }
1088
1089
1090 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1091                                   char *argv[])
1092 {
1093         char cmd[256], *pos, *end;
1094         int i, ret;
1095
1096         if (argc < 2) {
1097                 printf("Invalid PASSPHRASE command: needs two arguments "
1098                        "(network id and passphrase)\n");
1099                 return -1;
1100         }
1101
1102         end = cmd + sizeof(cmd);
1103         pos = cmd;
1104         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1105                           argv[0], argv[1]);
1106         if (ret < 0 || ret >= end - pos) {
1107                 printf("Too long PASSPHRASE command.\n");
1108                 return -1;
1109         }
1110         pos += ret;
1111         for (i = 2; i < argc; i++) {
1112                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1113                 if (ret < 0 || ret >= end - pos) {
1114                         printf("Too long PASSPHRASE command.\n");
1115                         return -1;
1116                 }
1117                 pos += ret;
1118         }
1119
1120         return wpa_ctrl_command(ctrl, cmd);
1121 }
1122
1123
1124 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1125 {
1126         char cmd[256], *pos, *end;
1127         int i, ret;
1128
1129         if (argc < 2) {
1130                 printf("Invalid BSSID command: needs two arguments (network "
1131                        "id and BSSID)\n");
1132                 return -1;
1133         }
1134
1135         end = cmd + sizeof(cmd);
1136         pos = cmd;
1137         ret = os_snprintf(pos, end - pos, "BSSID");
1138         if (ret < 0 || ret >= end - pos) {
1139                 printf("Too long BSSID command.\n");
1140                 return -1;
1141         }
1142         pos += ret;
1143         for (i = 0; i < argc; i++) {
1144                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1145                 if (ret < 0 || ret >= end - pos) {
1146                         printf("Too long BSSID command.\n");
1147                         return -1;
1148                 }
1149                 pos += ret;
1150         }
1151
1152         return wpa_ctrl_command(ctrl, cmd);
1153 }
1154
1155
1156 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1157                                      char *argv[])
1158 {
1159         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1160 }
1161
1162
1163 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1164                                       char *argv[])
1165 {
1166         char cmd[32];
1167         int res;
1168
1169         if (argc < 1) {
1170                 printf("Invalid SELECT_NETWORK command: needs one argument "
1171                        "(network id)\n");
1172                 return -1;
1173         }
1174
1175         res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1176         if (res < 0 || (size_t) res >= sizeof(cmd))
1177                 return -1;
1178         cmd[sizeof(cmd) - 1] = '\0';
1179
1180         return wpa_ctrl_command(ctrl, cmd);
1181 }
1182
1183
1184 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1185                                       char *argv[])
1186 {
1187         char cmd[32];
1188         int res;
1189
1190         if (argc < 1) {
1191                 printf("Invalid ENABLE_NETWORK command: needs one argument "
1192                        "(network id)\n");
1193                 return -1;
1194         }
1195
1196         res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1197         if (res < 0 || (size_t) res >= sizeof(cmd))
1198                 return -1;
1199         cmd[sizeof(cmd) - 1] = '\0';
1200
1201         return wpa_ctrl_command(ctrl, cmd);
1202 }
1203
1204
1205 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1206                                        char *argv[])
1207 {
1208         char cmd[32];
1209         int res;
1210
1211         if (argc < 1) {
1212                 printf("Invalid DISABLE_NETWORK command: needs one argument "
1213                        "(network id)\n");
1214                 return -1;
1215         }
1216
1217         res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1218         if (res < 0 || (size_t) res >= sizeof(cmd))
1219                 return -1;
1220         cmd[sizeof(cmd) - 1] = '\0';
1221
1222         return wpa_ctrl_command(ctrl, cmd);
1223 }
1224
1225
1226 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1227                                    char *argv[])
1228 {
1229         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1230 }
1231
1232
1233 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1234                                       char *argv[])
1235 {
1236         char cmd[32];
1237         int res;
1238
1239         if (argc < 1) {
1240                 printf("Invalid REMOVE_NETWORK command: needs one argument "
1241                        "(network id)\n");
1242                 return -1;
1243         }
1244
1245         res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1246         if (res < 0 || (size_t) res >= sizeof(cmd))
1247                 return -1;
1248         cmd[sizeof(cmd) - 1] = '\0';
1249
1250         return wpa_ctrl_command(ctrl, cmd);
1251 }
1252
1253
1254 static void wpa_cli_show_network_variables(void)
1255 {
1256         printf("set_network variables:\n"
1257                "  ssid (network name, SSID)\n"
1258                "  psk (WPA passphrase or pre-shared key)\n"
1259                "  key_mgmt (key management protocol)\n"
1260                "  identity (EAP identity)\n"
1261                "  password (EAP password)\n"
1262                "  ...\n"
1263                "\n"
1264                "Note: Values are entered in the same format as the "
1265                "configuration file is using,\n"
1266                "i.e., strings values need to be inside double quotation "
1267                "marks.\n"
1268                "For example: set_network 1 ssid \"network name\"\n"
1269                "\n"
1270                "Please see wpa_supplicant.conf documentation for full list "
1271                "of\navailable variables.\n");
1272 }
1273
1274
1275 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1276                                    char *argv[])
1277 {
1278         char cmd[256];
1279         int res;
1280
1281         if (argc == 0) {
1282                 wpa_cli_show_network_variables();
1283                 return 0;
1284         }
1285
1286         if (argc != 3) {
1287                 printf("Invalid SET_NETWORK command: needs three arguments\n"
1288                        "(network id, variable name, and value)\n");
1289                 return -1;
1290         }
1291
1292         res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1293                           argv[0], argv[1], argv[2]);
1294         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1295                 printf("Too long SET_NETWORK command.\n");
1296                 return -1;
1297         }
1298         return wpa_ctrl_command(ctrl, cmd);
1299 }
1300
1301
1302 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1303                                    char *argv[])
1304 {
1305         char cmd[256];
1306         int res;
1307
1308         if (argc == 0) {
1309                 wpa_cli_show_network_variables();
1310                 return 0;
1311         }
1312
1313         if (argc != 2) {
1314                 printf("Invalid GET_NETWORK command: needs two arguments\n"
1315                        "(network id and variable name)\n");
1316                 return -1;
1317         }
1318
1319         res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1320                           argv[0], argv[1]);
1321         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1322                 printf("Too long GET_NETWORK command.\n");
1323                 return -1;
1324         }
1325         return wpa_ctrl_command(ctrl, cmd);
1326 }
1327
1328
1329 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1330                                   char *argv[])
1331 {
1332         return wpa_ctrl_command(ctrl, "DISCONNECT");
1333 }
1334
1335
1336 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1337                                   char *argv[])
1338 {
1339         return wpa_ctrl_command(ctrl, "RECONNECT");
1340 }
1341
1342
1343 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1344                                    char *argv[])
1345 {
1346         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1347 }
1348
1349
1350 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1351 {
1352         return wpa_ctrl_command(ctrl, "SCAN");
1353 }
1354
1355
1356 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1357                                     char *argv[])
1358 {
1359         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1360 }
1361
1362
1363 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1364 {
1365         char cmd[64];
1366         int res;
1367
1368         if (argc != 1) {
1369                 printf("Invalid BSS command: need one argument (index or "
1370                        "BSSID)\n");
1371                 return -1;
1372         }
1373
1374         res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1375         if (res < 0 || (size_t) res >= sizeof(cmd))
1376                 return -1;
1377         cmd[sizeof(cmd) - 1] = '\0';
1378
1379         return wpa_ctrl_command(ctrl, cmd);
1380 }
1381
1382
1383 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1384                                       char *argv[])
1385 {
1386         char cmd[64];
1387         int res;
1388
1389         if (argc < 1 || argc > 2) {
1390                 printf("Invalid GET_CAPABILITY command: need either one or "
1391                        "two arguments\n");
1392                 return -1;
1393         }
1394
1395         if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1396                 printf("Invalid GET_CAPABILITY command: second argument, "
1397                        "if any, must be 'strict'\n");
1398                 return -1;
1399         }
1400
1401         res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1402                           (argc == 2) ? " strict" : "");
1403         if (res < 0 || (size_t) res >= sizeof(cmd))
1404                 return -1;
1405         cmd[sizeof(cmd) - 1] = '\0';
1406
1407         return wpa_ctrl_command(ctrl, cmd);
1408 }
1409
1410
1411 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1412 {
1413         printf("Available interfaces:\n");
1414         return wpa_ctrl_command(ctrl, "INTERFACES");
1415 }
1416
1417
1418 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1419 {
1420         if (argc < 1) {
1421                 wpa_cli_list_interfaces(ctrl);
1422                 return 0;
1423         }
1424
1425         wpa_cli_close_connection();
1426         os_free(ctrl_ifname);
1427         ctrl_ifname = os_strdup(argv[0]);
1428
1429         if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1430                 printf("Connected to interface '%s.\n", ctrl_ifname);
1431         } else {
1432                 printf("Could not connect to interface '%s' - re-trying\n",
1433                        ctrl_ifname);
1434         }
1435         return 0;
1436 }
1437
1438
1439 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1440                                    char *argv[])
1441 {
1442         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1443 }
1444
1445
1446 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1447                                  char *argv[])
1448 {
1449         return wpa_ctrl_command(ctrl, "TERMINATE");
1450 }
1451
1452
1453 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1454                                      char *argv[])
1455 {
1456         char cmd[256];
1457         int res;
1458
1459         if (argc < 1) {
1460                 printf("Invalid INTERFACE_ADD command: needs at least one "
1461                        "argument (interface name)\n"
1462                        "All arguments: ifname confname driver ctrl_interface "
1463                        "driver_param bridge_name\n");
1464                 return -1;
1465         }
1466
1467         /*
1468          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1469          * <driver_param>TAB<bridge_name>
1470          */
1471         res = os_snprintf(cmd, sizeof(cmd),
1472                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1473                           argv[0],
1474                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1475                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1476                           argc > 5 ? argv[5] : "");
1477         if (res < 0 || (size_t) res >= sizeof(cmd))
1478                 return -1;
1479         cmd[sizeof(cmd) - 1] = '\0';
1480         return wpa_ctrl_command(ctrl, cmd);
1481 }
1482
1483
1484 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1485                                         char *argv[])
1486 {
1487         char cmd[128];
1488         int res;
1489
1490         if (argc != 1) {
1491                 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1492                        "(interface name)\n");
1493                 return -1;
1494         }
1495
1496         res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1497         if (res < 0 || (size_t) res >= sizeof(cmd))
1498                 return -1;
1499         cmd[sizeof(cmd) - 1] = '\0';
1500         return wpa_ctrl_command(ctrl, cmd);
1501 }
1502
1503
1504 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1505                                       char *argv[])
1506 {
1507         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1508 }
1509
1510
1511 #ifdef CONFIG_AP
1512 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1513 {
1514         char buf[64];
1515         if (argc != 1) {
1516                 printf("Invalid 'sta' command - exactly one argument, STA "
1517                        "address, is required.\n");
1518                 return -1;
1519         }
1520         os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1521         return wpa_ctrl_command(ctrl, buf);
1522 }
1523
1524
1525 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1526                                 char *addr, size_t addr_len)
1527 {
1528         char buf[4096], *pos;
1529         size_t len;
1530         int ret;
1531
1532         if (ctrl_conn == NULL) {
1533                 printf("Not connected to hostapd - command dropped.\n");
1534                 return -1;
1535         }
1536         len = sizeof(buf) - 1;
1537         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1538                                wpa_cli_msg_cb);
1539         if (ret == -2) {
1540                 printf("'%s' command timed out.\n", cmd);
1541                 return -2;
1542         } else if (ret < 0) {
1543                 printf("'%s' command failed.\n", cmd);
1544                 return -1;
1545         }
1546
1547         buf[len] = '\0';
1548         if (memcmp(buf, "FAIL", 4) == 0)
1549                 return -1;
1550         printf("%s", buf);
1551
1552         pos = buf;
1553         while (*pos != '\0' && *pos != '\n')
1554                 pos++;
1555         *pos = '\0';
1556         os_strlcpy(addr, buf, addr_len);
1557         return 0;
1558 }
1559
1560
1561 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1562 {
1563         char addr[32], cmd[64];
1564
1565         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1566                 return 0;
1567         do {
1568                 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1569         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1570
1571         return -1;
1572 }
1573 #endif /* CONFIG_AP */
1574
1575
1576 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1577 {
1578         return wpa_ctrl_command(ctrl, "SUSPEND");
1579 }
1580
1581
1582 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1583 {
1584         return wpa_ctrl_command(ctrl, "RESUME");
1585 }
1586
1587
1588 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1589 {
1590         return wpa_ctrl_command(ctrl, "DROP_SA");
1591 }
1592
1593
1594 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1595 {
1596         char cmd[128];
1597         int res;
1598
1599         if (argc != 1) {
1600                 printf("Invalid ROAM command: needs one argument "
1601                        "(target AP's BSSID)\n");
1602                 return -1;
1603         }
1604
1605         res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1606         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1607                 printf("Too long ROAM command.\n");
1608                 return -1;
1609         }
1610         return wpa_ctrl_command(ctrl, cmd);
1611 }
1612
1613
1614 #ifdef CONFIG_P2P
1615
1616 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1617 {
1618         char cmd[128];
1619         int res;
1620
1621         if (argc == 0)
1622                 return wpa_ctrl_command(ctrl, "P2P_FIND");
1623
1624         if (argc > 1)
1625                 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1626                                   argv[0], argv[1]);
1627         else
1628                 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
1629         if (res < 0 || (size_t) res >= sizeof(cmd))
1630                 return -1;
1631         cmd[sizeof(cmd) - 1] = '\0';
1632         return wpa_ctrl_command(ctrl, cmd);
1633 }
1634
1635
1636 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1637                                      char *argv[])
1638 {
1639         return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1640 }
1641
1642
1643 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1644                                    char *argv[])
1645 {
1646         char cmd[128];
1647         int res;
1648
1649         if (argc < 2) {
1650                 printf("Invalid P2P_CONNECT command: needs at least two "
1651                        "arguments (address and pbc/PIN)\n");
1652                 return -1;
1653         }
1654
1655         if (argc > 4)
1656                 res = os_snprintf(cmd, sizeof(cmd),
1657                                   "P2P_CONNECT %s %s %s %s %s",
1658                                   argv[0], argv[1], argv[2], argv[3],
1659                                   argv[4]);
1660         else if (argc > 3)
1661                 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1662                                   argv[0], argv[1], argv[2], argv[3]);
1663         else if (argc > 2)
1664                 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1665                                   argv[0], argv[1], argv[2]);
1666         else
1667                 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1668                                   argv[0], argv[1]);
1669         if (res < 0 || (size_t) res >= sizeof(cmd))
1670                 return -1;
1671         cmd[sizeof(cmd) - 1] = '\0';
1672         return wpa_ctrl_command(ctrl, cmd);
1673 }
1674
1675
1676 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1677                                   char *argv[])
1678 {
1679         char cmd[128];
1680         int res;
1681
1682         if (argc == 0)
1683                 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
1684
1685         res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
1686         if (res < 0 || (size_t) res >= sizeof(cmd))
1687                 return -1;
1688         cmd[sizeof(cmd) - 1] = '\0';
1689         return wpa_ctrl_command(ctrl, cmd);
1690 }
1691
1692
1693 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1694                                         char *argv[])
1695 {
1696         char cmd[128];
1697         int res;
1698
1699         if (argc != 1) {
1700                 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
1701                        "(interface name)\n");
1702                 return -1;
1703         }
1704
1705         res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
1706         if (res < 0 || (size_t) res >= sizeof(cmd))
1707                 return -1;
1708         cmd[sizeof(cmd) - 1] = '\0';
1709         return wpa_ctrl_command(ctrl, cmd);
1710 }
1711
1712
1713 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1714                                         char *argv[])
1715 {
1716         char cmd[128];
1717         int res;
1718
1719         if (argc == 0)
1720                 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
1721
1722         res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s", argv[0]);
1723         if (res < 0 || (size_t) res >= sizeof(cmd))
1724                 return -1;
1725         cmd[sizeof(cmd) - 1] = '\0';
1726         return wpa_ctrl_command(ctrl, cmd);
1727 }
1728
1729
1730 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1731                                      char *argv[])
1732 {
1733         char cmd[128];
1734         int res;
1735
1736         if (argc != 2) {
1737                 printf("Invalid P2P_PROV_DISC command: needs two arguments "
1738                        "(address and config method\n"
1739                        "(display, keypad, or pbc)\n");
1740                 return -1;
1741         }
1742
1743         res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
1744                           argv[0], argv[1]);
1745         if (res < 0 || (size_t) res >= sizeof(cmd))
1746                 return -1;
1747         cmd[sizeof(cmd) - 1] = '\0';
1748         return wpa_ctrl_command(ctrl, cmd);
1749 }
1750
1751
1752 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1753                                           char *argv[])
1754 {
1755         return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1756 }
1757
1758
1759 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1760                                          char *argv[])
1761 {
1762         char cmd[4096];
1763         int res;
1764
1765         if (argc != 2 && argc != 4) {
1766                 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1767                        "arguments (address and TLVs) or four arguments "
1768                        "(address, \"upnp\", version, search target "
1769                        "(SSDP ST:)\n");
1770                 return -1;
1771         }
1772
1773         if (argc == 4)
1774                 res = os_snprintf(cmd, sizeof(cmd),
1775                                   "P2P_SERV_DISC_REQ %s %s %s %s",
1776                                   argv[0], argv[1], argv[2], argv[3]);
1777         else
1778                 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
1779                                   argv[0], argv[1]);
1780         if (res < 0 || (size_t) res >= sizeof(cmd))
1781                 return -1;
1782         cmd[sizeof(cmd) - 1] = '\0';
1783         return wpa_ctrl_command(ctrl, cmd);
1784 }
1785
1786
1787 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1788                                                 int argc, char *argv[])
1789 {
1790         char cmd[128];
1791         int res;
1792
1793         if (argc != 1) {
1794                 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
1795                        "argument (pending request identifier)\n");
1796                 return -1;
1797         }
1798
1799         res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
1800                           argv[0]);
1801         if (res < 0 || (size_t) res >= sizeof(cmd))
1802                 return -1;
1803         cmd[sizeof(cmd) - 1] = '\0';
1804         return wpa_ctrl_command(ctrl, cmd);
1805 }
1806
1807
1808 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1809                                           char *argv[])
1810 {
1811         char cmd[4096];
1812         int res;
1813
1814         if (argc != 4) {
1815                 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1816                        "arguments (freq, address, dialog token, and TLVs)\n");
1817                 return -1;
1818         }
1819
1820         res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1821                           argv[0], argv[1], argv[2], argv[3]);
1822         if (res < 0 || (size_t) res >= sizeof(cmd))
1823                 return -1;
1824         cmd[sizeof(cmd) - 1] = '\0';
1825         return wpa_ctrl_command(ctrl, cmd);
1826 }
1827
1828
1829 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1830                                           char *argv[])
1831 {
1832         return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1833 }
1834
1835
1836 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1837                                               int argc, char *argv[])
1838 {
1839         char cmd[128];
1840         int res;
1841
1842         if (argc != 1) {
1843                 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
1844                        "argument (external processing: 0/1)\n");
1845                 return -1;
1846         }
1847
1848         res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
1849                           argv[0]);
1850         if (res < 0 || (size_t) res >= sizeof(cmd))
1851                 return -1;
1852         cmd[sizeof(cmd) - 1] = '\0';
1853         return wpa_ctrl_command(ctrl, cmd);
1854 }
1855
1856
1857 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1858                                          char *argv[])
1859 {
1860         return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1861 }
1862
1863
1864 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1865                                        char *argv[])
1866 {
1867         char cmd[4096];
1868         int res;
1869
1870         if (argc != 3 && argc != 4) {
1871                 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1872                        "arguments\n");
1873                 return -1;
1874         }
1875
1876         if (argc == 4)
1877                 res = os_snprintf(cmd, sizeof(cmd),
1878                                   "P2P_SERVICE_ADD %s %s %s %s",
1879                                   argv[0], argv[1], argv[2], argv[3]);
1880         else
1881                 res = os_snprintf(cmd, sizeof(cmd),
1882                                   "P2P_SERVICE_ADD %s %s %s",
1883                                   argv[0], argv[1], argv[2]);
1884         if (res < 0 || (size_t) res >= sizeof(cmd))
1885                 return -1;
1886         cmd[sizeof(cmd) - 1] = '\0';
1887         return wpa_ctrl_command(ctrl, cmd);
1888 }
1889
1890
1891 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1892                                        char *argv[])
1893 {
1894         char cmd[4096];
1895         int res;
1896
1897         if (argc != 2 && argc != 3) {
1898                 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1899                        "arguments\n");
1900                 return -1;
1901         }
1902
1903         if (argc == 3)
1904                 res = os_snprintf(cmd, sizeof(cmd),
1905                                   "P2P_SERVICE_DEL %s %s %s",
1906                                   argv[0], argv[1], argv[2]);
1907         else
1908                 res = os_snprintf(cmd, sizeof(cmd),
1909                                   "P2P_SERVICE_DEL %s %s",
1910                                   argv[0], argv[1]);
1911         if (res < 0 || (size_t) res >= sizeof(cmd))
1912                 return -1;
1913         cmd[sizeof(cmd) - 1] = '\0';
1914         return wpa_ctrl_command(ctrl, cmd);
1915 }
1916
1917
1918 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1919                                   int argc, char *argv[])
1920 {
1921         char cmd[128];
1922         int res;
1923
1924         if (argc != 1) {
1925                 printf("Invalid P2P_REJECT command: needs one argument "
1926                        "(peer address)\n");
1927                 return -1;
1928         }
1929
1930         res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
1931         if (res < 0 || (size_t) res >= sizeof(cmd))
1932                 return -1;
1933         cmd[sizeof(cmd) - 1] = '\0';
1934         return wpa_ctrl_command(ctrl, cmd);
1935 }
1936
1937
1938 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1939                                   int argc, char *argv[])
1940 {
1941         char cmd[128];
1942         int res;
1943
1944         if (argc < 1) {
1945                 printf("Invalid P2P_INVITE command: needs at least one "
1946                        "argument\n");
1947                 return -1;
1948         }
1949
1950         if (argc > 2)
1951                 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
1952                                   argv[0], argv[1], argv[2]);
1953         else if (argc > 1)
1954                 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
1955                                   argv[0], argv[1]);
1956         else
1957                 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
1958         if (res < 0 || (size_t) res >= sizeof(cmd))
1959                 return -1;
1960         cmd[sizeof(cmd) - 1] = '\0';
1961         return wpa_ctrl_command(ctrl, cmd);
1962 }
1963
1964
1965 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1966 {
1967         char buf[64];
1968         if (argc != 1) {
1969                 printf("Invalid 'p2p_peer' command - exactly one argument, "
1970                        "P2P peer device address, is required.\n");
1971                 return -1;
1972         }
1973         os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
1974         return wpa_ctrl_command(ctrl, buf);
1975 }
1976
1977
1978 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1979                                      char *addr, size_t addr_len,
1980                                      int discovered)
1981 {
1982         char buf[4096], *pos;
1983         size_t len;
1984         int ret;
1985
1986         if (ctrl_conn == NULL)
1987                 return -1;
1988         len = sizeof(buf) - 1;
1989         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1990                                wpa_cli_msg_cb);
1991         if (ret == -2) {
1992                 printf("'%s' command timed out.\n", cmd);
1993                 return -2;
1994         } else if (ret < 0) {
1995                 printf("'%s' command failed.\n", cmd);
1996                 return -1;
1997         }
1998
1999         buf[len] = '\0';
2000         if (memcmp(buf, "FAIL", 4) == 0)
2001                 return -1;
2002
2003         pos = buf;
2004         while (*pos != '\0' && *pos != '\n')
2005                 pos++;
2006         *pos++ = '\0';
2007         os_strlcpy(addr, buf, addr_len);
2008         if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2009                 printf("%s\n", addr);
2010         return 0;
2011 }
2012
2013
2014 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2015 {
2016         char addr[32], cmd[64];
2017         int discovered;
2018
2019         discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2020
2021         if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2022                                       addr, sizeof(addr), discovered))
2023                 return 0;
2024         do {
2025                 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2026         } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2027                          discovered) == 0);
2028
2029         return -1;
2030 }
2031
2032
2033 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2034 {
2035         char cmd[100];
2036         int res;
2037
2038         if (argc != 2) {
2039                 printf("Invalid P2P_SET command: needs two arguments (field, "
2040                        "value)\n");
2041                 return -1;
2042         }
2043
2044         res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2045         if (res < 0 || (size_t) res >= sizeof(cmd))
2046                 return -1;
2047         cmd[sizeof(cmd) - 1] = '\0';
2048         return wpa_ctrl_command(ctrl, cmd);
2049 }
2050
2051
2052 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2053 {
2054         return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2055 }
2056
2057
2058 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2059                                         char *argv[])
2060 {
2061         char cmd[100];
2062         int res;
2063
2064         if (argc != 0 && argc != 2 && argc != 4) {
2065                 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2066                        "(preferred duration, interval; in microsecods).\n"
2067                        "Optional second pair can be used to provide "
2068                        "acceptable values.\n");
2069                 return -1;
2070         }
2071
2072         if (argc == 4)
2073                 res = os_snprintf(cmd, sizeof(cmd),
2074                                   "P2P_PRESENCE_REQ %s %s %s %s",
2075                                   argv[0], argv[1], argv[2], argv[3]);
2076         else if (argc == 2)
2077                 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2078                                   argv[0], argv[1]);
2079         else
2080                 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2081         if (res < 0 || (size_t) res >= sizeof(cmd))
2082                 return -1;
2083         cmd[sizeof(cmd) - 1] = '\0';
2084         return wpa_ctrl_command(ctrl, cmd);
2085 }
2086
2087
2088 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2089                                       char *argv[])
2090 {
2091         char cmd[100];
2092         int res;
2093
2094         if (argc != 0 && argc != 2) {
2095                 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2096                        "(availability period, availability interval; in "
2097                        "millisecods).\n"
2098                        "Extended Listen Timing can be cancelled with this "
2099                        "command when used without parameters.\n");
2100                 return -1;
2101         }
2102
2103         if (argc == 2)
2104                 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2105                                   argv[0], argv[1]);
2106         else
2107                 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2108         if (res < 0 || (size_t) res >= sizeof(cmd))
2109                 return -1;
2110         cmd[sizeof(cmd) - 1] = '\0';
2111         return wpa_ctrl_command(ctrl, cmd);
2112 }
2113
2114 #endif /* CONFIG_P2P */
2115
2116
2117 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2118                                        char *argv[])
2119 {
2120         char cmd[256];
2121         int res;
2122
2123         if (argc != 1) {
2124                 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2125                        "(0/1 = disable/enable automatic reconnection)\n");
2126                 return -1;
2127         }
2128         res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2129         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2130                 printf("Too long STA_AUTOCONNECT command.\n");
2131                 return -1;
2132         }
2133         return wpa_ctrl_command(ctrl, cmd);
2134 }
2135
2136
2137 enum wpa_cli_cmd_flags {
2138         cli_cmd_flag_none               = 0x00,
2139         cli_cmd_flag_sensitive          = 0x01
2140 };
2141
2142 struct wpa_cli_cmd {
2143         const char *cmd;
2144         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2145         enum wpa_cli_cmd_flags flags;
2146         const char *usage;
2147 };
2148
2149 static struct wpa_cli_cmd wpa_cli_commands[] = {
2150         { "status", wpa_cli_cmd_status,
2151           cli_cmd_flag_none,
2152           "[verbose] = get current WPA/EAPOL/EAP status" },
2153         { "ping", wpa_cli_cmd_ping,
2154           cli_cmd_flag_none,
2155           "= pings wpa_supplicant" },
2156         { "note", wpa_cli_cmd_note,
2157           cli_cmd_flag_none,
2158           "<text> = add a note to wpa_supplicant debug log" },
2159         { "mib", wpa_cli_cmd_mib,
2160           cli_cmd_flag_none,
2161           "= get MIB variables (dot1x, dot11)" },
2162         { "help", wpa_cli_cmd_help,
2163           cli_cmd_flag_none,
2164           "= show this usage help" },
2165         { "interface", wpa_cli_cmd_interface,
2166           cli_cmd_flag_none,
2167           "[ifname] = show interfaces/select interface" },
2168         { "level", wpa_cli_cmd_level,
2169           cli_cmd_flag_none,
2170           "<debug level> = change debug level" },
2171         { "license", wpa_cli_cmd_license,
2172           cli_cmd_flag_none,
2173           "= show full wpa_cli license" },
2174         { "quit", wpa_cli_cmd_quit,
2175           cli_cmd_flag_none,
2176           "= exit wpa_cli" },
2177         { "set", wpa_cli_cmd_set,
2178           cli_cmd_flag_none,
2179           "= set variables (shows list of variables when run without "
2180           "arguments)" },
2181         { "logon", wpa_cli_cmd_logon,
2182           cli_cmd_flag_none,
2183           "= IEEE 802.1X EAPOL state machine logon" },
2184         { "logoff", wpa_cli_cmd_logoff,
2185           cli_cmd_flag_none,
2186           "= IEEE 802.1X EAPOL state machine logoff" },
2187         { "pmksa", wpa_cli_cmd_pmksa,
2188           cli_cmd_flag_none,
2189           "= show PMKSA cache" },
2190         { "reassociate", wpa_cli_cmd_reassociate,
2191           cli_cmd_flag_none,
2192           "= force reassociation" },
2193         { "preauthenticate", wpa_cli_cmd_preauthenticate,
2194           cli_cmd_flag_none,
2195           "<BSSID> = force preauthentication" },
2196         { "identity", wpa_cli_cmd_identity,
2197           cli_cmd_flag_none,
2198           "<network id> <identity> = configure identity for an SSID" },
2199         { "password", wpa_cli_cmd_password,
2200           cli_cmd_flag_sensitive,
2201           "<network id> <password> = configure password for an SSID" },
2202         { "new_password", wpa_cli_cmd_new_password,
2203           cli_cmd_flag_sensitive,
2204           "<network id> <password> = change password for an SSID" },
2205         { "pin", wpa_cli_cmd_pin,
2206           cli_cmd_flag_sensitive,
2207           "<network id> <pin> = configure pin for an SSID" },
2208         { "otp", wpa_cli_cmd_otp,
2209           cli_cmd_flag_sensitive,
2210           "<network id> <password> = configure one-time-password for an SSID"
2211         },
2212         { "passphrase", wpa_cli_cmd_passphrase,
2213           cli_cmd_flag_sensitive,
2214           "<network id> <passphrase> = configure private key passphrase\n"
2215           "  for an SSID" },
2216         { "bssid", wpa_cli_cmd_bssid,
2217           cli_cmd_flag_none,
2218           "<network id> <BSSID> = set preferred BSSID for an SSID" },
2219         { "list_networks", wpa_cli_cmd_list_networks,
2220           cli_cmd_flag_none,
2221           "= list configured networks" },
2222         { "select_network", wpa_cli_cmd_select_network,
2223           cli_cmd_flag_none,
2224           "<network id> = select a network (disable others)" },
2225         { "enable_network", wpa_cli_cmd_enable_network,
2226           cli_cmd_flag_none,
2227           "<network id> = enable a network" },
2228         { "disable_network", wpa_cli_cmd_disable_network,
2229           cli_cmd_flag_none,
2230           "<network id> = disable a network" },
2231         { "add_network", wpa_cli_cmd_add_network,
2232           cli_cmd_flag_none,
2233           "= add a network" },
2234         { "remove_network", wpa_cli_cmd_remove_network,
2235           cli_cmd_flag_none,
2236           "<network id> = remove a network" },
2237         { "set_network", wpa_cli_cmd_set_network,
2238           cli_cmd_flag_sensitive,
2239           "<network id> <variable> <value> = set network variables (shows\n"
2240           "  list of variables when run without arguments)" },
2241         { "get_network", wpa_cli_cmd_get_network,
2242           cli_cmd_flag_none,
2243           "<network id> <variable> = get network variables" },
2244         { "save_config", wpa_cli_cmd_save_config,
2245           cli_cmd_flag_none,
2246           "= save the current configuration" },
2247         { "disconnect", wpa_cli_cmd_disconnect,
2248           cli_cmd_flag_none,
2249           "= disconnect and wait for reassociate/reconnect command before\n"
2250           "  connecting" },
2251         { "reconnect", wpa_cli_cmd_reconnect,
2252           cli_cmd_flag_none,
2253           "= like reassociate, but only takes effect if already disconnected"
2254         },
2255         { "scan", wpa_cli_cmd_scan,
2256           cli_cmd_flag_none,
2257           "= request new BSS scan" },
2258         { "scan_results", wpa_cli_cmd_scan_results,
2259           cli_cmd_flag_none,
2260           "= get latest scan results" },
2261         { "bss", wpa_cli_cmd_bss,
2262           cli_cmd_flag_none,
2263           "<<idx> | <bssid>> = get detailed scan result info" },
2264         { "get_capability", wpa_cli_cmd_get_capability,
2265           cli_cmd_flag_none,
2266           "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2267         { "reconfigure", wpa_cli_cmd_reconfigure,
2268           cli_cmd_flag_none,
2269           "= force wpa_supplicant to re-read its configuration file" },
2270         { "terminate", wpa_cli_cmd_terminate,
2271           cli_cmd_flag_none,
2272           "= terminate wpa_supplicant" },
2273         { "interface_add", wpa_cli_cmd_interface_add,
2274           cli_cmd_flag_none,
2275           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2276           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2277           "  are optional" },
2278         { "interface_remove", wpa_cli_cmd_interface_remove,
2279           cli_cmd_flag_none,
2280           "<ifname> = removes the interface" },
2281         { "interface_list", wpa_cli_cmd_interface_list,
2282           cli_cmd_flag_none,
2283           "= list available interfaces" },
2284         { "ap_scan", wpa_cli_cmd_ap_scan,
2285           cli_cmd_flag_none,
2286           "<value> = set ap_scan parameter" },
2287         { "stkstart", wpa_cli_cmd_stkstart,
2288           cli_cmd_flag_none,
2289           "<addr> = request STK negotiation with <addr>" },
2290         { "ft_ds", wpa_cli_cmd_ft_ds,
2291           cli_cmd_flag_none,
2292           "<addr> = request over-the-DS FT with <addr>" },
2293         { "wps_pbc", wpa_cli_cmd_wps_pbc,
2294           cli_cmd_flag_none,
2295           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2296         { "wps_pin", wpa_cli_cmd_wps_pin,
2297           cli_cmd_flag_sensitive,
2298           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2299           "hardcoded)" },
2300         { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2301           cli_cmd_flag_sensitive,
2302           "<PIN> = verify PIN checksum" },
2303         { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2304           "Cancels the pending WPS operation" },
2305 #ifdef CONFIG_WPS_OOB
2306         { "wps_oob", wpa_cli_cmd_wps_oob,
2307           cli_cmd_flag_sensitive,
2308           "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2309 #endif /* CONFIG_WPS_OOB */
2310         { "wps_reg", wpa_cli_cmd_wps_reg,
2311           cli_cmd_flag_sensitive,
2312           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2313         { "wps_er_start", wpa_cli_cmd_wps_er_start,
2314           cli_cmd_flag_none,
2315           "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2316         { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2317           cli_cmd_flag_none,
2318           "= stop Wi-Fi Protected Setup External Registrar" },
2319         { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2320           cli_cmd_flag_sensitive,
2321           "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2322         { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2323           cli_cmd_flag_none,
2324           "<UUID> = accept an Enrollee PBC using External Registrar" },
2325         { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2326           cli_cmd_flag_sensitive,
2327           "<UUID> <PIN> = learn AP configuration" },
2328         { "wps_er_config", wpa_cli_cmd_wps_er_config,
2329           cli_cmd_flag_sensitive,
2330           "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2331         { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2332           cli_cmd_flag_none,
2333           "<addr> = request RSN authentication with <addr> in IBSS" },
2334 #ifdef CONFIG_AP
2335         { "sta", wpa_cli_cmd_sta,
2336           cli_cmd_flag_none,
2337           "<addr> = get information about an associated station (AP)" },
2338         { "all_sta", wpa_cli_cmd_all_sta,
2339           cli_cmd_flag_none,
2340           "= get information about all associated stations (AP)" },
2341 #endif /* CONFIG_AP */
2342         { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2343           "= notification of suspend/hibernate" },
2344         { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2345           "= notification of resume/thaw" },
2346         { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2347           "= drop SA without deauth/disassoc (test command)" },
2348         { "roam", wpa_cli_cmd_roam,
2349           cli_cmd_flag_none,
2350           "<addr> = roam to the specified BSS" },
2351 #ifdef CONFIG_P2P
2352         { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2353           "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2354         { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2355           "= stop P2P Devices search" },
2356         { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2357           "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2358         { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2359           "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2360         { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2361           "<ifname> = remote P2P group interface (terminate group if GO)" },
2362         { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2363           "= add a new P2P group (local end as GO)" },
2364         { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2365           "<addr> <method> = request provisioning discovery" },
2366         { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2367           cli_cmd_flag_none,
2368           "= get the passphrase for a group (GO only)" },
2369         { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2370           cli_cmd_flag_none,
2371           "<addr> <TLVs> = schedule service discovery request" },
2372         { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2373           cli_cmd_flag_none,
2374           "<id> = cancel pending service discovery request" },
2375         { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2376           cli_cmd_flag_none,
2377           "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2378         { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2379           cli_cmd_flag_none,
2380           "= indicate change in local services" },
2381         { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2382           cli_cmd_flag_none,
2383           "<external> = set external processing of service discovery" },
2384         { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2385           cli_cmd_flag_none,
2386           "= remove all stored service entries" },
2387         { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2388           cli_cmd_flag_none,
2389           "<bonjour|upnp> <query|version> <response|service> = add a local "
2390           "service" },
2391         { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2392           cli_cmd_flag_none,
2393           "<bonjour|upnp> <query|version> [|service] = remove a local "
2394           "service" },
2395         { "p2p_reject", wpa_cli_cmd_p2p_reject,
2396           cli_cmd_flag_none,
2397           "<addr> = reject connection attempts from a specific peer" },
2398         { "p2p_invite", wpa_cli_cmd_p2p_invite,
2399           cli_cmd_flag_none,
2400           "<cmd> [peer=addr] = invite peer" },
2401         { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2402           "[discovered] = list known (optionally, only fully discovered) P2P "
2403           "peers" },
2404         { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2405           "<address> = show information about known P2P peer" },
2406         { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2407           "<field> <value> = set a P2P parameter" },
2408         { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2409           "= flush P2P state" },
2410         { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2411           "[<duration> <interval>] [<duration> <interval>] = request GO "
2412           "presence" },
2413         { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2414           "[<period> <interval>] = set extended listen timing" },
2415 #endif /* CONFIG_P2P */
2416         { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2417           "<0/1> = disable/enable automatic reconnection" },
2418         { NULL, NULL, cli_cmd_flag_none, NULL }
2419 };
2420
2421
2422 /*
2423  * Prints command usage, lines are padded with the specified string.
2424  */
2425 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2426 {
2427         char c;
2428         size_t n;
2429
2430         printf("%s%s ", pad, cmd->cmd);
2431         for (n = 0; (c = cmd->usage[n]); n++) {
2432                 printf("%c", c);
2433                 if (c == '\n')
2434                         printf("%s", pad);
2435         }
2436         printf("\n");
2437 }
2438
2439
2440 static void print_help(void)
2441 {
2442         int n;
2443         printf("commands:\n");
2444         for (n = 0; wpa_cli_commands[n].cmd; n++)
2445                 print_cmd_help(&wpa_cli_commands[n], "  ");
2446 }
2447
2448
2449 #ifdef CONFIG_READLINE
2450 static int cmd_has_sensitive_data(const char *cmd)
2451 {
2452         const char *c, *delim;
2453         int n;
2454         size_t len;
2455
2456         delim = os_strchr(cmd, ' ');
2457         if (delim)
2458                 len = delim - cmd;
2459         else
2460                 len = os_strlen(cmd);
2461
2462         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2463                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2464                         return (wpa_cli_commands[n].flags &
2465                                 cli_cmd_flag_sensitive);
2466         }
2467         return 0;
2468 }
2469 #endif /* CONFIG_READLINE */
2470
2471
2472 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2473 {
2474         struct wpa_cli_cmd *cmd, *match = NULL;
2475         int count;
2476         int ret = 0;
2477
2478         count = 0;
2479         cmd = wpa_cli_commands;
2480         while (cmd->cmd) {
2481                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2482                 {
2483                         match = cmd;
2484                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2485                                 /* we have an exact match */
2486                                 count = 1;
2487                                 break;
2488                         }
2489                         count++;
2490                 }
2491                 cmd++;
2492         }
2493
2494         if (count > 1) {
2495                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2496                 cmd = wpa_cli_commands;
2497                 while (cmd->cmd) {
2498                         if (os_strncasecmp(cmd->cmd, argv[0],
2499                                            os_strlen(argv[0])) == 0) {
2500                                 printf(" %s", cmd->cmd);
2501                         }
2502                         cmd++;
2503                 }
2504                 printf("\n");
2505                 ret = 1;
2506         } else if (count == 0) {
2507                 printf("Unknown command '%s'\n", argv[0]);
2508                 ret = 1;
2509         } else {
2510                 ret = match->handler(ctrl, argc - 1, &argv[1]);
2511         }
2512
2513         return ret;
2514 }
2515
2516
2517 static int str_match(const char *a, const char *b)
2518 {
2519         return os_strncmp(a, b, os_strlen(b)) == 0;
2520 }
2521
2522
2523 static int wpa_cli_exec(const char *program, const char *arg1,
2524                         const char *arg2)
2525 {
2526         char *cmd;
2527         size_t len;
2528         int res;
2529         int ret = 0;
2530
2531         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2532         cmd = os_malloc(len);
2533         if (cmd == NULL)
2534                 return -1;
2535         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2536         if (res < 0 || (size_t) res >= len) {
2537                 os_free(cmd);
2538                 return -1;
2539         }
2540         cmd[len - 1] = '\0';
2541 #ifndef _WIN32_WCE
2542         if (system(cmd) < 0)
2543                 ret = -1;
2544 #endif /* _WIN32_WCE */
2545         os_free(cmd);
2546
2547         return ret;
2548 }
2549
2550
2551 static void wpa_cli_action_process(const char *msg)
2552 {
2553         const char *pos;
2554         char *copy = NULL, *id, *pos2;
2555
2556         pos = msg;
2557         if (*pos == '<') {
2558                 /* skip priority */
2559                 pos = os_strchr(pos, '>');
2560                 if (pos)
2561                         pos++;
2562                 else
2563                         pos = msg;
2564         }
2565
2566         if (str_match(pos, WPA_EVENT_CONNECTED)) {
2567                 int new_id = -1;
2568                 os_unsetenv("WPA_ID");
2569                 os_unsetenv("WPA_ID_STR");
2570                 os_unsetenv("WPA_CTRL_DIR");
2571
2572                 pos = os_strstr(pos, "[id=");
2573                 if (pos)
2574                         copy = os_strdup(pos + 4);
2575
2576                 if (copy) {
2577                         pos2 = id = copy;
2578                         while (*pos2 && *pos2 != ' ')
2579                                 pos2++;
2580                         *pos2++ = '\0';
2581                         new_id = atoi(id);
2582                         os_setenv("WPA_ID", id, 1);
2583                         while (*pos2 && *pos2 != '=')
2584                                 pos2++;
2585                         if (*pos2 == '=')
2586                                 pos2++;
2587                         id = pos2;
2588                         while (*pos2 && *pos2 != ']')
2589                                 pos2++;
2590                         *pos2 = '\0';
2591                         os_setenv("WPA_ID_STR", id, 1);
2592                         os_free(copy);
2593                 }
2594
2595                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2596
2597                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2598                         wpa_cli_connected = 1;
2599                         wpa_cli_last_id = new_id;
2600                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2601                 }
2602         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2603                 if (wpa_cli_connected) {
2604                         wpa_cli_connected = 0;
2605                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2606                 }
2607         } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2608                 wpa_cli_exec(action_file, ctrl_ifname, pos);
2609         } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2610                 wpa_cli_exec(action_file, ctrl_ifname, pos);
2611         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2612                 wpa_cli_exec(action_file, ctrl_ifname, pos);
2613         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2614                 wpa_cli_exec(action_file, ctrl_ifname, pos);
2615         } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2616                 wpa_cli_exec(action_file, ctrl_ifname, pos);
2617         } else if (str_match(pos, WPS_EVENT_FAIL)) {
2618                 wpa_cli_exec(action_file, ctrl_ifname, pos);
2619         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2620                 printf("wpa_supplicant is terminating - stop monitoring\n");
2621                 wpa_cli_quit = 1;
2622         }
2623 }
2624
2625
2626 #ifndef CONFIG_ANSI_C_EXTRA
2627 static void wpa_cli_action_cb(char *msg, size_t len)
2628 {
2629         wpa_cli_action_process(msg);
2630 }
2631 #endif /* CONFIG_ANSI_C_EXTRA */
2632
2633
2634 static void wpa_cli_reconnect(void)
2635 {
2636         wpa_cli_close_connection();
2637         wpa_cli_open_connection(ctrl_ifname, 1);
2638 }
2639
2640
2641 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
2642                                  int action_monitor)
2643 {
2644         int first = 1;
2645         if (ctrl_conn == NULL) {
2646                 wpa_cli_reconnect();
2647                 return;
2648         }
2649         while (wpa_ctrl_pending(ctrl) > 0) {
2650                 char buf[256];
2651                 size_t len = sizeof(buf) - 1;
2652                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2653                         buf[len] = '\0';
2654                         if (action_monitor)
2655                                 wpa_cli_action_process(buf);
2656                         else {
2657                                 if (wpa_cli_show_event(buf)) {
2658                                         if (in_read && first)
2659                                                 printf("\r");
2660                                         first = 0;
2661                                         printf("%s\n", buf);
2662                                         readline_redraw();
2663                                 }
2664                         }
2665                 } else {
2666                         printf("Could not read pending message.\n");
2667                         break;
2668                 }
2669         }
2670
2671         if (wpa_ctrl_pending(ctrl) < 0) {
2672                 printf("Connection to wpa_supplicant lost - trying to "
2673                        "reconnect\n");
2674                 wpa_cli_reconnect();
2675         }
2676 }
2677
2678
2679 #ifdef CONFIG_READLINE
2680 static char * wpa_cli_cmd_gen(const char *text, int state)
2681 {
2682         static int i, len;
2683         const char *cmd;
2684
2685         if (state == 0) {
2686                 i = 0;
2687                 len = os_strlen(text);
2688         }
2689
2690         while ((cmd = wpa_cli_commands[i].cmd)) {
2691                 i++;
2692                 if (os_strncasecmp(cmd, text, len) == 0)
2693                         return strdup(cmd);
2694         }
2695
2696         return NULL;
2697 }
2698
2699
2700 static char * wpa_cli_dummy_gen(const char *text, int state)
2701 {
2702         int i;
2703
2704         for (i = 0; wpa_cli_commands[i].cmd; i++) {
2705                 const char *cmd = wpa_cli_commands[i].cmd;
2706                 size_t len = os_strlen(cmd);
2707                 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
2708                     rl_line_buffer[len] == ' ') {
2709                         printf("\n%s\n", wpa_cli_commands[i].usage);
2710                         readline_redraw();
2711                         break;
2712                 }
2713         }
2714
2715         rl_attempted_completion_over = 1;
2716         return NULL;
2717 }
2718
2719
2720 static char * wpa_cli_status_gen(const char *text, int state)
2721 {
2722         static int i, len;
2723         char *options[] = {
2724                 "verbose", NULL
2725         };
2726         char *t;
2727
2728         if (state == 0) {
2729                 i = 0;
2730                 len = os_strlen(text);
2731         }
2732
2733         while ((t = options[i])) {
2734                 i++;
2735                 if (os_strncasecmp(t, text, len) == 0)
2736                         return strdup(t);
2737         }
2738
2739         rl_attempted_completion_over = 1;
2740         return NULL;
2741 }
2742
2743
2744 static char ** wpa_cli_completion(const char *text, int start, int end)
2745 {
2746         char * (*func)(const char *text, int state);
2747
2748         if (start == 0)
2749                 func = wpa_cli_cmd_gen;
2750         else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
2751                 func = wpa_cli_status_gen;
2752         else
2753                 func = wpa_cli_dummy_gen;
2754         return rl_completion_matches(text, func);
2755 }
2756 #endif /* CONFIG_READLINE */
2757
2758
2759 static void wpa_cli_interactive(void)
2760 {
2761 #define max_args 10
2762         char cmdbuf[256], *cmd, *argv[max_args], *pos;
2763         int argc;
2764 #ifdef CONFIG_READLINE
2765         char *home, *hfile = NULL;
2766 #endif /* CONFIG_READLINE */
2767
2768         printf("\nInteractive mode\n\n");
2769
2770 #ifdef CONFIG_READLINE
2771         rl_attempted_completion_function = wpa_cli_completion;
2772         home = getenv("HOME");
2773         if (home) {
2774                 const char *fname = ".wpa_cli_history";
2775                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2776                 hfile = os_malloc(hfile_len);
2777                 if (hfile) {
2778                         int res;
2779                         res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2780                                           fname);
2781                         if (res >= 0 && res < hfile_len) {
2782                                 hfile[hfile_len - 1] = '\0';
2783                                 read_history(hfile);
2784                                 stifle_history(100);
2785                         }
2786                 }
2787         }
2788 #endif /* CONFIG_READLINE */
2789
2790         do {
2791                 wpa_cli_recv_pending(mon_conn, 0, 0);
2792 #ifndef CONFIG_NATIVE_WINDOWS
2793                 alarm(ping_interval);
2794 #endif /* CONFIG_NATIVE_WINDOWS */
2795 #ifdef CONFIG_WPA_CLI_FORK
2796                 if (mon_pid)
2797                         kill(mon_pid, SIGUSR1);
2798 #endif /* CONFIG_WPA_CLI_FORK */
2799 #ifdef CONFIG_READLINE
2800                 cmd = readline("> ");
2801                 if (cmd && *cmd) {
2802                         HIST_ENTRY *h;
2803                         while (next_history())
2804                                 ;
2805                         h = previous_history();
2806                         if (h == NULL || os_strcmp(cmd, h->line) != 0)
2807                                 add_history(cmd);
2808                         next_history();
2809                 }
2810 #else /* CONFIG_READLINE */
2811                 printf("> ");
2812                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2813 #endif /* CONFIG_READLINE */
2814 #ifndef CONFIG_NATIVE_WINDOWS
2815                 alarm(0);
2816 #endif /* CONFIG_NATIVE_WINDOWS */
2817                 if (cmd == NULL)
2818                         break;
2819                 wpa_cli_recv_pending(mon_conn, 0, 0);
2820                 pos = cmd;
2821                 while (*pos != '\0') {
2822                         if (*pos == '\n') {
2823                                 *pos = '\0';
2824                                 break;
2825                         }
2826                         pos++;
2827                 }
2828                 argc = 0;
2829                 pos = cmd;
2830                 for (;;) {
2831                         while (*pos == ' ')
2832                                 pos++;
2833                         if (*pos == '\0')
2834                                 break;
2835                         argv[argc] = pos;
2836                         argc++;
2837                         if (argc == max_args)
2838                                 break;
2839                         if (*pos == '"') {
2840                                 char *pos2 = os_strrchr(pos, '"');
2841                                 if (pos2)
2842                                         pos = pos2 + 1;
2843                         }
2844                         while (*pos != '\0' && *pos != ' ')
2845                                 pos++;
2846                         if (*pos == ' ')
2847                                 *pos++ = '\0';
2848                 }
2849                 if (argc)
2850                         wpa_request(ctrl_conn, argc, argv);
2851
2852                 if (cmd != cmdbuf)
2853                         free(cmd);
2854 #ifdef CONFIG_WPA_CLI_FORK
2855                 if (mon_pid)
2856                         kill(mon_pid, SIGUSR2);
2857 #endif /* CONFIG_WPA_CLI_FORK */
2858         } while (!wpa_cli_quit);
2859
2860 #ifdef CONFIG_READLINE
2861         if (hfile) {
2862                 /* Save command history, excluding lines that may contain
2863                  * passwords. */
2864                 HIST_ENTRY *h;
2865                 history_set_pos(0);
2866                 while ((h = current_history())) {
2867                         char *p = h->line;
2868                         while (*p == ' ' || *p == '\t')
2869                                 p++;
2870                         if (cmd_has_sensitive_data(p)) {
2871                                 h = remove_history(where_history());
2872                                 if (h) {
2873                                         os_free(h->line);
2874                                         os_free(h->data);
2875                                         os_free(h);
2876                                 } else
2877                                         next_history();
2878                         } else
2879                                 next_history();
2880                 }
2881                 write_history(hfile);
2882                 os_free(hfile);
2883         }
2884 #endif /* CONFIG_READLINE */
2885 }
2886
2887
2888 static void wpa_cli_action(struct wpa_ctrl *ctrl)
2889 {
2890 #ifdef CONFIG_ANSI_C_EXTRA
2891         /* TODO: ANSI C version(?) */
2892         printf("Action processing not supported in ANSI C build.\n");
2893 #else /* CONFIG_ANSI_C_EXTRA */
2894         fd_set rfds;
2895         int fd, res;
2896         struct timeval tv;
2897         char buf[256]; /* note: large enough to fit in unsolicited messages */
2898         size_t len;
2899
2900         fd = wpa_ctrl_get_fd(ctrl);
2901
2902         while (!wpa_cli_quit) {
2903                 FD_ZERO(&rfds);
2904                 FD_SET(fd, &rfds);
2905                 tv.tv_sec = ping_interval;
2906                 tv.tv_usec = 0;
2907                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
2908                 if (res < 0 && errno != EINTR) {
2909                         perror("select");
2910                         break;
2911                 }
2912
2913                 if (FD_ISSET(fd, &rfds))
2914                         wpa_cli_recv_pending(ctrl, 0, 1);
2915                 else {
2916                         /* verify that connection is still working */
2917                         len = sizeof(buf) - 1;
2918                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2919                                              wpa_cli_action_cb) < 0 ||
2920                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2921                                 printf("wpa_supplicant did not reply to PING "
2922                                        "command - exiting\n");
2923                                 break;
2924                         }
2925                 }
2926         }
2927 #endif /* CONFIG_ANSI_C_EXTRA */
2928 }
2929
2930
2931 static void wpa_cli_cleanup(void)
2932 {
2933         wpa_cli_close_connection();
2934         if (pid_file)
2935                 os_daemonize_terminate(pid_file);
2936
2937         os_program_deinit();
2938 }
2939
2940 static void wpa_cli_terminate(int sig)
2941 {
2942         wpa_cli_cleanup();
2943         exit(0);
2944 }
2945
2946
2947 #ifdef CONFIG_WPA_CLI_FORK
2948 static void wpa_cli_usr1(int sig)
2949 {
2950         readline_redraw();
2951 }
2952 #endif /* CONFIG_WPA_CLI_FORK */
2953
2954
2955 #ifndef CONFIG_NATIVE_WINDOWS
2956 static void wpa_cli_alarm(int sig)
2957 {
2958         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2959                 printf("Connection to wpa_supplicant lost - trying to "
2960                        "reconnect\n");
2961                 wpa_cli_close_connection();
2962         }
2963         if (!ctrl_conn)
2964                 wpa_cli_reconnect();
2965         if (mon_conn)
2966                 wpa_cli_recv_pending(mon_conn, 1, 0);
2967         alarm(ping_interval);
2968 }
2969 #endif /* CONFIG_NATIVE_WINDOWS */
2970
2971
2972 static char * wpa_cli_get_default_ifname(void)
2973 {
2974         char *ifname = NULL;
2975
2976 #ifdef CONFIG_CTRL_IFACE_UNIX
2977         struct dirent *dent;
2978         DIR *dir = opendir(ctrl_iface_dir);
2979         if (!dir)
2980                 return NULL;
2981         while ((dent = readdir(dir))) {
2982 #ifdef _DIRENT_HAVE_D_TYPE
2983                 /*
2984                  * Skip the file if it is not a socket. Also accept
2985                  * DT_UNKNOWN (0) in case the C library or underlying
2986                  * file system does not support d_type.
2987                  */
2988                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2989                         continue;
2990 #endif /* _DIRENT_HAVE_D_TYPE */
2991                 if (os_strcmp(dent->d_name, ".") == 0 ||
2992                     os_strcmp(dent->d_name, "..") == 0)
2993                         continue;
2994                 printf("Selected interface '%s'\n", dent->d_name);
2995                 ifname = os_strdup(dent->d_name);
2996                 break;
2997         }
2998         closedir(dir);
2999 #endif /* CONFIG_CTRL_IFACE_UNIX */
3000
3001 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3002         char buf[2048], *pos;
3003         size_t len;
3004         struct wpa_ctrl *ctrl;
3005         int ret;
3006
3007         ctrl = wpa_ctrl_open(NULL);
3008         if (ctrl == NULL)
3009                 return NULL;
3010
3011         len = sizeof(buf) - 1;
3012         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3013         if (ret >= 0) {
3014                 buf[len] = '\0';
3015                 pos = os_strchr(buf, '\n');
3016                 if (pos)
3017                         *pos = '\0';
3018                 ifname = os_strdup(buf);
3019         }
3020         wpa_ctrl_close(ctrl);
3021 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3022
3023         return ifname;
3024 }
3025
3026
3027 int main(int argc, char *argv[])
3028 {
3029         int warning_displayed = 0;
3030         int c;
3031         int daemonize = 0;
3032         int ret = 0;
3033         const char *global = NULL;
3034
3035         if (os_program_init())
3036                 return -1;
3037
3038         for (;;) {
3039                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3040                 if (c < 0)
3041                         break;
3042                 switch (c) {
3043                 case 'a':
3044                         action_file = optarg;
3045                         break;
3046                 case 'B':
3047                         daemonize = 1;
3048                         break;
3049                 case 'g':
3050                         global = optarg;
3051                         break;
3052                 case 'G':
3053                         ping_interval = atoi(optarg);
3054                         break;
3055                 case 'h':
3056                         usage();
3057                         return 0;
3058                 case 'v':
3059                         printf("%s\n", wpa_cli_version);
3060                         return 0;
3061                 case 'i':
3062                         os_free(ctrl_ifname);
3063                         ctrl_ifname = os_strdup(optarg);
3064                         break;
3065                 case 'p':
3066                         ctrl_iface_dir = optarg;
3067                         break;
3068                 case 'P':
3069                         pid_file = optarg;
3070                         break;
3071                 default:
3072                         usage();
3073                         return -1;
3074                 }
3075         }
3076
3077         interactive = (argc == optind) && (action_file == NULL);
3078
3079         if (interactive)
3080                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3081
3082         if (global) {
3083 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3084                 ctrl_conn = wpa_ctrl_open(NULL);
3085 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3086                 ctrl_conn = wpa_ctrl_open(global);
3087 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3088                 if (ctrl_conn == NULL) {
3089                         perror("Failed to connect to wpa_supplicant - "
3090                                "wpa_ctrl_open");
3091                         return -1;
3092                 }
3093         }
3094
3095 #ifndef _WIN32_WCE
3096         signal(SIGINT, wpa_cli_terminate);
3097         signal(SIGTERM, wpa_cli_terminate);
3098 #endif /* _WIN32_WCE */
3099 #ifndef CONFIG_NATIVE_WINDOWS
3100         signal(SIGALRM, wpa_cli_alarm);
3101 #endif /* CONFIG_NATIVE_WINDOWS */
3102 #ifdef CONFIG_WPA_CLI_FORK
3103         signal(SIGUSR1, wpa_cli_usr1);
3104 #endif /* CONFIG_WPA_CLI_FORK */
3105
3106         if (ctrl_ifname == NULL)
3107                 ctrl_ifname = wpa_cli_get_default_ifname();
3108
3109         if (interactive) {
3110                 for (; !global;) {
3111                         if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3112                                 if (warning_displayed)
3113                                         printf("Connection established.\n");
3114                                 break;
3115                         }
3116
3117                         if (!warning_displayed) {
3118                                 printf("Could not connect to wpa_supplicant - "
3119                                        "re-trying\n");
3120                                 warning_displayed = 1;
3121                         }
3122                         os_sleep(1, 0);
3123                         continue;
3124                 }
3125         } else {
3126                 if (!global &&
3127                     wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3128                         perror("Failed to connect to wpa_supplicant - "
3129                                "wpa_ctrl_open");
3130                         return -1;
3131                 }
3132
3133                 if (action_file) {
3134                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
3135                                 wpa_cli_attached = 1;
3136                         } else {
3137                                 printf("Warning: Failed to attach to "
3138                                        "wpa_supplicant.\n");
3139                                 return -1;
3140                         }
3141                 }
3142         }
3143
3144         if (daemonize && os_daemonize(pid_file))
3145                 return -1;
3146
3147         if (interactive)
3148                 wpa_cli_interactive();
3149         else if (action_file)
3150                 wpa_cli_action(ctrl_conn);
3151         else
3152                 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3153
3154         os_free(ctrl_ifname);
3155         wpa_cli_cleanup();
3156
3157         return ret;
3158 }
3159
3160 #else /* CONFIG_CTRL_IFACE */
3161 int main(int argc, char *argv[])
3162 {
3163         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3164         return -1;
3165 }
3166 #endif /* CONFIG_CTRL_IFACE */