bae0d6f405dd408892ccb8e6ba536275a2b94901
[wpasupplicant] / wpa_supplicant / wpa_cli.c
1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2009, 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 "wpa_ctrl.h"
28 #include "common.h"
29 #include "version.h"
30
31
32 static const char *wpa_cli_version =
33 "wpa_cli v" VERSION_STR "\n"
34 "Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
35
36
37 static const char *wpa_cli_license =
38 "This program is free software. You can distribute it and/or modify it\n"
39 "under the terms of the GNU General Public License version 2.\n"
40 "\n"
41 "Alternatively, this software may be distributed under the terms of the\n"
42 "BSD license. See README and COPYING for more details.\n";
43
44 static const char *wpa_cli_full_license =
45 "This program is free software; you can redistribute it and/or modify\n"
46 "it under the terms of the GNU General Public License version 2 as\n"
47 "published by the Free Software Foundation.\n"
48 "\n"
49 "This program is distributed in the hope that it will be useful,\n"
50 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
52 "GNU General Public License for more details.\n"
53 "\n"
54 "You should have received a copy of the GNU General Public License\n"
55 "along with this program; if not, write to the Free Software\n"
56 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
57 "\n"
58 "Alternatively, this software may be distributed under the terms of the\n"
59 "BSD license.\n"
60 "\n"
61 "Redistribution and use in source and binary forms, with or without\n"
62 "modification, are permitted provided that the following conditions are\n"
63 "met:\n"
64 "\n"
65 "1. Redistributions of source code must retain the above copyright\n"
66 "   notice, this list of conditions and the following disclaimer.\n"
67 "\n"
68 "2. Redistributions in binary form must reproduce the above copyright\n"
69 "   notice, this list of conditions and the following disclaimer in the\n"
70 "   documentation and/or other materials provided with the distribution.\n"
71 "\n"
72 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73 "   names of its contributors may be used to endorse or promote products\n"
74 "   derived from this software without specific prior written permission.\n"
75 "\n"
76 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
87 "\n";
88
89 static struct wpa_ctrl *ctrl_conn;
90 static int wpa_cli_quit = 0;
91 static int wpa_cli_attached = 0;
92 static int wpa_cli_connected = 0;
93 static int wpa_cli_last_id = 0;
94 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
95 static char *ctrl_ifname = NULL;
96 static const char *pid_file = NULL;
97 static const char *action_file = NULL;
98 static int ping_interval = 5;
99
100
101 static void print_help();
102
103
104 static void usage(void)
105 {
106         printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107                "[-a<action file>] \\\n"
108                "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  "
109                "[command..]\n"
110                "  -h = help (show this usage text)\n"
111                "  -v = shown version information\n"
112                "  -a = run in daemon mode executing the action file based on "
113                "events from\n"
114                "       wpa_supplicant\n"
115                "  -B = run a daemon in the background\n"
116                "  default path: /var/run/wpa_supplicant\n"
117                "  default interface: first interface found in socket path\n");
118         print_help();
119 }
120
121
122 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
123 {
124 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
125         ctrl_conn = wpa_ctrl_open(ifname);
126         return ctrl_conn;
127 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
128         char *cfile;
129         int flen, res;
130
131         if (ifname == NULL)
132                 return NULL;
133
134         flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
135         cfile = os_malloc(flen);
136         if (cfile == NULL)
137                 return NULL;
138         res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
139         if (res < 0 || res >= flen) {
140                 os_free(cfile);
141                 return NULL;
142         }
143
144         ctrl_conn = wpa_ctrl_open(cfile);
145         os_free(cfile);
146         return ctrl_conn;
147 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
148 }
149
150
151 static void wpa_cli_close_connection(void)
152 {
153         if (ctrl_conn == NULL)
154                 return;
155
156         if (wpa_cli_attached) {
157                 wpa_ctrl_detach(ctrl_conn);
158                 wpa_cli_attached = 0;
159         }
160         wpa_ctrl_close(ctrl_conn);
161         ctrl_conn = NULL;
162 }
163
164
165 static void wpa_cli_msg_cb(char *msg, size_t len)
166 {
167         printf("%s\n", msg);
168 }
169
170
171 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
172 {
173         char buf[2048];
174         size_t len;
175         int ret;
176
177         if (ctrl_conn == NULL) {
178                 printf("Not connected to wpa_supplicant - command dropped.\n");
179                 return -1;
180         }
181         len = sizeof(buf) - 1;
182         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
183                                wpa_cli_msg_cb);
184         if (ret == -2) {
185                 printf("'%s' command timed out.\n", cmd);
186                 return -2;
187         } else if (ret < 0) {
188                 printf("'%s' command failed.\n", cmd);
189                 return -1;
190         }
191         if (print) {
192                 buf[len] = '\0';
193                 printf("%s", buf);
194         }
195         return 0;
196 }
197
198
199 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
200 {
201         return _wpa_ctrl_command(ctrl, cmd, 1);
202 }
203
204
205 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
206 {
207         int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
208         return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
209 }
210
211
212 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
213 {
214         return wpa_ctrl_command(ctrl, "PING");
215 }
216
217
218 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
219 {
220         return wpa_ctrl_command(ctrl, "MIB");
221 }
222
223
224 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
225 {
226         return wpa_ctrl_command(ctrl, "PMKSA");
227 }
228
229
230 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
231 {
232         print_help();
233         return 0;
234 }
235
236
237 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
238 {
239         printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
240         return 0;
241 }
242
243
244 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
245 {
246         wpa_cli_quit = 1;
247         return 0;
248 }
249
250
251 static void wpa_cli_show_variables(void)
252 {
253         printf("set variables:\n"
254                "  EAPOL::heldPeriod (EAPOL state machine held period, "
255                "in seconds)\n"
256                "  EAPOL::authPeriod (EAPOL state machine authentication "
257                "period, in seconds)\n"
258                "  EAPOL::startPeriod (EAPOL state machine start period, in "
259                "seconds)\n"
260                "  EAPOL::maxStart (EAPOL state machine maximum start "
261                "attempts)\n");
262         printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
263                "seconds)\n"
264                "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
265                " threshold\n\tpercentage)\n"
266                "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
267                "security\n\tassociation in seconds)\n");
268 }
269
270
271 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
272 {
273         char cmd[256];
274         int res;
275
276         if (argc == 0) {
277                 wpa_cli_show_variables();
278                 return 0;
279         }
280
281         if (argc != 2) {
282                 printf("Invalid SET command: needs two arguments (variable "
283                        "name and value)\n");
284                 return -1;
285         }
286
287         res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
288         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
289                 printf("Too long SET command.\n");
290                 return -1;
291         }
292         return wpa_ctrl_command(ctrl, cmd);
293 }
294
295
296 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
297 {
298         return wpa_ctrl_command(ctrl, "LOGOFF");
299 }
300
301
302 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
303 {
304         return wpa_ctrl_command(ctrl, "LOGON");
305 }
306
307
308 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
309                                    char *argv[])
310 {
311         return wpa_ctrl_command(ctrl, "REASSOCIATE");
312 }
313
314
315 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
316                                        char *argv[])
317 {
318         char cmd[256];
319         int res;
320
321         if (argc != 1) {
322                 printf("Invalid PREAUTH command: needs one argument "
323                        "(BSSID)\n");
324                 return -1;
325         }
326
327         res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
328         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
329                 printf("Too long PREAUTH command.\n");
330                 return -1;
331         }
332         return wpa_ctrl_command(ctrl, cmd);
333 }
334
335
336 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
337 {
338         char cmd[256];
339         int res;
340
341         if (argc != 1) {
342                 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
343                        "value)\n");
344                 return -1;
345         }
346         res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
347         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
348                 printf("Too long AP_SCAN command.\n");
349                 return -1;
350         }
351         return wpa_ctrl_command(ctrl, cmd);
352 }
353
354
355 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
356                                 char *argv[])
357 {
358         char cmd[256];
359         int res;
360
361         if (argc != 1) {
362                 printf("Invalid STKSTART command: needs one argument "
363                        "(Peer STA MAC address)\n");
364                 return -1;
365         }
366
367         res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
368         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
369                 printf("Too long STKSTART command.\n");
370                 return -1;
371         }
372         return wpa_ctrl_command(ctrl, cmd);
373 }
374
375
376 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
377 {
378         char cmd[256];
379         int res;
380
381         if (argc != 1) {
382                 printf("Invalid FT_DS command: needs one argument "
383                        "(Target AP MAC address)\n");
384                 return -1;
385         }
386
387         res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
388         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
389                 printf("Too long FT_DS command.\n");
390                 return -1;
391         }
392         return wpa_ctrl_command(ctrl, cmd);
393 }
394
395
396 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
397 {
398         char cmd[256];
399         int res;
400
401         if (argc == 0) {
402                 /* Any BSSID */
403                 return wpa_ctrl_command(ctrl, "WPS_PBC");
404         }
405
406         /* Specific BSSID */
407         res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
408         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
409                 printf("Too long WPS_PBC command.\n");
410                 return -1;
411         }
412         return wpa_ctrl_command(ctrl, cmd);
413 }
414
415
416 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
417 {
418         char cmd[256];
419         int res;
420
421         if (argc == 0) {
422                 printf("Invalid WPS_PIN command: need one or two arguments:\n"
423                        "- BSSID: use 'any' to select any\n"
424                        "- PIN: optional, used only with devices that have no "
425                        "display\n");
426                 return -1;
427         }
428
429         if (argc == 1) {
430                 /* Use dynamically generated PIN (returned as reply) */
431                 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
432                 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
433                         printf("Too long WPS_PIN command.\n");
434                         return -1;
435                 }
436                 return wpa_ctrl_command(ctrl, cmd);
437         }
438
439         /* Use hardcoded PIN from a label */
440         res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
441         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
442                 printf("Too long WPS_PIN command.\n");
443                 return -1;
444         }
445         return wpa_ctrl_command(ctrl, cmd);
446 }
447
448
449 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
450 {
451         char cmd[256];
452         int res;
453
454         if (argc != 3) {
455                 printf("Invalid WPS_OOB command: need three arguments:\n"
456                        "- OOB_DEV_TYPE: use 'ufd'\n"
457                        "- OOB_PATH: path of OOB device like '/mnt'\n"
458                        "- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
459                        "'cred'\n");
460                 return -1;
461         }
462
463         res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
464                           argv[0], argv[1], argv[2]);
465         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
466                 printf("Too long WPS_OOB command.\n");
467                 return -1;
468         }
469         return wpa_ctrl_command(ctrl, cmd);
470 }
471
472
473 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
474 {
475         char cmd[256];
476         int res;
477
478         if (argc != 2) {
479                 printf("Invalid WPS_REG command: need two arguments:\n"
480                        "- BSSID: use 'any' to select any\n"
481                        "- AP PIN\n");
482                 return -1;
483         }
484
485         res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
486         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
487                 printf("Too long WPS_REG command.\n");
488                 return -1;
489         }
490         return wpa_ctrl_command(ctrl, cmd);
491 }
492
493
494 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
495 {
496         char cmd[256];
497         int res;
498
499         if (argc != 1) {
500                 printf("Invalid IBSS_RSN command: needs one argument "
501                        "(Peer STA MAC address)\n");
502                 return -1;
503         }
504
505         res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
506         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
507                 printf("Too long IBSS_RSN command.\n");
508                 return -1;
509         }
510         return wpa_ctrl_command(ctrl, cmd);
511 }
512
513
514 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
515 {
516         char cmd[256];
517         int res;
518
519         if (argc != 1) {
520                 printf("Invalid LEVEL command: needs one argument (debug "
521                        "level)\n");
522                 return -1;
523         }
524         res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
525         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
526                 printf("Too long LEVEL command.\n");
527                 return -1;
528         }
529         return wpa_ctrl_command(ctrl, cmd);
530 }
531
532
533 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
534 {
535         char cmd[256], *pos, *end;
536         int i, ret;
537
538         if (argc < 2) {
539                 printf("Invalid IDENTITY command: needs two arguments "
540                        "(network id and identity)\n");
541                 return -1;
542         }
543
544         end = cmd + sizeof(cmd);
545         pos = cmd;
546         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
547                           argv[0], argv[1]);
548         if (ret < 0 || ret >= end - pos) {
549                 printf("Too long IDENTITY command.\n");
550                 return -1;
551         }
552         pos += ret;
553         for (i = 2; i < argc; i++) {
554                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
555                 if (ret < 0 || ret >= end - pos) {
556                         printf("Too long IDENTITY command.\n");
557                         return -1;
558                 }
559                 pos += ret;
560         }
561
562         return wpa_ctrl_command(ctrl, cmd);
563 }
564
565
566 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
567 {
568         char cmd[256], *pos, *end;
569         int i, ret;
570
571         if (argc < 2) {
572                 printf("Invalid PASSWORD command: needs two arguments "
573                        "(network id and password)\n");
574                 return -1;
575         }
576
577         end = cmd + sizeof(cmd);
578         pos = cmd;
579         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
580                           argv[0], argv[1]);
581         if (ret < 0 || ret >= end - pos) {
582                 printf("Too long PASSWORD command.\n");
583                 return -1;
584         }
585         pos += ret;
586         for (i = 2; i < argc; i++) {
587                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
588                 if (ret < 0 || ret >= end - pos) {
589                         printf("Too long PASSWORD command.\n");
590                         return -1;
591                 }
592                 pos += ret;
593         }
594
595         return wpa_ctrl_command(ctrl, cmd);
596 }
597
598
599 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
600                                     char *argv[])
601 {
602         char cmd[256], *pos, *end;
603         int i, ret;
604
605         if (argc < 2) {
606                 printf("Invalid NEW_PASSWORD command: needs two arguments "
607                        "(network id and password)\n");
608                 return -1;
609         }
610
611         end = cmd + sizeof(cmd);
612         pos = cmd;
613         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
614                           argv[0], argv[1]);
615         if (ret < 0 || ret >= end - pos) {
616                 printf("Too long NEW_PASSWORD command.\n");
617                 return -1;
618         }
619         pos += ret;
620         for (i = 2; i < argc; i++) {
621                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
622                 if (ret < 0 || ret >= end - pos) {
623                         printf("Too long NEW_PASSWORD command.\n");
624                         return -1;
625                 }
626                 pos += ret;
627         }
628
629         return wpa_ctrl_command(ctrl, cmd);
630 }
631
632
633 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
634 {
635         char cmd[256], *pos, *end;
636         int i, ret;
637
638         if (argc < 2) {
639                 printf("Invalid PIN command: needs two arguments "
640                        "(network id and pin)\n");
641                 return -1;
642         }
643
644         end = cmd + sizeof(cmd);
645         pos = cmd;
646         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
647                           argv[0], argv[1]);
648         if (ret < 0 || ret >= end - pos) {
649                 printf("Too long PIN command.\n");
650                 return -1;
651         }
652         pos += ret;
653         for (i = 2; i < argc; i++) {
654                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
655                 if (ret < 0 || ret >= end - pos) {
656                         printf("Too long PIN command.\n");
657                         return -1;
658                 }
659                 pos += ret;
660         }
661         return wpa_ctrl_command(ctrl, cmd);
662 }
663
664
665 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
666 {
667         char cmd[256], *pos, *end;
668         int i, ret;
669
670         if (argc < 2) {
671                 printf("Invalid OTP command: needs two arguments (network "
672                        "id and password)\n");
673                 return -1;
674         }
675
676         end = cmd + sizeof(cmd);
677         pos = cmd;
678         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
679                           argv[0], argv[1]);
680         if (ret < 0 || ret >= end - pos) {
681                 printf("Too long OTP command.\n");
682                 return -1;
683         }
684         pos += ret;
685         for (i = 2; i < argc; i++) {
686                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
687                 if (ret < 0 || ret >= end - pos) {
688                         printf("Too long OTP command.\n");
689                         return -1;
690                 }
691                 pos += ret;
692         }
693
694         return wpa_ctrl_command(ctrl, cmd);
695 }
696
697
698 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
699                                   char *argv[])
700 {
701         char cmd[256], *pos, *end;
702         int i, ret;
703
704         if (argc < 2) {
705                 printf("Invalid PASSPHRASE command: needs two arguments "
706                        "(network id and passphrase)\n");
707                 return -1;
708         }
709
710         end = cmd + sizeof(cmd);
711         pos = cmd;
712         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
713                           argv[0], argv[1]);
714         if (ret < 0 || ret >= end - pos) {
715                 printf("Too long PASSPHRASE command.\n");
716                 return -1;
717         }
718         pos += ret;
719         for (i = 2; i < argc; i++) {
720                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
721                 if (ret < 0 || ret >= end - pos) {
722                         printf("Too long PASSPHRASE command.\n");
723                         return -1;
724                 }
725                 pos += ret;
726         }
727
728         return wpa_ctrl_command(ctrl, cmd);
729 }
730
731
732 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
733 {
734         char cmd[256], *pos, *end;
735         int i, ret;
736
737         if (argc < 2) {
738                 printf("Invalid BSSID command: needs two arguments (network "
739                        "id and BSSID)\n");
740                 return -1;
741         }
742
743         end = cmd + sizeof(cmd);
744         pos = cmd;
745         ret = os_snprintf(pos, end - pos, "BSSID");
746         if (ret < 0 || ret >= end - pos) {
747                 printf("Too long BSSID command.\n");
748                 return -1;
749         }
750         pos += ret;
751         for (i = 0; i < argc; i++) {
752                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
753                 if (ret < 0 || ret >= end - pos) {
754                         printf("Too long BSSID command.\n");
755                         return -1;
756                 }
757                 pos += ret;
758         }
759
760         return wpa_ctrl_command(ctrl, cmd);
761 }
762
763
764 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
765                                      char *argv[])
766 {
767         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
768 }
769
770
771 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
772                                       char *argv[])
773 {
774         char cmd[32];
775         int res;
776
777         if (argc < 1) {
778                 printf("Invalid SELECT_NETWORK command: needs one argument "
779                        "(network id)\n");
780                 return -1;
781         }
782
783         res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
784         if (res < 0 || (size_t) res >= sizeof(cmd))
785                 return -1;
786         cmd[sizeof(cmd) - 1] = '\0';
787
788         return wpa_ctrl_command(ctrl, cmd);
789 }
790
791
792 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
793                                       char *argv[])
794 {
795         char cmd[32];
796         int res;
797
798         if (argc < 1) {
799                 printf("Invalid ENABLE_NETWORK command: needs one argument "
800                        "(network id)\n");
801                 return -1;
802         }
803
804         res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
805         if (res < 0 || (size_t) res >= sizeof(cmd))
806                 return -1;
807         cmd[sizeof(cmd) - 1] = '\0';
808
809         return wpa_ctrl_command(ctrl, cmd);
810 }
811
812
813 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
814                                        char *argv[])
815 {
816         char cmd[32];
817         int res;
818
819         if (argc < 1) {
820                 printf("Invalid DISABLE_NETWORK command: needs one argument "
821                        "(network id)\n");
822                 return -1;
823         }
824
825         res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
826         if (res < 0 || (size_t) res >= sizeof(cmd))
827                 return -1;
828         cmd[sizeof(cmd) - 1] = '\0';
829
830         return wpa_ctrl_command(ctrl, cmd);
831 }
832
833
834 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
835                                    char *argv[])
836 {
837         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
838 }
839
840
841 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
842                                       char *argv[])
843 {
844         char cmd[32];
845         int res;
846
847         if (argc < 1) {
848                 printf("Invalid REMOVE_NETWORK command: needs one argument "
849                        "(network id)\n");
850                 return -1;
851         }
852
853         res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
854         if (res < 0 || (size_t) res >= sizeof(cmd))
855                 return -1;
856         cmd[sizeof(cmd) - 1] = '\0';
857
858         return wpa_ctrl_command(ctrl, cmd);
859 }
860
861
862 static void wpa_cli_show_network_variables(void)
863 {
864         printf("set_network variables:\n"
865                "  ssid (network name, SSID)\n"
866                "  psk (WPA passphrase or pre-shared key)\n"
867                "  key_mgmt (key management protocol)\n"
868                "  identity (EAP identity)\n"
869                "  password (EAP password)\n"
870                "  ...\n"
871                "\n"
872                "Note: Values are entered in the same format as the "
873                "configuration file is using,\n"
874                "i.e., strings values need to be inside double quotation "
875                "marks.\n"
876                "For example: set_network 1 ssid \"network name\"\n"
877                "\n"
878                "Please see wpa_supplicant.conf documentation for full list "
879                "of\navailable variables.\n");
880 }
881
882
883 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
884                                    char *argv[])
885 {
886         char cmd[256];
887         int res;
888
889         if (argc == 0) {
890                 wpa_cli_show_network_variables();
891                 return 0;
892         }
893
894         if (argc != 3) {
895                 printf("Invalid SET_NETWORK command: needs three arguments\n"
896                        "(network id, variable name, and value)\n");
897                 return -1;
898         }
899
900         res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
901                           argv[0], argv[1], argv[2]);
902         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
903                 printf("Too long SET_NETWORK command.\n");
904                 return -1;
905         }
906         return wpa_ctrl_command(ctrl, cmd);
907 }
908
909
910 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
911                                    char *argv[])
912 {
913         char cmd[256];
914         int res;
915
916         if (argc == 0) {
917                 wpa_cli_show_network_variables();
918                 return 0;
919         }
920
921         if (argc != 2) {
922                 printf("Invalid GET_NETWORK command: needs two arguments\n"
923                        "(network id and variable name)\n");
924                 return -1;
925         }
926
927         res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
928                           argv[0], argv[1]);
929         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
930                 printf("Too long GET_NETWORK command.\n");
931                 return -1;
932         }
933         return wpa_ctrl_command(ctrl, cmd);
934 }
935
936
937 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
938                                   char *argv[])
939 {
940         return wpa_ctrl_command(ctrl, "DISCONNECT");
941 }
942
943
944 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
945                                   char *argv[])
946 {
947         return wpa_ctrl_command(ctrl, "RECONNECT");
948 }
949
950
951 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
952                                    char *argv[])
953 {
954         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
955 }
956
957
958 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
959 {
960         return wpa_ctrl_command(ctrl, "SCAN");
961 }
962
963
964 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
965                                     char *argv[])
966 {
967         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
968 }
969
970
971 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
972 {
973         char cmd[64];
974         int res;
975
976         if (argc != 1) {
977                 printf("Invalid BSS command: need one argument (index or "
978                        "BSSID)\n");
979                 return -1;
980         }
981
982         res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
983         if (res < 0 || (size_t) res >= sizeof(cmd))
984                 return -1;
985         cmd[sizeof(cmd) - 1] = '\0';
986
987         return wpa_ctrl_command(ctrl, cmd);
988 }
989
990
991 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
992                                       char *argv[])
993 {
994         char cmd[64];
995         int res;
996
997         if (argc < 1 || argc > 2) {
998                 printf("Invalid GET_CAPABILITY command: need either one or "
999                        "two arguments\n");
1000                 return -1;
1001         }
1002
1003         if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1004                 printf("Invalid GET_CAPABILITY command: second argument, "
1005                        "if any, must be 'strict'\n");
1006                 return -1;
1007         }
1008
1009         res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1010                           (argc == 2) ? " strict" : "");
1011         if (res < 0 || (size_t) res >= sizeof(cmd))
1012                 return -1;
1013         cmd[sizeof(cmd) - 1] = '\0';
1014
1015         return wpa_ctrl_command(ctrl, cmd);
1016 }
1017
1018
1019 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1020 {
1021         printf("Available interfaces:\n");
1022         return wpa_ctrl_command(ctrl, "INTERFACES");
1023 }
1024
1025
1026 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1027 {
1028         if (argc < 1) {
1029                 wpa_cli_list_interfaces(ctrl);
1030                 return 0;
1031         }
1032
1033         wpa_cli_close_connection();
1034         os_free(ctrl_ifname);
1035         ctrl_ifname = os_strdup(argv[0]);
1036
1037         if (wpa_cli_open_connection(ctrl_ifname)) {
1038                 printf("Connected to interface '%s.\n", ctrl_ifname);
1039                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1040                         wpa_cli_attached = 1;
1041                 } else {
1042                         printf("Warning: Failed to attach to "
1043                                "wpa_supplicant.\n");
1044                 }
1045         } else {
1046                 printf("Could not connect to interface '%s' - re-trying\n",
1047                        ctrl_ifname);
1048         }
1049         return 0;
1050 }
1051
1052
1053 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1054                                    char *argv[])
1055 {
1056         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1057 }
1058
1059
1060 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1061                                  char *argv[])
1062 {
1063         return wpa_ctrl_command(ctrl, "TERMINATE");
1064 }
1065
1066
1067 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1068                                      char *argv[])
1069 {
1070         char cmd[256];
1071         int res;
1072
1073         if (argc < 1) {
1074                 printf("Invalid INTERFACE_ADD command: needs at least one "
1075                        "argument (interface name)\n"
1076                        "All arguments: ifname confname driver ctrl_interface "
1077                        "driver_param bridge_name\n");
1078                 return -1;
1079         }
1080
1081         /*
1082          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1083          * <driver_param>TAB<bridge_name>
1084          */
1085         res = os_snprintf(cmd, sizeof(cmd),
1086                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1087                           argv[0],
1088                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1089                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1090                           argc > 5 ? argv[5] : "");
1091         if (res < 0 || (size_t) res >= sizeof(cmd))
1092                 return -1;
1093         cmd[sizeof(cmd) - 1] = '\0';
1094         return wpa_ctrl_command(ctrl, cmd);
1095 }
1096
1097
1098 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1099                                         char *argv[])
1100 {
1101         char cmd[128];
1102         int res;
1103
1104         if (argc != 1) {
1105                 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1106                        "(interface name)\n");
1107                 return -1;
1108         }
1109
1110         res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1111         if (res < 0 || (size_t) res >= sizeof(cmd))
1112                 return -1;
1113         cmd[sizeof(cmd) - 1] = '\0';
1114         return wpa_ctrl_command(ctrl, cmd);
1115 }
1116
1117
1118 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1119                                       char *argv[])
1120 {
1121         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1122 }
1123
1124
1125 enum wpa_cli_cmd_flags {
1126         cli_cmd_flag_none               = 0x00,
1127         cli_cmd_flag_sensitive          = 0x01
1128 };
1129
1130 struct wpa_cli_cmd {
1131         const char *cmd;
1132         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1133         enum wpa_cli_cmd_flags flags;
1134         const char *usage;
1135 };
1136
1137 static struct wpa_cli_cmd wpa_cli_commands[] = {
1138         { "status", wpa_cli_cmd_status,
1139           cli_cmd_flag_none,
1140           "[verbose] = get current WPA/EAPOL/EAP status" },
1141         { "ping", wpa_cli_cmd_ping,
1142           cli_cmd_flag_none,
1143           "= pings wpa_supplicant" },
1144         { "mib", wpa_cli_cmd_mib,
1145           cli_cmd_flag_none,
1146           "= get MIB variables (dot1x, dot11)" },
1147         { "help", wpa_cli_cmd_help,
1148           cli_cmd_flag_none,
1149           "= show this usage help" },
1150         { "interface", wpa_cli_cmd_interface,
1151           cli_cmd_flag_none,
1152           "[ifname] = show interfaces/select interface" },
1153         { "level", wpa_cli_cmd_level,
1154           cli_cmd_flag_none,
1155           "<debug level> = change debug level" },
1156         { "license", wpa_cli_cmd_license,
1157           cli_cmd_flag_none,
1158           "= show full wpa_cli license" },
1159         { "quit", wpa_cli_cmd_quit,
1160           cli_cmd_flag_none,
1161           "= exit wpa_cli" },
1162         { "set", wpa_cli_cmd_set,
1163           cli_cmd_flag_none,
1164           "= set variables (shows list of variables when run without "
1165           "arguments)" },
1166         { "logon", wpa_cli_cmd_logon,
1167           cli_cmd_flag_none,
1168           "= IEEE 802.1X EAPOL state machine logon" },
1169         { "logoff", wpa_cli_cmd_logoff,
1170           cli_cmd_flag_none,
1171           "= IEEE 802.1X EAPOL state machine logoff" },
1172         { "pmksa", wpa_cli_cmd_pmksa,
1173           cli_cmd_flag_none,
1174           "= show PMKSA cache" },
1175         { "reassociate", wpa_cli_cmd_reassociate,
1176           cli_cmd_flag_none,
1177           "= force reassociation" },
1178         { "preauthenticate", wpa_cli_cmd_preauthenticate,
1179           cli_cmd_flag_none,
1180           "<BSSID> = force preauthentication" },
1181         { "identity", wpa_cli_cmd_identity,
1182           cli_cmd_flag_none,
1183           "<network id> <identity> = configure identity for an SSID" },
1184         { "password", wpa_cli_cmd_password,
1185           cli_cmd_flag_sensitive,
1186           "<network id> <password> = configure password for an SSID" },
1187         { "new_password", wpa_cli_cmd_new_password,
1188           cli_cmd_flag_sensitive,
1189           "<network id> <password> = change password for an SSID" },
1190         { "pin", wpa_cli_cmd_pin,
1191           cli_cmd_flag_sensitive,
1192           "<network id> <pin> = configure pin for an SSID" },
1193         { "otp", wpa_cli_cmd_otp,
1194           cli_cmd_flag_sensitive,
1195           "<network id> <password> = configure one-time-password for an SSID"
1196         },
1197         { "passphrase", wpa_cli_cmd_passphrase,
1198           cli_cmd_flag_sensitive,
1199           "<network id> <passphrase> = configure private key passphrase\n"
1200           "  for an SSID" },
1201         { "bssid", wpa_cli_cmd_bssid,
1202           cli_cmd_flag_none,
1203           "<network id> <BSSID> = set preferred BSSID for an SSID" },
1204         { "list_networks", wpa_cli_cmd_list_networks,
1205           cli_cmd_flag_none,
1206           "= list configured networks" },
1207         { "select_network", wpa_cli_cmd_select_network,
1208           cli_cmd_flag_none,
1209           "<network id> = select a network (disable others)" },
1210         { "enable_network", wpa_cli_cmd_enable_network,
1211           cli_cmd_flag_none,
1212           "<network id> = enable a network" },
1213         { "disable_network", wpa_cli_cmd_disable_network,
1214           cli_cmd_flag_none,
1215           "<network id> = disable a network" },
1216         { "add_network", wpa_cli_cmd_add_network,
1217           cli_cmd_flag_none,
1218           "= add a network" },
1219         { "remove_network", wpa_cli_cmd_remove_network,
1220           cli_cmd_flag_none,
1221           "<network id> = remove a network" },
1222         { "set_network", wpa_cli_cmd_set_network,
1223           cli_cmd_flag_sensitive,
1224           "<network id> <variable> <value> = set network variables (shows\n"
1225           "  list of variables when run without arguments)" },
1226         { "get_network", wpa_cli_cmd_get_network,
1227           cli_cmd_flag_none,
1228           "<network id> <variable> = get network variables" },
1229         { "save_config", wpa_cli_cmd_save_config,
1230           cli_cmd_flag_none,
1231           "= save the current configuration" },
1232         { "disconnect", wpa_cli_cmd_disconnect,
1233           cli_cmd_flag_none,
1234           "= disconnect and wait for reassociate/reconnect command before\n"
1235           "  connecting" },
1236         { "reconnect", wpa_cli_cmd_reconnect,
1237           cli_cmd_flag_none,
1238           "= like reassociate, but only takes effect if already disconnected"
1239         },
1240         { "scan", wpa_cli_cmd_scan,
1241           cli_cmd_flag_none,
1242           "= request new BSS scan" },
1243         { "scan_results", wpa_cli_cmd_scan_results,
1244           cli_cmd_flag_none,
1245           "= get latest scan results" },
1246         { "bss", wpa_cli_cmd_bss,
1247           cli_cmd_flag_none,
1248           "<<idx> | <bssid>> = get detailed scan result info" },
1249         { "get_capability", wpa_cli_cmd_get_capability,
1250           cli_cmd_flag_none,
1251           "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1252         { "reconfigure", wpa_cli_cmd_reconfigure,
1253           cli_cmd_flag_none,
1254           "= force wpa_supplicant to re-read its configuration file" },
1255         { "terminate", wpa_cli_cmd_terminate,
1256           cli_cmd_flag_none,
1257           "= terminate wpa_supplicant" },
1258         { "interface_add", wpa_cli_cmd_interface_add,
1259           cli_cmd_flag_none,
1260           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1261           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
1262           "  are optional" },
1263         { "interface_remove", wpa_cli_cmd_interface_remove,
1264           cli_cmd_flag_none,
1265           "<ifname> = removes the interface" },
1266         { "interface_list", wpa_cli_cmd_interface_list,
1267           cli_cmd_flag_none,
1268           "= list available interfaces" },
1269         { "ap_scan", wpa_cli_cmd_ap_scan,
1270           cli_cmd_flag_none,
1271           "<value> = set ap_scan parameter" },
1272         { "stkstart", wpa_cli_cmd_stkstart,
1273           cli_cmd_flag_none,
1274           "<addr> = request STK negotiation with <addr>" },
1275         { "ft_ds", wpa_cli_cmd_ft_ds,
1276           cli_cmd_flag_none,
1277           "<addr> = request over-the-DS FT with <addr>" },
1278         { "wps_pbc", wpa_cli_cmd_wps_pbc,
1279           cli_cmd_flag_none,
1280           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1281         { "wps_pin", wpa_cli_cmd_wps_pin,
1282           cli_cmd_flag_sensitive,
1283           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1284           "hardcoded)" },
1285         { "wps_oob", wpa_cli_cmd_wps_oob,
1286           cli_cmd_flag_sensitive,
1287           "<OOB_DEV_TYPE> <OOB_PATH> <OOB_METHOD> = start WPS OOB" },
1288         { "wps_reg", wpa_cli_cmd_wps_reg,
1289           cli_cmd_flag_sensitive,
1290           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1291         { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1292           cli_cmd_flag_none,
1293           "<addr> = request RSN authentication with <addr> in IBSS" },
1294         { NULL, NULL, cli_cmd_flag_none, NULL }
1295 };
1296
1297
1298 /*
1299  * Prints command usage, lines are padded with the specified string.
1300  */
1301 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1302 {
1303         char c;
1304         size_t n;
1305
1306         printf("%s%s ", pad, cmd->cmd);
1307         for (n = 0; (c = cmd->usage[n]); n++) {
1308                 printf("%c", c);
1309                 if (c == '\n')
1310                         printf("%s", pad);
1311         }
1312         printf("\n");
1313 }
1314
1315
1316 static void print_help(void)
1317 {
1318         int n;
1319         printf("commands:\n");
1320         for (n = 0; wpa_cli_commands[n].cmd; n++)
1321                 print_cmd_help(&wpa_cli_commands[n], "  ");
1322 }
1323
1324
1325 #ifdef CONFIG_READLINE
1326 static int cmd_has_sensitive_data(const char *cmd)
1327 {
1328         const char *c, *delim;
1329         int n;
1330         size_t len;
1331
1332         delim = os_strchr(cmd, ' ');
1333         if (delim)
1334                 len = delim - cmd;
1335         else
1336                 len = os_strlen(cmd);
1337
1338         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1339                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1340                         return (wpa_cli_commands[n].flags &
1341                                 cli_cmd_flag_sensitive);
1342         }
1343         return 0;
1344 }
1345 #endif /* CONFIG_READLINE */
1346
1347
1348 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1349 {
1350         struct wpa_cli_cmd *cmd, *match = NULL;
1351         int count;
1352         int ret = 0;
1353
1354         count = 0;
1355         cmd = wpa_cli_commands;
1356         while (cmd->cmd) {
1357                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1358                 {
1359                         match = cmd;
1360                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1361                                 /* we have an exact match */
1362                                 count = 1;
1363                                 break;
1364                         }
1365                         count++;
1366                 }
1367                 cmd++;
1368         }
1369
1370         if (count > 1) {
1371                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1372                 cmd = wpa_cli_commands;
1373                 while (cmd->cmd) {
1374                         if (os_strncasecmp(cmd->cmd, argv[0],
1375                                            os_strlen(argv[0])) == 0) {
1376                                 printf(" %s", cmd->cmd);
1377                         }
1378                         cmd++;
1379                 }
1380                 printf("\n");
1381                 ret = 1;
1382         } else if (count == 0) {
1383                 printf("Unknown command '%s'\n", argv[0]);
1384                 ret = 1;
1385         } else {
1386                 ret = match->handler(ctrl, argc - 1, &argv[1]);
1387         }
1388
1389         return ret;
1390 }
1391
1392
1393 static int str_match(const char *a, const char *b)
1394 {
1395         return os_strncmp(a, b, os_strlen(b)) == 0;
1396 }
1397
1398
1399 static int wpa_cli_exec(const char *program, const char *arg1,
1400                         const char *arg2)
1401 {
1402         char *cmd;
1403         size_t len;
1404         int res;
1405         int ret = 0;
1406
1407         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1408         cmd = os_malloc(len);
1409         if (cmd == NULL)
1410                 return -1;
1411         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1412         if (res < 0 || (size_t) res >= len) {
1413                 os_free(cmd);
1414                 return -1;
1415         }
1416         cmd[len - 1] = '\0';
1417 #ifndef _WIN32_WCE
1418         if (system(cmd) < 0)
1419                 ret = -1;
1420 #endif /* _WIN32_WCE */
1421         os_free(cmd);
1422
1423         return ret;
1424 }
1425
1426
1427 static void wpa_cli_action_process(const char *msg)
1428 {
1429         const char *pos;
1430         char *copy = NULL, *id, *pos2;
1431
1432         pos = msg;
1433         if (*pos == '<') {
1434                 /* skip priority */
1435                 pos = os_strchr(pos, '>');
1436                 if (pos)
1437                         pos++;
1438                 else
1439                         pos = msg;
1440         }
1441
1442         if (str_match(pos, WPA_EVENT_CONNECTED)) {
1443                 int new_id = -1;
1444                 os_unsetenv("WPA_ID");
1445                 os_unsetenv("WPA_ID_STR");
1446                 os_unsetenv("WPA_CTRL_DIR");
1447
1448                 pos = os_strstr(pos, "[id=");
1449                 if (pos)
1450                         copy = os_strdup(pos + 4);
1451
1452                 if (copy) {
1453                         pos2 = id = copy;
1454                         while (*pos2 && *pos2 != ' ')
1455                                 pos2++;
1456                         *pos2++ = '\0';
1457                         new_id = atoi(id);
1458                         os_setenv("WPA_ID", id, 1);
1459                         while (*pos2 && *pos2 != '=')
1460                                 pos2++;
1461                         if (*pos2 == '=')
1462                                 pos2++;
1463                         id = pos2;
1464                         while (*pos2 && *pos2 != ']')
1465                                 pos2++;
1466                         *pos2 = '\0';
1467                         os_setenv("WPA_ID_STR", id, 1);
1468                         os_free(copy);
1469                 }
1470
1471                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1472
1473                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1474                         wpa_cli_connected = 1;
1475                         wpa_cli_last_id = new_id;
1476                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1477                 }
1478         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1479                 if (wpa_cli_connected) {
1480                         wpa_cli_connected = 0;
1481                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1482                 }
1483         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1484                 printf("wpa_supplicant is terminating - stop monitoring\n");
1485                 wpa_cli_quit = 1;
1486         }
1487 }
1488
1489
1490 #ifndef CONFIG_ANSI_C_EXTRA
1491 static void wpa_cli_action_cb(char *msg, size_t len)
1492 {
1493         wpa_cli_action_process(msg);
1494 }
1495 #endif /* CONFIG_ANSI_C_EXTRA */
1496
1497
1498 static void wpa_cli_reconnect(void)
1499 {
1500         wpa_cli_close_connection();
1501         ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1502         if (ctrl_conn) {
1503                 printf("Connection to wpa_supplicant re-established\n");
1504                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1505                         wpa_cli_attached = 1;
1506                 } else {
1507                         printf("Warning: Failed to attach to "
1508                                "wpa_supplicant.\n");
1509                 }
1510         }
1511 }
1512
1513
1514 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1515                                  int action_monitor)
1516 {
1517         int first = 1;
1518         if (ctrl_conn == NULL) {
1519                 wpa_cli_reconnect();
1520                 return;
1521         }
1522         while (wpa_ctrl_pending(ctrl) > 0) {
1523                 char buf[256];
1524                 size_t len = sizeof(buf) - 1;
1525                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1526                         buf[len] = '\0';
1527                         if (action_monitor)
1528                                 wpa_cli_action_process(buf);
1529                         else {
1530                                 if (in_read && first)
1531                                         printf("\n");
1532                                 first = 0;
1533                                 printf("%s\n", buf);
1534                         }
1535                 } else {
1536                         printf("Could not read pending message.\n");
1537                         break;
1538                 }
1539         }
1540
1541         if (wpa_ctrl_pending(ctrl) < 0) {
1542                 printf("Connection to wpa_supplicant lost - trying to "
1543                        "reconnect\n");
1544                 wpa_cli_reconnect();
1545         }
1546 }
1547
1548
1549 #ifdef CONFIG_READLINE
1550 static char * wpa_cli_cmd_gen(const char *text, int state)
1551 {
1552         static int i, len;
1553         const char *cmd;
1554
1555         if (state == 0) {
1556                 i = 0;
1557                 len = os_strlen(text);
1558         }
1559
1560         while ((cmd = wpa_cli_commands[i].cmd)) {
1561                 i++;
1562                 if (os_strncasecmp(cmd, text, len) == 0)
1563                         return os_strdup(cmd);
1564         }
1565
1566         return NULL;
1567 }
1568
1569
1570 static char * wpa_cli_dummy_gen(const char *text, int state)
1571 {
1572         return NULL;
1573 }
1574
1575
1576 static char ** wpa_cli_completion(const char *text, int start, int end)
1577 {
1578         return rl_completion_matches(text, start == 0 ?
1579                                      wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1580 }
1581 #endif /* CONFIG_READLINE */
1582
1583
1584 static void wpa_cli_interactive(void)
1585 {
1586 #define max_args 10
1587         char cmdbuf[256], *cmd, *argv[max_args], *pos;
1588         int argc;
1589 #ifdef CONFIG_READLINE
1590         char *home, *hfile = NULL;
1591 #endif /* CONFIG_READLINE */
1592
1593         printf("\nInteractive mode\n\n");
1594
1595 #ifdef CONFIG_READLINE
1596         rl_attempted_completion_function = wpa_cli_completion;
1597         home = getenv("HOME");
1598         if (home) {
1599                 const char *fname = ".wpa_cli_history";
1600                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1601                 hfile = os_malloc(hfile_len);
1602                 if (hfile) {
1603                         int res;
1604                         res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1605                                           fname);
1606                         if (res >= 0 && res < hfile_len) {
1607                                 hfile[hfile_len - 1] = '\0';
1608                                 read_history(hfile);
1609                                 stifle_history(100);
1610                         }
1611                 }
1612         }
1613 #endif /* CONFIG_READLINE */
1614
1615         do {
1616                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1617 #ifndef CONFIG_NATIVE_WINDOWS
1618                 alarm(ping_interval);
1619 #endif /* CONFIG_NATIVE_WINDOWS */
1620 #ifdef CONFIG_READLINE
1621                 cmd = readline("> ");
1622                 if (cmd && *cmd) {
1623                         HIST_ENTRY *h;
1624                         while (next_history())
1625                                 ;
1626                         h = previous_history();
1627                         if (h == NULL || os_strcmp(cmd, h->line) != 0)
1628                                 add_history(cmd);
1629                         next_history();
1630                 }
1631 #else /* CONFIG_READLINE */
1632                 printf("> ");
1633                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1634 #endif /* CONFIG_READLINE */
1635 #ifndef CONFIG_NATIVE_WINDOWS
1636                 alarm(0);
1637 #endif /* CONFIG_NATIVE_WINDOWS */
1638                 if (cmd == NULL)
1639                         break;
1640                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1641                 pos = cmd;
1642                 while (*pos != '\0') {
1643                         if (*pos == '\n') {
1644                                 *pos = '\0';
1645                                 break;
1646                         }
1647                         pos++;
1648                 }
1649                 argc = 0;
1650                 pos = cmd;
1651                 for (;;) {
1652                         while (*pos == ' ')
1653                                 pos++;
1654                         if (*pos == '\0')
1655                                 break;
1656                         argv[argc] = pos;
1657                         argc++;
1658                         if (argc == max_args)
1659                                 break;
1660                         if (*pos == '"') {
1661                                 char *pos2 = os_strrchr(pos, '"');
1662                                 if (pos2)
1663                                         pos = pos2 + 1;
1664                         }
1665                         while (*pos != '\0' && *pos != ' ')
1666                                 pos++;
1667                         if (*pos == ' ')
1668                                 *pos++ = '\0';
1669                 }
1670                 if (argc)
1671                         wpa_request(ctrl_conn, argc, argv);
1672
1673                 if (cmd != cmdbuf)
1674                         os_free(cmd);
1675         } while (!wpa_cli_quit);
1676
1677 #ifdef CONFIG_READLINE
1678         if (hfile) {
1679                 /* Save command history, excluding lines that may contain
1680                  * passwords. */
1681                 HIST_ENTRY *h;
1682                 history_set_pos(0);
1683                 while ((h = current_history())) {
1684                         char *p = h->line;
1685                         while (*p == ' ' || *p == '\t')
1686                                 p++;
1687                         if (cmd_has_sensitive_data(p)) {
1688                                 h = remove_history(where_history());
1689                                 if (h) {
1690                                         os_free(h->line);
1691                                         os_free(h->data);
1692                                         os_free(h);
1693                                 } else
1694                                         next_history();
1695                         } else
1696                                 next_history();
1697                 }
1698                 write_history(hfile);
1699                 os_free(hfile);
1700         }
1701 #endif /* CONFIG_READLINE */
1702 }
1703
1704
1705 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1706 {
1707 #ifdef CONFIG_ANSI_C_EXTRA
1708         /* TODO: ANSI C version(?) */
1709         printf("Action processing not supported in ANSI C build.\n");
1710 #else /* CONFIG_ANSI_C_EXTRA */
1711         fd_set rfds;
1712         int fd, res;
1713         struct timeval tv;
1714         char buf[256]; /* note: large enough to fit in unsolicited messages */
1715         size_t len;
1716
1717         fd = wpa_ctrl_get_fd(ctrl);
1718
1719         while (!wpa_cli_quit) {
1720                 FD_ZERO(&rfds);
1721                 FD_SET(fd, &rfds);
1722                 tv.tv_sec = ping_interval;
1723                 tv.tv_usec = 0;
1724                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1725                 if (res < 0 && errno != EINTR) {
1726                         perror("select");
1727                         break;
1728                 }
1729
1730                 if (FD_ISSET(fd, &rfds))
1731                         wpa_cli_recv_pending(ctrl, 0, 1);
1732                 else {
1733                         /* verify that connection is still working */
1734                         len = sizeof(buf) - 1;
1735                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1736                                              wpa_cli_action_cb) < 0 ||
1737                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1738                                 printf("wpa_supplicant did not reply to PING "
1739                                        "command - exiting\n");
1740                                 break;
1741                         }
1742                 }
1743         }
1744 #endif /* CONFIG_ANSI_C_EXTRA */
1745 }
1746
1747
1748 static void wpa_cli_cleanup(void)
1749 {
1750         wpa_cli_close_connection();
1751         if (pid_file)
1752                 os_daemonize_terminate(pid_file);
1753
1754         os_program_deinit();
1755 }
1756
1757 static void wpa_cli_terminate(int sig)
1758 {
1759         wpa_cli_cleanup();
1760         exit(0);
1761 }
1762
1763
1764 #ifndef CONFIG_NATIVE_WINDOWS
1765 static void wpa_cli_alarm(int sig)
1766 {
1767         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1768                 printf("Connection to wpa_supplicant lost - trying to "
1769                        "reconnect\n");
1770                 wpa_cli_close_connection();
1771         }
1772         if (!ctrl_conn)
1773                 wpa_cli_reconnect();
1774         if (ctrl_conn)
1775                 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1776         alarm(ping_interval);
1777 }
1778 #endif /* CONFIG_NATIVE_WINDOWS */
1779
1780
1781 static char * wpa_cli_get_default_ifname(void)
1782 {
1783         char *ifname = NULL;
1784
1785 #ifdef CONFIG_CTRL_IFACE_UNIX
1786         struct dirent *dent;
1787         DIR *dir = opendir(ctrl_iface_dir);
1788         if (!dir)
1789                 return NULL;
1790         while ((dent = readdir(dir))) {
1791 #ifdef _DIRENT_HAVE_D_TYPE
1792                 /*
1793                  * Skip the file if it is not a socket. Also accept
1794                  * DT_UNKNOWN (0) in case the C library or underlying
1795                  * file system does not support d_type.
1796                  */
1797                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1798                         continue;
1799 #endif /* _DIRENT_HAVE_D_TYPE */
1800                 if (os_strcmp(dent->d_name, ".") == 0 ||
1801                     os_strcmp(dent->d_name, "..") == 0)
1802                         continue;
1803                 printf("Selected interface '%s'\n", dent->d_name);
1804                 ifname = os_strdup(dent->d_name);
1805                 break;
1806         }
1807         closedir(dir);
1808 #endif /* CONFIG_CTRL_IFACE_UNIX */
1809
1810 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1811         char buf[2048], *pos;
1812         size_t len;
1813         struct wpa_ctrl *ctrl;
1814         int ret;
1815
1816         ctrl = wpa_ctrl_open(NULL);
1817         if (ctrl == NULL)
1818                 return NULL;
1819
1820         len = sizeof(buf) - 1;
1821         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1822         if (ret >= 0) {
1823                 buf[len] = '\0';
1824                 pos = os_strchr(buf, '\n');
1825                 if (pos)
1826                         *pos = '\0';
1827                 ifname = os_strdup(buf);
1828         }
1829         wpa_ctrl_close(ctrl);
1830 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1831
1832         return ifname;
1833 }
1834
1835
1836 int main(int argc, char *argv[])
1837 {
1838         int interactive;
1839         int warning_displayed = 0;
1840         int c;
1841         int daemonize = 0;
1842         int ret = 0;
1843         const char *global = NULL;
1844
1845         if (os_program_init())
1846                 return -1;
1847
1848         for (;;) {
1849                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
1850                 if (c < 0)
1851                         break;
1852                 switch (c) {
1853                 case 'a':
1854                         action_file = optarg;
1855                         break;
1856                 case 'B':
1857                         daemonize = 1;
1858                         break;
1859                 case 'g':
1860                         global = optarg;
1861                         break;
1862                 case 'G':
1863                         ping_interval = atoi(optarg);
1864                         break;
1865                 case 'h':
1866                         usage();
1867                         return 0;
1868                 case 'v':
1869                         printf("%s\n", wpa_cli_version);
1870                         return 0;
1871                 case 'i':
1872                         os_free(ctrl_ifname);
1873                         ctrl_ifname = os_strdup(optarg);
1874                         break;
1875                 case 'p':
1876                         ctrl_iface_dir = optarg;
1877                         break;
1878                 case 'P':
1879                         pid_file = optarg;
1880                         break;
1881                 default:
1882                         usage();
1883                         return -1;
1884                 }
1885         }
1886
1887         interactive = (argc == optind) && (action_file == NULL);
1888
1889         if (interactive)
1890                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1891
1892         if (global) {
1893 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1894                 ctrl_conn = wpa_ctrl_open(NULL);
1895 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1896                 ctrl_conn = wpa_ctrl_open(global);
1897 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1898                 if (ctrl_conn == NULL) {
1899                         perror("Failed to connect to wpa_supplicant - "
1900                                "wpa_ctrl_open");
1901                         return -1;
1902                 }
1903         }
1904
1905         for (; !global;) {
1906                 if (ctrl_ifname == NULL)
1907                         ctrl_ifname = wpa_cli_get_default_ifname();
1908                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1909                 if (ctrl_conn) {
1910                         if (warning_displayed)
1911                                 printf("Connection established.\n");
1912                         break;
1913                 }
1914
1915                 if (!interactive) {
1916                         perror("Failed to connect to wpa_supplicant - "
1917                                "wpa_ctrl_open");
1918                         return -1;
1919                 }
1920
1921                 if (!warning_displayed) {
1922                         printf("Could not connect to wpa_supplicant - "
1923                                "re-trying\n");
1924                         warning_displayed = 1;
1925                 }
1926                 os_sleep(1, 0);
1927                 continue;
1928         }
1929
1930 #ifndef _WIN32_WCE
1931         signal(SIGINT, wpa_cli_terminate);
1932         signal(SIGTERM, wpa_cli_terminate);
1933 #endif /* _WIN32_WCE */
1934 #ifndef CONFIG_NATIVE_WINDOWS
1935         signal(SIGALRM, wpa_cli_alarm);
1936 #endif /* CONFIG_NATIVE_WINDOWS */
1937
1938         if (interactive || action_file) {
1939                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1940                         wpa_cli_attached = 1;
1941                 } else {
1942                         printf("Warning: Failed to attach to "
1943                                "wpa_supplicant.\n");
1944                         if (!interactive)
1945                                 return -1;
1946                 }
1947         }
1948
1949         if (daemonize && os_daemonize(pid_file))
1950                 return -1;
1951
1952         if (interactive)
1953                 wpa_cli_interactive();
1954         else if (action_file)
1955                 wpa_cli_action(ctrl_conn);
1956         else
1957                 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1958
1959         os_free(ctrl_ifname);
1960         wpa_cli_cleanup();
1961
1962         return ret;
1963 }
1964
1965 #else /* CONFIG_CTRL_IFACE */
1966 int main(int argc, char *argv[])
1967 {
1968         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1969         return -1;
1970 }
1971 #endif /* CONFIG_CTRL_IFACE */