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