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