Fixed a copy-paste error in a function documentation
[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_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
450 {
451         char cmd[256];
452         int res;
453
454         if (argc != 2) {
455                 printf("Invalid WPS_REG command: need two arguments:\n"
456                        "- BSSID: use 'any' to select any\n"
457                        "- AP PIN\n");
458                 return -1;
459         }
460
461         res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
462         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
463                 printf("Too long WPS_REG command.\n");
464                 return -1;
465         }
466         return wpa_ctrl_command(ctrl, cmd);
467 }
468
469
470 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
471 {
472         char cmd[256];
473         int res;
474
475         if (argc != 1) {
476                 printf("Invalid IBSS_RSN command: needs one argument "
477                        "(Peer STA MAC address)\n");
478                 return -1;
479         }
480
481         res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
482         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
483                 printf("Too long IBSS_RSN command.\n");
484                 return -1;
485         }
486         return wpa_ctrl_command(ctrl, cmd);
487 }
488
489
490 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
491 {
492         char cmd[256];
493         int res;
494
495         if (argc != 1) {
496                 printf("Invalid LEVEL command: needs one argument (debug "
497                        "level)\n");
498                 return -1;
499         }
500         res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
501         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
502                 printf("Too long LEVEL command.\n");
503                 return -1;
504         }
505         return wpa_ctrl_command(ctrl, cmd);
506 }
507
508
509 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
510 {
511         char cmd[256], *pos, *end;
512         int i, ret;
513
514         if (argc < 2) {
515                 printf("Invalid IDENTITY command: needs two arguments "
516                        "(network id and identity)\n");
517                 return -1;
518         }
519
520         end = cmd + sizeof(cmd);
521         pos = cmd;
522         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
523                           argv[0], argv[1]);
524         if (ret < 0 || ret >= end - pos) {
525                 printf("Too long IDENTITY command.\n");
526                 return -1;
527         }
528         pos += ret;
529         for (i = 2; i < argc; i++) {
530                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
531                 if (ret < 0 || ret >= end - pos) {
532                         printf("Too long IDENTITY command.\n");
533                         return -1;
534                 }
535                 pos += ret;
536         }
537
538         return wpa_ctrl_command(ctrl, cmd);
539 }
540
541
542 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
543 {
544         char cmd[256], *pos, *end;
545         int i, ret;
546
547         if (argc < 2) {
548                 printf("Invalid PASSWORD command: needs two arguments "
549                        "(network id and password)\n");
550                 return -1;
551         }
552
553         end = cmd + sizeof(cmd);
554         pos = cmd;
555         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
556                           argv[0], argv[1]);
557         if (ret < 0 || ret >= end - pos) {
558                 printf("Too long PASSWORD command.\n");
559                 return -1;
560         }
561         pos += ret;
562         for (i = 2; i < argc; i++) {
563                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
564                 if (ret < 0 || ret >= end - pos) {
565                         printf("Too long PASSWORD command.\n");
566                         return -1;
567                 }
568                 pos += ret;
569         }
570
571         return wpa_ctrl_command(ctrl, cmd);
572 }
573
574
575 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
576                                     char *argv[])
577 {
578         char cmd[256], *pos, *end;
579         int i, ret;
580
581         if (argc < 2) {
582                 printf("Invalid NEW_PASSWORD command: needs two arguments "
583                        "(network id and password)\n");
584                 return -1;
585         }
586
587         end = cmd + sizeof(cmd);
588         pos = cmd;
589         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
590                           argv[0], argv[1]);
591         if (ret < 0 || ret >= end - pos) {
592                 printf("Too long NEW_PASSWORD command.\n");
593                 return -1;
594         }
595         pos += ret;
596         for (i = 2; i < argc; i++) {
597                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
598                 if (ret < 0 || ret >= end - pos) {
599                         printf("Too long NEW_PASSWORD command.\n");
600                         return -1;
601                 }
602                 pos += ret;
603         }
604
605         return wpa_ctrl_command(ctrl, cmd);
606 }
607
608
609 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
610 {
611         char cmd[256], *pos, *end;
612         int i, ret;
613
614         if (argc < 2) {
615                 printf("Invalid PIN command: needs two arguments "
616                        "(network id and pin)\n");
617                 return -1;
618         }
619
620         end = cmd + sizeof(cmd);
621         pos = cmd;
622         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
623                           argv[0], argv[1]);
624         if (ret < 0 || ret >= end - pos) {
625                 printf("Too long PIN command.\n");
626                 return -1;
627         }
628         pos += ret;
629         for (i = 2; i < argc; i++) {
630                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
631                 if (ret < 0 || ret >= end - pos) {
632                         printf("Too long PIN command.\n");
633                         return -1;
634                 }
635                 pos += ret;
636         }
637         return wpa_ctrl_command(ctrl, cmd);
638 }
639
640
641 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
642 {
643         char cmd[256], *pos, *end;
644         int i, ret;
645
646         if (argc < 2) {
647                 printf("Invalid OTP command: needs two arguments (network "
648                        "id and password)\n");
649                 return -1;
650         }
651
652         end = cmd + sizeof(cmd);
653         pos = cmd;
654         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
655                           argv[0], argv[1]);
656         if (ret < 0 || ret >= end - pos) {
657                 printf("Too long OTP command.\n");
658                 return -1;
659         }
660         pos += ret;
661         for (i = 2; i < argc; i++) {
662                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
663                 if (ret < 0 || ret >= end - pos) {
664                         printf("Too long OTP command.\n");
665                         return -1;
666                 }
667                 pos += ret;
668         }
669
670         return wpa_ctrl_command(ctrl, cmd);
671 }
672
673
674 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
675                                   char *argv[])
676 {
677         char cmd[256], *pos, *end;
678         int i, ret;
679
680         if (argc < 2) {
681                 printf("Invalid PASSPHRASE command: needs two arguments "
682                        "(network id and passphrase)\n");
683                 return -1;
684         }
685
686         end = cmd + sizeof(cmd);
687         pos = cmd;
688         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
689                           argv[0], argv[1]);
690         if (ret < 0 || ret >= end - pos) {
691                 printf("Too long PASSPHRASE command.\n");
692                 return -1;
693         }
694         pos += ret;
695         for (i = 2; i < argc; i++) {
696                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
697                 if (ret < 0 || ret >= end - pos) {
698                         printf("Too long PASSPHRASE command.\n");
699                         return -1;
700                 }
701                 pos += ret;
702         }
703
704         return wpa_ctrl_command(ctrl, cmd);
705 }
706
707
708 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
709 {
710         char cmd[256], *pos, *end;
711         int i, ret;
712
713         if (argc < 2) {
714                 printf("Invalid BSSID command: needs two arguments (network "
715                        "id and BSSID)\n");
716                 return -1;
717         }
718
719         end = cmd + sizeof(cmd);
720         pos = cmd;
721         ret = os_snprintf(pos, end - pos, "BSSID");
722         if (ret < 0 || ret >= end - pos) {
723                 printf("Too long BSSID command.\n");
724                 return -1;
725         }
726         pos += ret;
727         for (i = 0; i < argc; i++) {
728                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
729                 if (ret < 0 || ret >= end - pos) {
730                         printf("Too long BSSID command.\n");
731                         return -1;
732                 }
733                 pos += ret;
734         }
735
736         return wpa_ctrl_command(ctrl, cmd);
737 }
738
739
740 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
741                                      char *argv[])
742 {
743         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
744 }
745
746
747 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
748                                       char *argv[])
749 {
750         char cmd[32];
751         int res;
752
753         if (argc < 1) {
754                 printf("Invalid SELECT_NETWORK command: needs one argument "
755                        "(network id)\n");
756                 return -1;
757         }
758
759         res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
760         if (res < 0 || (size_t) res >= sizeof(cmd))
761                 return -1;
762         cmd[sizeof(cmd) - 1] = '\0';
763
764         return wpa_ctrl_command(ctrl, cmd);
765 }
766
767
768 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
769                                       char *argv[])
770 {
771         char cmd[32];
772         int res;
773
774         if (argc < 1) {
775                 printf("Invalid ENABLE_NETWORK command: needs one argument "
776                        "(network id)\n");
777                 return -1;
778         }
779
780         res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
781         if (res < 0 || (size_t) res >= sizeof(cmd))
782                 return -1;
783         cmd[sizeof(cmd) - 1] = '\0';
784
785         return wpa_ctrl_command(ctrl, cmd);
786 }
787
788
789 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
790                                        char *argv[])
791 {
792         char cmd[32];
793         int res;
794
795         if (argc < 1) {
796                 printf("Invalid DISABLE_NETWORK command: needs one argument "
797                        "(network id)\n");
798                 return -1;
799         }
800
801         res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
802         if (res < 0 || (size_t) res >= sizeof(cmd))
803                 return -1;
804         cmd[sizeof(cmd) - 1] = '\0';
805
806         return wpa_ctrl_command(ctrl, cmd);
807 }
808
809
810 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
811                                    char *argv[])
812 {
813         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
814 }
815
816
817 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
818                                       char *argv[])
819 {
820         char cmd[32];
821         int res;
822
823         if (argc < 1) {
824                 printf("Invalid REMOVE_NETWORK command: needs one argument "
825                        "(network id)\n");
826                 return -1;
827         }
828
829         res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
830         if (res < 0 || (size_t) res >= sizeof(cmd))
831                 return -1;
832         cmd[sizeof(cmd) - 1] = '\0';
833
834         return wpa_ctrl_command(ctrl, cmd);
835 }
836
837
838 static void wpa_cli_show_network_variables(void)
839 {
840         printf("set_network variables:\n"
841                "  ssid (network name, SSID)\n"
842                "  psk (WPA passphrase or pre-shared key)\n"
843                "  key_mgmt (key management protocol)\n"
844                "  identity (EAP identity)\n"
845                "  password (EAP password)\n"
846                "  ...\n"
847                "\n"
848                "Note: Values are entered in the same format as the "
849                "configuration file is using,\n"
850                "i.e., strings values need to be inside double quotation "
851                "marks.\n"
852                "For example: set_network 1 ssid \"network name\"\n"
853                "\n"
854                "Please see wpa_supplicant.conf documentation for full list "
855                "of\navailable variables.\n");
856 }
857
858
859 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
860                                    char *argv[])
861 {
862         char cmd[256];
863         int res;
864
865         if (argc == 0) {
866                 wpa_cli_show_network_variables();
867                 return 0;
868         }
869
870         if (argc != 3) {
871                 printf("Invalid SET_NETWORK command: needs three arguments\n"
872                        "(network id, variable name, and value)\n");
873                 return -1;
874         }
875
876         res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
877                           argv[0], argv[1], argv[2]);
878         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
879                 printf("Too long SET_NETWORK command.\n");
880                 return -1;
881         }
882         return wpa_ctrl_command(ctrl, cmd);
883 }
884
885
886 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
887                                    char *argv[])
888 {
889         char cmd[256];
890         int res;
891
892         if (argc == 0) {
893                 wpa_cli_show_network_variables();
894                 return 0;
895         }
896
897         if (argc != 2) {
898                 printf("Invalid GET_NETWORK command: needs two arguments\n"
899                        "(network id and variable name)\n");
900                 return -1;
901         }
902
903         res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
904                           argv[0], argv[1]);
905         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
906                 printf("Too long GET_NETWORK command.\n");
907                 return -1;
908         }
909         return wpa_ctrl_command(ctrl, cmd);
910 }
911
912
913 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
914                                   char *argv[])
915 {
916         return wpa_ctrl_command(ctrl, "DISCONNECT");
917 }
918
919
920 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
921                                   char *argv[])
922 {
923         return wpa_ctrl_command(ctrl, "RECONNECT");
924 }
925
926
927 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
928                                    char *argv[])
929 {
930         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
931 }
932
933
934 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
935 {
936         return wpa_ctrl_command(ctrl, "SCAN");
937 }
938
939
940 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
941                                     char *argv[])
942 {
943         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
944 }
945
946
947 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
948 {
949         char cmd[64];
950         int res;
951
952         if (argc != 1) {
953                 printf("Invalid BSS command: need one argument (index or "
954                        "BSSID)\n");
955                 return -1;
956         }
957
958         res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
959         if (res < 0 || (size_t) res >= sizeof(cmd))
960                 return -1;
961         cmd[sizeof(cmd) - 1] = '\0';
962
963         return wpa_ctrl_command(ctrl, cmd);
964 }
965
966
967 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
968                                       char *argv[])
969 {
970         char cmd[64];
971         int res;
972
973         if (argc < 1 || argc > 2) {
974                 printf("Invalid GET_CAPABILITY command: need either one or "
975                        "two arguments\n");
976                 return -1;
977         }
978
979         if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
980                 printf("Invalid GET_CAPABILITY command: second argument, "
981                        "if any, must be 'strict'\n");
982                 return -1;
983         }
984
985         res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
986                           (argc == 2) ? " strict" : "");
987         if (res < 0 || (size_t) res >= sizeof(cmd))
988                 return -1;
989         cmd[sizeof(cmd) - 1] = '\0';
990
991         return wpa_ctrl_command(ctrl, cmd);
992 }
993
994
995 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
996 {
997         printf("Available interfaces:\n");
998         return wpa_ctrl_command(ctrl, "INTERFACES");
999 }
1000
1001
1002 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1003 {
1004         if (argc < 1) {
1005                 wpa_cli_list_interfaces(ctrl);
1006                 return 0;
1007         }
1008
1009         wpa_cli_close_connection();
1010         os_free(ctrl_ifname);
1011         ctrl_ifname = os_strdup(argv[0]);
1012
1013         if (wpa_cli_open_connection(ctrl_ifname)) {
1014                 printf("Connected to interface '%s.\n", ctrl_ifname);
1015                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1016                         wpa_cli_attached = 1;
1017                 } else {
1018                         printf("Warning: Failed to attach to "
1019                                "wpa_supplicant.\n");
1020                 }
1021         } else {
1022                 printf("Could not connect to interface '%s' - re-trying\n",
1023                        ctrl_ifname);
1024         }
1025         return 0;
1026 }
1027
1028
1029 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1030                                    char *argv[])
1031 {
1032         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1033 }
1034
1035
1036 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1037                                  char *argv[])
1038 {
1039         return wpa_ctrl_command(ctrl, "TERMINATE");
1040 }
1041
1042
1043 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1044                                      char *argv[])
1045 {
1046         char cmd[256];
1047         int res;
1048
1049         if (argc < 1) {
1050                 printf("Invalid INTERFACE_ADD command: needs at least one "
1051                        "argument (interface name)\n"
1052                        "All arguments: ifname confname driver ctrl_interface "
1053                        "driver_param bridge_name\n");
1054                 return -1;
1055         }
1056
1057         /*
1058          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1059          * <driver_param>TAB<bridge_name>
1060          */
1061         res = os_snprintf(cmd, sizeof(cmd),
1062                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1063                           argv[0],
1064                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1065                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1066                           argc > 5 ? argv[5] : "");
1067         if (res < 0 || (size_t) res >= sizeof(cmd))
1068                 return -1;
1069         cmd[sizeof(cmd) - 1] = '\0';
1070         return wpa_ctrl_command(ctrl, cmd);
1071 }
1072
1073
1074 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1075                                         char *argv[])
1076 {
1077         char cmd[128];
1078         int res;
1079
1080         if (argc != 1) {
1081                 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1082                        "(interface name)\n");
1083                 return -1;
1084         }
1085
1086         res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1087         if (res < 0 || (size_t) res >= sizeof(cmd))
1088                 return -1;
1089         cmd[sizeof(cmd) - 1] = '\0';
1090         return wpa_ctrl_command(ctrl, cmd);
1091 }
1092
1093
1094 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1095                                       char *argv[])
1096 {
1097         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1098 }
1099
1100
1101 enum wpa_cli_cmd_flags {
1102         cli_cmd_flag_none               = 0x00,
1103         cli_cmd_flag_sensitive          = 0x01
1104 };
1105
1106 struct wpa_cli_cmd {
1107         const char *cmd;
1108         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1109         enum wpa_cli_cmd_flags flags;
1110         const char *usage;
1111 };
1112
1113 static struct wpa_cli_cmd wpa_cli_commands[] = {
1114         { "status", wpa_cli_cmd_status,
1115           cli_cmd_flag_none,
1116           "[verbose] = get current WPA/EAPOL/EAP status" },
1117         { "ping", wpa_cli_cmd_ping,
1118           cli_cmd_flag_none,
1119           "= pings wpa_supplicant" },
1120         { "mib", wpa_cli_cmd_mib,
1121           cli_cmd_flag_none,
1122           "= get MIB variables (dot1x, dot11)" },
1123         { "help", wpa_cli_cmd_help,
1124           cli_cmd_flag_none,
1125           "= show this usage help" },
1126         { "interface", wpa_cli_cmd_interface,
1127           cli_cmd_flag_none,
1128           "[ifname] = show interfaces/select interface" },
1129         { "level", wpa_cli_cmd_level,
1130           cli_cmd_flag_none,
1131           "<debug level> = change debug level" },
1132         { "license", wpa_cli_cmd_license,
1133           cli_cmd_flag_none,
1134           "= show full wpa_cli license" },
1135         { "quit", wpa_cli_cmd_quit,
1136           cli_cmd_flag_none,
1137           "= exit wpa_cli" },
1138         { "set", wpa_cli_cmd_set,
1139           cli_cmd_flag_none,
1140           "= set variables (shows list of variables when run without "
1141           "arguments)" },
1142         { "logon", wpa_cli_cmd_logon,
1143           cli_cmd_flag_none,
1144           "= IEEE 802.1X EAPOL state machine logon" },
1145         { "logoff", wpa_cli_cmd_logoff,
1146           cli_cmd_flag_none,
1147           "= IEEE 802.1X EAPOL state machine logoff" },
1148         { "pmksa", wpa_cli_cmd_pmksa,
1149           cli_cmd_flag_none,
1150           "= show PMKSA cache" },
1151         { "reassociate", wpa_cli_cmd_reassociate,
1152           cli_cmd_flag_none,
1153           "= force reassociation" },
1154         { "preauthenticate", wpa_cli_cmd_preauthenticate,
1155           cli_cmd_flag_none,
1156           "<BSSID> = force preauthentication" },
1157         { "identity", wpa_cli_cmd_identity,
1158           cli_cmd_flag_none,
1159           "<network id> <identity> = configure identity for an SSID" },
1160         { "password", wpa_cli_cmd_password,
1161           cli_cmd_flag_sensitive,
1162           "<network id> <password> = configure password for an SSID" },
1163         { "new_password", wpa_cli_cmd_new_password,
1164           cli_cmd_flag_sensitive,
1165           "<network id> <password> = change password for an SSID" },
1166         { "pin", wpa_cli_cmd_pin,
1167           cli_cmd_flag_sensitive,
1168           "<network id> <pin> = configure pin for an SSID" },
1169         { "otp", wpa_cli_cmd_otp,
1170           cli_cmd_flag_sensitive,
1171           "<network id> <password> = configure one-time-password for an SSID"
1172         },
1173         { "passphrase", wpa_cli_cmd_passphrase,
1174           cli_cmd_flag_sensitive,
1175           "<network id> <passphrase> = configure private key passphrase\n"
1176           "  for an SSID" },
1177         { "bssid", wpa_cli_cmd_bssid,
1178           cli_cmd_flag_none,
1179           "<network id> <BSSID> = set preferred BSSID for an SSID" },
1180         { "list_networks", wpa_cli_cmd_list_networks,
1181           cli_cmd_flag_none,
1182           "= list configured networks" },
1183         { "select_network", wpa_cli_cmd_select_network,
1184           cli_cmd_flag_none,
1185           "<network id> = select a network (disable others)" },
1186         { "enable_network", wpa_cli_cmd_enable_network,
1187           cli_cmd_flag_none,
1188           "<network id> = enable a network" },
1189         { "disable_network", wpa_cli_cmd_disable_network,
1190           cli_cmd_flag_none,
1191           "<network id> = disable a network" },
1192         { "add_network", wpa_cli_cmd_add_network,
1193           cli_cmd_flag_none,
1194           "= add a network" },
1195         { "remove_network", wpa_cli_cmd_remove_network,
1196           cli_cmd_flag_none,
1197           "<network id> = remove a network" },
1198         { "set_network", wpa_cli_cmd_set_network,
1199           cli_cmd_flag_sensitive,
1200           "<network id> <variable> <value> = set network variables (shows\n"
1201           "  list of variables when run without arguments)" },
1202         { "get_network", wpa_cli_cmd_get_network,
1203           cli_cmd_flag_none,
1204           "<network id> <variable> = get network variables" },
1205         { "save_config", wpa_cli_cmd_save_config,
1206           cli_cmd_flag_none,
1207           "= save the current configuration" },
1208         { "disconnect", wpa_cli_cmd_disconnect,
1209           cli_cmd_flag_none,
1210           "= disconnect and wait for reassociate/reconnect command before\n"
1211           "  connecting" },
1212         { "reconnect", wpa_cli_cmd_reconnect,
1213           cli_cmd_flag_none,
1214           "= like reassociate, but only takes effect if already disconnected"
1215         },
1216         { "scan", wpa_cli_cmd_scan,
1217           cli_cmd_flag_none,
1218           "= request new BSS scan" },
1219         { "scan_results", wpa_cli_cmd_scan_results,
1220           cli_cmd_flag_none,
1221           "= get latest scan results" },
1222         { "bss", wpa_cli_cmd_bss,
1223           cli_cmd_flag_none,
1224           "<<idx> | <bssid>> = get detailed scan result info" },
1225         { "get_capability", wpa_cli_cmd_get_capability,
1226           cli_cmd_flag_none,
1227           "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1228         { "reconfigure", wpa_cli_cmd_reconfigure,
1229           cli_cmd_flag_none,
1230           "= force wpa_supplicant to re-read its configuration file" },
1231         { "terminate", wpa_cli_cmd_terminate,
1232           cli_cmd_flag_none,
1233           "= terminate wpa_supplicant" },
1234         { "interface_add", wpa_cli_cmd_interface_add,
1235           cli_cmd_flag_none,
1236           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1237           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
1238           "  are optional" },
1239         { "interface_remove", wpa_cli_cmd_interface_remove,
1240           cli_cmd_flag_none,
1241           "<ifname> = removes the interface" },
1242         { "interface_list", wpa_cli_cmd_interface_list,
1243           cli_cmd_flag_none,
1244           "= list available interfaces" },
1245         { "ap_scan", wpa_cli_cmd_ap_scan,
1246           cli_cmd_flag_none,
1247           "<value> = set ap_scan parameter" },
1248         { "stkstart", wpa_cli_cmd_stkstart,
1249           cli_cmd_flag_none,
1250           "<addr> = request STK negotiation with <addr>" },
1251         { "ft_ds", wpa_cli_cmd_ft_ds,
1252           cli_cmd_flag_none,
1253           "<addr> = request over-the-DS FT with <addr>" },
1254         { "wps_pbc", wpa_cli_cmd_wps_pbc,
1255           cli_cmd_flag_none,
1256           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1257         { "wps_pin", wpa_cli_cmd_wps_pin,
1258           cli_cmd_flag_sensitive,
1259           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1260           "hardcoded)" },
1261         { "wps_reg", wpa_cli_cmd_wps_reg,
1262           cli_cmd_flag_sensitive,
1263           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1264         { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1265           cli_cmd_flag_none,
1266           "<addr> = request RSN authentication with <addr> in IBSS" },
1267         { NULL, NULL, cli_cmd_flag_none, NULL }
1268 };
1269
1270
1271 /*
1272  * Prints command usage, lines are padded with the specified string.
1273  */
1274 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1275 {
1276         char c;
1277         size_t n;
1278
1279         printf("%s%s ", pad, cmd->cmd);
1280         for (n = 0; (c = cmd->usage[n]); n++) {
1281                 printf("%c", c);
1282                 if (c == '\n')
1283                         printf("%s", pad);
1284         }
1285         printf("\n");
1286 }
1287
1288
1289 static void print_help(void)
1290 {
1291         int n;
1292         printf("commands:\n");
1293         for (n = 0; wpa_cli_commands[n].cmd; n++)
1294                 print_cmd_help(&wpa_cli_commands[n], "  ");
1295 }
1296
1297
1298 #ifdef CONFIG_READLINE
1299 static int cmd_has_sensitive_data(const char *cmd)
1300 {
1301         const char *c, *delim;
1302         int n;
1303         size_t len;
1304
1305         delim = os_strchr(cmd, ' ');
1306         if (delim)
1307                 len = delim - cmd;
1308         else
1309                 len = os_strlen(cmd);
1310
1311         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1312                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1313                         return (wpa_cli_commands[n].flags &
1314                                 cli_cmd_flag_sensitive);
1315         }
1316         return 0;
1317 }
1318 #endif /* CONFIG_READLINE */
1319
1320
1321 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1322 {
1323         struct wpa_cli_cmd *cmd, *match = NULL;
1324         int count;
1325         int ret = 0;
1326
1327         count = 0;
1328         cmd = wpa_cli_commands;
1329         while (cmd->cmd) {
1330                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1331                 {
1332                         match = cmd;
1333                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1334                                 /* we have an exact match */
1335                                 count = 1;
1336                                 break;
1337                         }
1338                         count++;
1339                 }
1340                 cmd++;
1341         }
1342
1343         if (count > 1) {
1344                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1345                 cmd = wpa_cli_commands;
1346                 while (cmd->cmd) {
1347                         if (os_strncasecmp(cmd->cmd, argv[0],
1348                                            os_strlen(argv[0])) == 0) {
1349                                 printf(" %s", cmd->cmd);
1350                         }
1351                         cmd++;
1352                 }
1353                 printf("\n");
1354                 ret = 1;
1355         } else if (count == 0) {
1356                 printf("Unknown command '%s'\n", argv[0]);
1357                 ret = 1;
1358         } else {
1359                 ret = match->handler(ctrl, argc - 1, &argv[1]);
1360         }
1361
1362         return ret;
1363 }
1364
1365
1366 static int str_match(const char *a, const char *b)
1367 {
1368         return os_strncmp(a, b, os_strlen(b)) == 0;
1369 }
1370
1371
1372 static int wpa_cli_exec(const char *program, const char *arg1,
1373                         const char *arg2)
1374 {
1375         char *cmd;
1376         size_t len;
1377         int res;
1378         int ret = 0;
1379
1380         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1381         cmd = os_malloc(len);
1382         if (cmd == NULL)
1383                 return -1;
1384         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1385         if (res < 0 || (size_t) res >= len) {
1386                 os_free(cmd);
1387                 return -1;
1388         }
1389         cmd[len - 1] = '\0';
1390 #ifndef _WIN32_WCE
1391         if (system(cmd) < 0)
1392                 ret = -1;
1393 #endif /* _WIN32_WCE */
1394         os_free(cmd);
1395
1396         return ret;
1397 }
1398
1399
1400 static void wpa_cli_action_process(const char *msg)
1401 {
1402         const char *pos;
1403         char *copy = NULL, *id, *pos2;
1404
1405         pos = msg;
1406         if (*pos == '<') {
1407                 /* skip priority */
1408                 pos = os_strchr(pos, '>');
1409                 if (pos)
1410                         pos++;
1411                 else
1412                         pos = msg;
1413         }
1414
1415         if (str_match(pos, WPA_EVENT_CONNECTED)) {
1416                 int new_id = -1;
1417                 os_unsetenv("WPA_ID");
1418                 os_unsetenv("WPA_ID_STR");
1419                 os_unsetenv("WPA_CTRL_DIR");
1420
1421                 pos = os_strstr(pos, "[id=");
1422                 if (pos)
1423                         copy = os_strdup(pos + 4);
1424
1425                 if (copy) {
1426                         pos2 = id = copy;
1427                         while (*pos2 && *pos2 != ' ')
1428                                 pos2++;
1429                         *pos2++ = '\0';
1430                         new_id = atoi(id);
1431                         os_setenv("WPA_ID", id, 1);
1432                         while (*pos2 && *pos2 != '=')
1433                                 pos2++;
1434                         if (*pos2 == '=')
1435                                 pos2++;
1436                         id = pos2;
1437                         while (*pos2 && *pos2 != ']')
1438                                 pos2++;
1439                         *pos2 = '\0';
1440                         os_setenv("WPA_ID_STR", id, 1);
1441                         os_free(copy);
1442                 }
1443
1444                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1445
1446                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1447                         wpa_cli_connected = 1;
1448                         wpa_cli_last_id = new_id;
1449                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1450                 }
1451         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1452                 if (wpa_cli_connected) {
1453                         wpa_cli_connected = 0;
1454                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1455                 }
1456         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1457                 printf("wpa_supplicant is terminating - stop monitoring\n");
1458                 wpa_cli_quit = 1;
1459         }
1460 }
1461
1462
1463 #ifndef CONFIG_ANSI_C_EXTRA
1464 static void wpa_cli_action_cb(char *msg, size_t len)
1465 {
1466         wpa_cli_action_process(msg);
1467 }
1468 #endif /* CONFIG_ANSI_C_EXTRA */
1469
1470
1471 static void wpa_cli_reconnect(void)
1472 {
1473         wpa_cli_close_connection();
1474         ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1475         if (ctrl_conn) {
1476                 printf("Connection to wpa_supplicant re-established\n");
1477                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1478                         wpa_cli_attached = 1;
1479                 } else {
1480                         printf("Warning: Failed to attach to "
1481                                "wpa_supplicant.\n");
1482                 }
1483         }
1484 }
1485
1486
1487 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1488                                  int action_monitor)
1489 {
1490         int first = 1;
1491         if (ctrl_conn == NULL) {
1492                 wpa_cli_reconnect();
1493                 return;
1494         }
1495         while (wpa_ctrl_pending(ctrl) > 0) {
1496                 char buf[256];
1497                 size_t len = sizeof(buf) - 1;
1498                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1499                         buf[len] = '\0';
1500                         if (action_monitor)
1501                                 wpa_cli_action_process(buf);
1502                         else {
1503                                 if (in_read && first)
1504                                         printf("\n");
1505                                 first = 0;
1506                                 printf("%s\n", buf);
1507                         }
1508                 } else {
1509                         printf("Could not read pending message.\n");
1510                         break;
1511                 }
1512         }
1513
1514         if (wpa_ctrl_pending(ctrl) < 0) {
1515                 printf("Connection to wpa_supplicant lost - trying to "
1516                        "reconnect\n");
1517                 wpa_cli_reconnect();
1518         }
1519 }
1520
1521
1522 #ifdef CONFIG_READLINE
1523 static char * wpa_cli_cmd_gen(const char *text, int state)
1524 {
1525         static int i, len;
1526         const char *cmd;
1527
1528         if (state == 0) {
1529                 i = 0;
1530                 len = os_strlen(text);
1531         }
1532
1533         while ((cmd = wpa_cli_commands[i].cmd)) {
1534                 i++;
1535                 if (os_strncasecmp(cmd, text, len) == 0)
1536                         return os_strdup(cmd);
1537         }
1538
1539         return NULL;
1540 }
1541
1542
1543 static char * wpa_cli_dummy_gen(const char *text, int state)
1544 {
1545         return NULL;
1546 }
1547
1548
1549 static char ** wpa_cli_completion(const char *text, int start, int end)
1550 {
1551         return rl_completion_matches(text, start == 0 ?
1552                                      wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1553 }
1554 #endif /* CONFIG_READLINE */
1555
1556
1557 static void wpa_cli_interactive(void)
1558 {
1559 #define max_args 10
1560         char cmdbuf[256], *cmd, *argv[max_args], *pos;
1561         int argc;
1562 #ifdef CONFIG_READLINE
1563         char *home, *hfile = NULL;
1564 #endif /* CONFIG_READLINE */
1565
1566         printf("\nInteractive mode\n\n");
1567
1568 #ifdef CONFIG_READLINE
1569         rl_attempted_completion_function = wpa_cli_completion;
1570         home = getenv("HOME");
1571         if (home) {
1572                 const char *fname = ".wpa_cli_history";
1573                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1574                 hfile = os_malloc(hfile_len);
1575                 if (hfile) {
1576                         int res;
1577                         res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1578                                           fname);
1579                         if (res >= 0 && res < hfile_len) {
1580                                 hfile[hfile_len - 1] = '\0';
1581                                 read_history(hfile);
1582                                 stifle_history(100);
1583                         }
1584                 }
1585         }
1586 #endif /* CONFIG_READLINE */
1587
1588         do {
1589                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1590 #ifndef CONFIG_NATIVE_WINDOWS
1591                 alarm(ping_interval);
1592 #endif /* CONFIG_NATIVE_WINDOWS */
1593 #ifdef CONFIG_READLINE
1594                 cmd = readline("> ");
1595                 if (cmd && *cmd) {
1596                         HIST_ENTRY *h;
1597                         while (next_history())
1598                                 ;
1599                         h = previous_history();
1600                         if (h == NULL || os_strcmp(cmd, h->line) != 0)
1601                                 add_history(cmd);
1602                         next_history();
1603                 }
1604 #else /* CONFIG_READLINE */
1605                 printf("> ");
1606                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1607 #endif /* CONFIG_READLINE */
1608 #ifndef CONFIG_NATIVE_WINDOWS
1609                 alarm(0);
1610 #endif /* CONFIG_NATIVE_WINDOWS */
1611                 if (cmd == NULL)
1612                         break;
1613                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1614                 pos = cmd;
1615                 while (*pos != '\0') {
1616                         if (*pos == '\n') {
1617                                 *pos = '\0';
1618                                 break;
1619                         }
1620                         pos++;
1621                 }
1622                 argc = 0;
1623                 pos = cmd;
1624                 for (;;) {
1625                         while (*pos == ' ')
1626                                 pos++;
1627                         if (*pos == '\0')
1628                                 break;
1629                         argv[argc] = pos;
1630                         argc++;
1631                         if (argc == max_args)
1632                                 break;
1633                         if (*pos == '"') {
1634                                 char *pos2 = os_strrchr(pos, '"');
1635                                 if (pos2)
1636                                         pos = pos2 + 1;
1637                         }
1638                         while (*pos != '\0' && *pos != ' ')
1639                                 pos++;
1640                         if (*pos == ' ')
1641                                 *pos++ = '\0';
1642                 }
1643                 if (argc)
1644                         wpa_request(ctrl_conn, argc, argv);
1645
1646                 if (cmd != cmdbuf)
1647                         os_free(cmd);
1648         } while (!wpa_cli_quit);
1649
1650 #ifdef CONFIG_READLINE
1651         if (hfile) {
1652                 /* Save command history, excluding lines that may contain
1653                  * passwords. */
1654                 HIST_ENTRY *h;
1655                 history_set_pos(0);
1656                 while ((h = current_history())) {
1657                         char *p = h->line;
1658                         while (*p == ' ' || *p == '\t')
1659                                 p++;
1660                         if (cmd_has_sensitive_data(p)) {
1661                                 h = remove_history(where_history());
1662                                 if (h) {
1663                                         os_free(h->line);
1664                                         os_free(h->data);
1665                                         os_free(h);
1666                                 } else
1667                                         next_history();
1668                         } else
1669                                 next_history();
1670                 }
1671                 write_history(hfile);
1672                 os_free(hfile);
1673         }
1674 #endif /* CONFIG_READLINE */
1675 }
1676
1677
1678 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1679 {
1680 #ifdef CONFIG_ANSI_C_EXTRA
1681         /* TODO: ANSI C version(?) */
1682         printf("Action processing not supported in ANSI C build.\n");
1683 #else /* CONFIG_ANSI_C_EXTRA */
1684         fd_set rfds;
1685         int fd, res;
1686         struct timeval tv;
1687         char buf[256]; /* note: large enough to fit in unsolicited messages */
1688         size_t len;
1689
1690         fd = wpa_ctrl_get_fd(ctrl);
1691
1692         while (!wpa_cli_quit) {
1693                 FD_ZERO(&rfds);
1694                 FD_SET(fd, &rfds);
1695                 tv.tv_sec = ping_interval;
1696                 tv.tv_usec = 0;
1697                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1698                 if (res < 0 && errno != EINTR) {
1699                         perror("select");
1700                         break;
1701                 }
1702
1703                 if (FD_ISSET(fd, &rfds))
1704                         wpa_cli_recv_pending(ctrl, 0, 1);
1705                 else {
1706                         /* verify that connection is still working */
1707                         len = sizeof(buf) - 1;
1708                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1709                                              wpa_cli_action_cb) < 0 ||
1710                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1711                                 printf("wpa_supplicant did not reply to PING "
1712                                        "command - exiting\n");
1713                                 break;
1714                         }
1715                 }
1716         }
1717 #endif /* CONFIG_ANSI_C_EXTRA */
1718 }
1719
1720
1721 static void wpa_cli_cleanup(void)
1722 {
1723         wpa_cli_close_connection();
1724         if (pid_file)
1725                 os_daemonize_terminate(pid_file);
1726
1727         os_program_deinit();
1728 }
1729
1730 static void wpa_cli_terminate(int sig)
1731 {
1732         wpa_cli_cleanup();
1733         exit(0);
1734 }
1735
1736
1737 #ifndef CONFIG_NATIVE_WINDOWS
1738 static void wpa_cli_alarm(int sig)
1739 {
1740         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1741                 printf("Connection to wpa_supplicant lost - trying to "
1742                        "reconnect\n");
1743                 wpa_cli_close_connection();
1744         }
1745         if (!ctrl_conn)
1746                 wpa_cli_reconnect();
1747         if (ctrl_conn)
1748                 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1749         alarm(ping_interval);
1750 }
1751 #endif /* CONFIG_NATIVE_WINDOWS */
1752
1753
1754 static char * wpa_cli_get_default_ifname(void)
1755 {
1756         char *ifname = NULL;
1757
1758 #ifdef CONFIG_CTRL_IFACE_UNIX
1759         struct dirent *dent;
1760         DIR *dir = opendir(ctrl_iface_dir);
1761         if (!dir)
1762                 return NULL;
1763         while ((dent = readdir(dir))) {
1764 #ifdef _DIRENT_HAVE_D_TYPE
1765                 /*
1766                  * Skip the file if it is not a socket. Also accept
1767                  * DT_UNKNOWN (0) in case the C library or underlying
1768                  * file system does not support d_type.
1769                  */
1770                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1771                         continue;
1772 #endif /* _DIRENT_HAVE_D_TYPE */
1773                 if (os_strcmp(dent->d_name, ".") == 0 ||
1774                     os_strcmp(dent->d_name, "..") == 0)
1775                         continue;
1776                 printf("Selected interface '%s'\n", dent->d_name);
1777                 ifname = os_strdup(dent->d_name);
1778                 break;
1779         }
1780         closedir(dir);
1781 #endif /* CONFIG_CTRL_IFACE_UNIX */
1782
1783 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1784         char buf[2048], *pos;
1785         size_t len;
1786         struct wpa_ctrl *ctrl;
1787         int ret;
1788
1789         ctrl = wpa_ctrl_open(NULL);
1790         if (ctrl == NULL)
1791                 return NULL;
1792
1793         len = sizeof(buf) - 1;
1794         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1795         if (ret >= 0) {
1796                 buf[len] = '\0';
1797                 pos = os_strchr(buf, '\n');
1798                 if (pos)
1799                         *pos = '\0';
1800                 ifname = os_strdup(buf);
1801         }
1802         wpa_ctrl_close(ctrl);
1803 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1804
1805         return ifname;
1806 }
1807
1808
1809 int main(int argc, char *argv[])
1810 {
1811         int interactive;
1812         int warning_displayed = 0;
1813         int c;
1814         int daemonize = 0;
1815         int ret = 0;
1816         const char *global = NULL;
1817
1818         if (os_program_init())
1819                 return -1;
1820
1821         for (;;) {
1822                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
1823                 if (c < 0)
1824                         break;
1825                 switch (c) {
1826                 case 'a':
1827                         action_file = optarg;
1828                         break;
1829                 case 'B':
1830                         daemonize = 1;
1831                         break;
1832                 case 'g':
1833                         global = optarg;
1834                         break;
1835                 case 'G':
1836                         ping_interval = atoi(optarg);
1837                         break;
1838                 case 'h':
1839                         usage();
1840                         return 0;
1841                 case 'v':
1842                         printf("%s\n", wpa_cli_version);
1843                         return 0;
1844                 case 'i':
1845                         os_free(ctrl_ifname);
1846                         ctrl_ifname = os_strdup(optarg);
1847                         break;
1848                 case 'p':
1849                         ctrl_iface_dir = optarg;
1850                         break;
1851                 case 'P':
1852                         pid_file = optarg;
1853                         break;
1854                 default:
1855                         usage();
1856                         return -1;
1857                 }
1858         }
1859
1860         interactive = (argc == optind) && (action_file == NULL);
1861
1862         if (interactive)
1863                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1864
1865         if (global) {
1866 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1867                 ctrl_conn = wpa_ctrl_open(NULL);
1868 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1869                 ctrl_conn = wpa_ctrl_open(global);
1870 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1871                 if (ctrl_conn == NULL) {
1872                         perror("Failed to connect to wpa_supplicant - "
1873                                "wpa_ctrl_open");
1874                         return -1;
1875                 }
1876         }
1877
1878         for (; !global;) {
1879                 if (ctrl_ifname == NULL)
1880                         ctrl_ifname = wpa_cli_get_default_ifname();
1881                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1882                 if (ctrl_conn) {
1883                         if (warning_displayed)
1884                                 printf("Connection established.\n");
1885                         break;
1886                 }
1887
1888                 if (!interactive) {
1889                         perror("Failed to connect to wpa_supplicant - "
1890                                "wpa_ctrl_open");
1891                         return -1;
1892                 }
1893
1894                 if (!warning_displayed) {
1895                         printf("Could not connect to wpa_supplicant - "
1896                                "re-trying\n");
1897                         warning_displayed = 1;
1898                 }
1899                 os_sleep(1, 0);
1900                 continue;
1901         }
1902
1903 #ifndef _WIN32_WCE
1904         signal(SIGINT, wpa_cli_terminate);
1905         signal(SIGTERM, wpa_cli_terminate);
1906 #endif /* _WIN32_WCE */
1907 #ifndef CONFIG_NATIVE_WINDOWS
1908         signal(SIGALRM, wpa_cli_alarm);
1909 #endif /* CONFIG_NATIVE_WINDOWS */
1910
1911         if (interactive || action_file) {
1912                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1913                         wpa_cli_attached = 1;
1914                 } else {
1915                         printf("Warning: Failed to attach to "
1916                                "wpa_supplicant.\n");
1917                         if (!interactive)
1918                                 return -1;
1919                 }
1920         }
1921
1922         if (daemonize && os_daemonize(pid_file))
1923                 return -1;
1924
1925         if (interactive)
1926                 wpa_cli_interactive();
1927         else if (action_file)
1928                 wpa_cli_action(ctrl_conn);
1929         else
1930                 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1931
1932         os_free(ctrl_ifname);
1933         wpa_cli_cleanup();
1934
1935         return ret;
1936 }
1937
1938 #else /* CONFIG_CTRL_IFACE */
1939 int main(int argc, char *argv[])
1940 {
1941         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1942         return -1;
1943 }
1944 #endif /* CONFIG_CTRL_IFACE */