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