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