OSDN Git Service

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