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