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