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