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