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