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