Allow HT to be enabled for a STA even without WMM
[wpasupplicant] / 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 struct wpa_cli_cmd {
1124         const char *cmd;
1125         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1126 };
1127
1128 static struct wpa_cli_cmd wpa_cli_commands[] = {
1129         { "status", wpa_cli_cmd_status },
1130         { "ping", wpa_cli_cmd_ping },
1131         { "mib", wpa_cli_cmd_mib },
1132         { "help", wpa_cli_cmd_help },
1133         { "interface", wpa_cli_cmd_interface },
1134         { "level", wpa_cli_cmd_level },
1135         { "license", wpa_cli_cmd_license },
1136         { "quit", wpa_cli_cmd_quit },
1137         { "set", wpa_cli_cmd_set },
1138         { "logon", wpa_cli_cmd_logon },
1139         { "logoff", wpa_cli_cmd_logoff },
1140         { "pmksa", wpa_cli_cmd_pmksa },
1141         { "reassociate", wpa_cli_cmd_reassociate },
1142         { "preauthenticate", wpa_cli_cmd_preauthenticate },
1143         { "identity", wpa_cli_cmd_identity },
1144         { "password", wpa_cli_cmd_password },
1145         { "new_password", wpa_cli_cmd_new_password },
1146         { "pin", wpa_cli_cmd_pin },
1147         { "otp", wpa_cli_cmd_otp },
1148         { "passphrase", wpa_cli_cmd_passphrase },
1149         { "bssid", wpa_cli_cmd_bssid },
1150         { "list_networks", wpa_cli_cmd_list_networks },
1151         { "select_network", wpa_cli_cmd_select_network },
1152         { "enable_network", wpa_cli_cmd_enable_network },
1153         { "disable_network", wpa_cli_cmd_disable_network },
1154         { "add_network", wpa_cli_cmd_add_network },
1155         { "remove_network", wpa_cli_cmd_remove_network },
1156         { "set_network", wpa_cli_cmd_set_network },
1157         { "get_network", wpa_cli_cmd_get_network },
1158         { "save_config", wpa_cli_cmd_save_config },
1159         { "disconnect", wpa_cli_cmd_disconnect },
1160         { "reconnect", wpa_cli_cmd_reconnect },
1161         { "scan", wpa_cli_cmd_scan },
1162         { "scan_results", wpa_cli_cmd_scan_results },
1163         { "bss", wpa_cli_cmd_bss },
1164         { "get_capability", wpa_cli_cmd_get_capability },
1165         { "reconfigure", wpa_cli_cmd_reconfigure },
1166         { "terminate", wpa_cli_cmd_terminate },
1167         { "interface_add", wpa_cli_cmd_interface_add },
1168         { "interface_remove", wpa_cli_cmd_interface_remove },
1169         { "ap_scan", wpa_cli_cmd_ap_scan },
1170         { "stkstart", wpa_cli_cmd_stkstart },
1171         { "ft_ds", wpa_cli_cmd_ft_ds },
1172         { "wps_pbc", wpa_cli_cmd_wps_pbc },
1173         { "wps_pin", wpa_cli_cmd_wps_pin },
1174         { "wps_reg", wpa_cli_cmd_wps_reg },
1175         { NULL, NULL }
1176 };
1177
1178
1179 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1180 {
1181         struct wpa_cli_cmd *cmd, *match = NULL;
1182         int count;
1183         int ret = 0;
1184
1185         count = 0;
1186         cmd = wpa_cli_commands;
1187         while (cmd->cmd) {
1188                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1189                 {
1190                         match = cmd;
1191                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1192                                 /* we have an exact match */
1193                                 count = 1;
1194                                 break;
1195                         }
1196                         count++;
1197                 }
1198                 cmd++;
1199         }
1200
1201         if (count > 1) {
1202                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1203                 cmd = wpa_cli_commands;
1204                 while (cmd->cmd) {
1205                         if (os_strncasecmp(cmd->cmd, argv[0],
1206                                            os_strlen(argv[0])) == 0) {
1207                                 printf(" %s", cmd->cmd);
1208                         }
1209                         cmd++;
1210                 }
1211                 printf("\n");
1212                 ret = 1;
1213         } else if (count == 0) {
1214                 printf("Unknown command '%s'\n", argv[0]);
1215                 ret = 1;
1216         } else {
1217                 ret = match->handler(ctrl, argc - 1, &argv[1]);
1218         }
1219
1220         return ret;
1221 }
1222
1223
1224 static int str_match(const char *a, const char *b)
1225 {
1226         return os_strncmp(a, b, os_strlen(b)) == 0;
1227 }
1228
1229
1230 static int wpa_cli_exec(const char *program, const char *arg1,
1231                         const char *arg2)
1232 {
1233         char *cmd;
1234         size_t len;
1235         int res;
1236         int ret = 0;
1237
1238         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1239         cmd = os_malloc(len);
1240         if (cmd == NULL)
1241                 return -1;
1242         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1243         if (res < 0 || (size_t) res >= len) {
1244                 os_free(cmd);
1245                 return -1;
1246         }
1247         cmd[len - 1] = '\0';
1248 #ifndef _WIN32_WCE
1249         if (system(cmd) < 0)
1250                 ret = -1;
1251 #endif /* _WIN32_WCE */
1252         os_free(cmd);
1253
1254         return ret;
1255 }
1256
1257
1258 static void wpa_cli_action_process(const char *msg)
1259 {
1260         const char *pos;
1261         char *copy = NULL, *id, *pos2;
1262
1263         pos = msg;
1264         if (*pos == '<') {
1265                 /* skip priority */
1266                 pos = os_strchr(pos, '>');
1267                 if (pos)
1268                         pos++;
1269                 else
1270                         pos = msg;
1271         }
1272
1273         if (str_match(pos, WPA_EVENT_CONNECTED)) {
1274                 int new_id = -1;
1275                 os_unsetenv("WPA_ID");
1276                 os_unsetenv("WPA_ID_STR");
1277                 os_unsetenv("WPA_CTRL_DIR");
1278
1279                 pos = os_strstr(pos, "[id=");
1280                 if (pos)
1281                         copy = os_strdup(pos + 4);
1282
1283                 if (copy) {
1284                         pos2 = id = copy;
1285                         while (*pos2 && *pos2 != ' ')
1286                                 pos2++;
1287                         *pos2++ = '\0';
1288                         new_id = atoi(id);
1289                         os_setenv("WPA_ID", id, 1);
1290                         while (*pos2 && *pos2 != '=')
1291                                 pos2++;
1292                         if (*pos2 == '=')
1293                                 pos2++;
1294                         id = pos2;
1295                         while (*pos2 && *pos2 != ']')
1296                                 pos2++;
1297                         *pos2 = '\0';
1298                         os_setenv("WPA_ID_STR", id, 1);
1299                         os_free(copy);
1300                 }
1301
1302                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1303
1304                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1305                         wpa_cli_connected = 1;
1306                         wpa_cli_last_id = new_id;
1307                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1308                 }
1309         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1310                 if (wpa_cli_connected) {
1311                         wpa_cli_connected = 0;
1312                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1313                 }
1314         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1315                 printf("wpa_supplicant is terminating - stop monitoring\n");
1316                 wpa_cli_quit = 1;
1317         }
1318 }
1319
1320
1321 #ifndef CONFIG_ANSI_C_EXTRA
1322 static void wpa_cli_action_cb(char *msg, size_t len)
1323 {
1324         wpa_cli_action_process(msg);
1325 }
1326 #endif /* CONFIG_ANSI_C_EXTRA */
1327
1328
1329 static void wpa_cli_reconnect(void)
1330 {
1331         wpa_cli_close_connection();
1332         ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1333         if (ctrl_conn) {
1334                 printf("Connection to wpa_supplicant re-established\n");
1335                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1336                         wpa_cli_attached = 1;
1337                 } else {
1338                         printf("Warning: Failed to attach to "
1339                                "wpa_supplicant.\n");
1340                 }
1341         }
1342 }
1343
1344
1345 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1346                                  int action_monitor)
1347 {
1348         int first = 1;
1349         if (ctrl_conn == NULL) {
1350                 wpa_cli_reconnect();
1351                 return;
1352         }
1353         while (wpa_ctrl_pending(ctrl) > 0) {
1354                 char buf[256];
1355                 size_t len = sizeof(buf) - 1;
1356                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1357                         buf[len] = '\0';
1358                         if (action_monitor)
1359                                 wpa_cli_action_process(buf);
1360                         else {
1361                                 if (in_read && first)
1362                                         printf("\n");
1363                                 first = 0;
1364                                 printf("%s\n", buf);
1365                         }
1366                 } else {
1367                         printf("Could not read pending message.\n");
1368                         break;
1369                 }
1370         }
1371
1372         if (wpa_ctrl_pending(ctrl) < 0) {
1373                 printf("Connection to wpa_supplicant lost - trying to "
1374                        "reconnect\n");
1375                 wpa_cli_reconnect();
1376         }
1377 }
1378
1379
1380 #ifdef CONFIG_READLINE
1381 static char * wpa_cli_cmd_gen(const char *text, int state)
1382 {
1383         static int i, len;
1384         const char *cmd;
1385
1386         if (state == 0) {
1387                 i = 0;
1388                 len = os_strlen(text);
1389         }
1390
1391         while ((cmd = wpa_cli_commands[i].cmd)) {
1392                 i++;
1393                 if (os_strncasecmp(cmd, text, len) == 0)
1394                         return os_strdup(cmd);
1395         }
1396
1397         return NULL;
1398 }
1399
1400
1401 static char * wpa_cli_dummy_gen(const char *text, int state)
1402 {
1403         return NULL;
1404 }
1405
1406
1407 static char ** wpa_cli_completion(const char *text, int start, int end)
1408 {
1409         return rl_completion_matches(text, start == 0 ?
1410                                      wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1411 }
1412 #endif /* CONFIG_READLINE */
1413
1414
1415 static void wpa_cli_interactive(void)
1416 {
1417 #define max_args 10
1418         char cmdbuf[256], *cmd, *argv[max_args], *pos;
1419         int argc;
1420 #ifdef CONFIG_READLINE
1421         char *home, *hfile = NULL;
1422 #endif /* CONFIG_READLINE */
1423
1424         printf("\nInteractive mode\n\n");
1425
1426 #ifdef CONFIG_READLINE
1427         rl_attempted_completion_function = wpa_cli_completion;
1428         home = getenv("HOME");
1429         if (home) {
1430                 const char *fname = ".wpa_cli_history";
1431                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1432                 hfile = os_malloc(hfile_len);
1433                 if (hfile) {
1434                         int res;
1435                         res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1436                                           fname);
1437                         if (res >= 0 && res < hfile_len) {
1438                                 hfile[hfile_len - 1] = '\0';
1439                                 read_history(hfile);
1440                                 stifle_history(100);
1441                         }
1442                 }
1443         }
1444 #endif /* CONFIG_READLINE */
1445
1446         do {
1447                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1448 #ifndef CONFIG_NATIVE_WINDOWS
1449                 alarm(1);
1450 #endif /* CONFIG_NATIVE_WINDOWS */
1451 #ifdef CONFIG_READLINE
1452                 cmd = readline("> ");
1453                 if (cmd && *cmd) {
1454                         HIST_ENTRY *h;
1455                         while (next_history())
1456                                 ;
1457                         h = previous_history();
1458                         if (h == NULL || os_strcmp(cmd, h->line) != 0)
1459                                 add_history(cmd);
1460                         next_history();
1461                 }
1462 #else /* CONFIG_READLINE */
1463                 printf("> ");
1464                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1465 #endif /* CONFIG_READLINE */
1466 #ifndef CONFIG_NATIVE_WINDOWS
1467                 alarm(0);
1468 #endif /* CONFIG_NATIVE_WINDOWS */
1469                 if (cmd == NULL)
1470                         break;
1471                 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1472                 pos = cmd;
1473                 while (*pos != '\0') {
1474                         if (*pos == '\n') {
1475                                 *pos = '\0';
1476                                 break;
1477                         }
1478                         pos++;
1479                 }
1480                 argc = 0;
1481                 pos = cmd;
1482                 for (;;) {
1483                         while (*pos == ' ')
1484                                 pos++;
1485                         if (*pos == '\0')
1486                                 break;
1487                         argv[argc] = pos;
1488                         argc++;
1489                         if (argc == max_args)
1490                                 break;
1491                         if (*pos == '"') {
1492                                 char *pos2 = os_strrchr(pos, '"');
1493                                 if (pos2)
1494                                         pos = pos2 + 1;
1495                         }
1496                         while (*pos != '\0' && *pos != ' ')
1497                                 pos++;
1498                         if (*pos == ' ')
1499                                 *pos++ = '\0';
1500                 }
1501                 if (argc)
1502                         wpa_request(ctrl_conn, argc, argv);
1503
1504                 if (cmd != cmdbuf)
1505                         os_free(cmd);
1506         } while (!wpa_cli_quit);
1507
1508 #ifdef CONFIG_READLINE
1509         if (hfile) {
1510                 /* Save command history, excluding lines that may contain
1511                  * passwords. */
1512                 HIST_ENTRY *h;
1513                 history_set_pos(0);
1514                 h = next_history();
1515                 while (h) {
1516                         char *p = h->line;
1517                         while (*p == ' ' || *p == '\t')
1518                                 p++;
1519                         if (os_strncasecmp(p, "pa", 2) == 0 ||
1520                             os_strncasecmp(p, "o", 1) == 0 ||
1521                             os_strncasecmp(p, "n", 1)) {
1522                                 h = remove_history(where_history());
1523                                 if (h) {
1524                                         os_free(h->line);
1525                                         os_free(h->data);
1526                                         os_free(h);
1527                                 }
1528                                 h = current_history();
1529                         } else {
1530                                 h = next_history();
1531                         }
1532                 }
1533                 write_history(hfile);
1534                 os_free(hfile);
1535         }
1536 #endif /* CONFIG_READLINE */
1537 }
1538
1539
1540 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1541 {
1542 #ifdef CONFIG_ANSI_C_EXTRA
1543         /* TODO: ANSI C version(?) */
1544         printf("Action processing not supported in ANSI C build.\n");
1545 #else /* CONFIG_ANSI_C_EXTRA */
1546         fd_set rfds;
1547         int fd, res;
1548         struct timeval tv;
1549         char buf[256]; /* note: large enough to fit in unsolicited messages */
1550         size_t len;
1551
1552         fd = wpa_ctrl_get_fd(ctrl);
1553
1554         while (!wpa_cli_quit) {
1555                 FD_ZERO(&rfds);
1556                 FD_SET(fd, &rfds);
1557                 tv.tv_sec = 2;
1558                 tv.tv_usec = 0;
1559                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1560                 if (res < 0 && errno != EINTR) {
1561                         perror("select");
1562                         break;
1563                 }
1564
1565                 if (FD_ISSET(fd, &rfds))
1566                         wpa_cli_recv_pending(ctrl, 0, 1);
1567                 else {
1568                         /* verify that connection is still working */
1569                         len = sizeof(buf) - 1;
1570                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1571                                              wpa_cli_action_cb) < 0 ||
1572                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1573                                 printf("wpa_supplicant did not reply to PING "
1574                                        "command - exiting\n");
1575                                 break;
1576                         }
1577                 }
1578         }
1579 #endif /* CONFIG_ANSI_C_EXTRA */
1580 }
1581
1582
1583 static void wpa_cli_cleanup(void)
1584 {
1585         wpa_cli_close_connection();
1586         if (pid_file)
1587                 os_daemonize_terminate(pid_file);
1588
1589         os_program_deinit();
1590 }
1591
1592 static void wpa_cli_terminate(int sig)
1593 {
1594         wpa_cli_cleanup();
1595         exit(0);
1596 }
1597
1598
1599 #ifndef CONFIG_NATIVE_WINDOWS
1600 static void wpa_cli_alarm(int sig)
1601 {
1602         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1603                 printf("Connection to wpa_supplicant lost - trying to "
1604                        "reconnect\n");
1605                 wpa_cli_close_connection();
1606         }
1607         if (!ctrl_conn)
1608                 wpa_cli_reconnect();
1609         if (ctrl_conn)
1610                 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1611         alarm(1);
1612 }
1613 #endif /* CONFIG_NATIVE_WINDOWS */
1614
1615
1616 static char * wpa_cli_get_default_ifname(void)
1617 {
1618         char *ifname = NULL;
1619
1620 #ifdef CONFIG_CTRL_IFACE_UNIX
1621         struct dirent *dent;
1622         DIR *dir = opendir(ctrl_iface_dir);
1623         if (!dir)
1624                 return NULL;
1625         while ((dent = readdir(dir))) {
1626 #ifdef _DIRENT_HAVE_D_TYPE
1627                 /*
1628                  * Skip the file if it is not a socket. Also accept
1629                  * DT_UNKNOWN (0) in case the C library or underlying
1630                  * file system does not support d_type.
1631                  */
1632                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1633                         continue;
1634 #endif /* _DIRENT_HAVE_D_TYPE */
1635                 if (os_strcmp(dent->d_name, ".") == 0 ||
1636                     os_strcmp(dent->d_name, "..") == 0)
1637                         continue;
1638                 printf("Selected interface '%s'\n", dent->d_name);
1639                 ifname = os_strdup(dent->d_name);
1640                 break;
1641         }
1642         closedir(dir);
1643 #endif /* CONFIG_CTRL_IFACE_UNIX */
1644
1645 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1646         char buf[2048], *pos;
1647         size_t len;
1648         struct wpa_ctrl *ctrl;
1649         int ret;
1650
1651         ctrl = wpa_ctrl_open(NULL);
1652         if (ctrl == NULL)
1653                 return NULL;
1654
1655         len = sizeof(buf) - 1;
1656         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1657         if (ret >= 0) {
1658                 buf[len] = '\0';
1659                 pos = os_strchr(buf, '\n');
1660                 if (pos)
1661                         *pos = '\0';
1662                 ifname = os_strdup(buf);
1663         }
1664         wpa_ctrl_close(ctrl);
1665 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1666
1667         return ifname;
1668 }
1669
1670
1671 int main(int argc, char *argv[])
1672 {
1673         int interactive;
1674         int warning_displayed = 0;
1675         int c;
1676         int daemonize = 0;
1677         int ret = 0;
1678         const char *global = NULL;
1679
1680         if (os_program_init())
1681                 return -1;
1682
1683         for (;;) {
1684                 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1685                 if (c < 0)
1686                         break;
1687                 switch (c) {
1688                 case 'a':
1689                         action_file = optarg;
1690                         break;
1691                 case 'B':
1692                         daemonize = 1;
1693                         break;
1694                 case 'g':
1695                         global = optarg;
1696                         break;
1697                 case 'h':
1698                         usage();
1699                         return 0;
1700                 case 'v':
1701                         printf("%s\n", wpa_cli_version);
1702                         return 0;
1703                 case 'i':
1704                         os_free(ctrl_ifname);
1705                         ctrl_ifname = os_strdup(optarg);
1706                         break;
1707                 case 'p':
1708                         ctrl_iface_dir = optarg;
1709                         break;
1710                 case 'P':
1711                         pid_file = optarg;
1712                         break;
1713                 default:
1714                         usage();
1715                         return -1;
1716                 }
1717         }
1718
1719         interactive = (argc == optind) && (action_file == NULL);
1720
1721         if (interactive)
1722                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1723
1724         if (global) {
1725 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1726                 ctrl_conn = wpa_ctrl_open(NULL);
1727 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1728                 ctrl_conn = wpa_ctrl_open(global);
1729 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1730                 if (ctrl_conn == NULL) {
1731                         perror("Failed to connect to wpa_supplicant - "
1732                                "wpa_ctrl_open");
1733                         return -1;
1734                 }
1735         }
1736
1737         for (; !global;) {
1738                 if (ctrl_ifname == NULL)
1739                         ctrl_ifname = wpa_cli_get_default_ifname();
1740                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1741                 if (ctrl_conn) {
1742                         if (warning_displayed)
1743                                 printf("Connection established.\n");
1744                         break;
1745                 }
1746
1747                 if (!interactive) {
1748                         perror("Failed to connect to wpa_supplicant - "
1749                                "wpa_ctrl_open");
1750                         return -1;
1751                 }
1752
1753                 if (!warning_displayed) {
1754                         printf("Could not connect to wpa_supplicant - "
1755                                "re-trying\n");
1756                         warning_displayed = 1;
1757                 }
1758                 os_sleep(1, 0);
1759                 continue;
1760         }
1761
1762 #ifndef _WIN32_WCE
1763         signal(SIGINT, wpa_cli_terminate);
1764         signal(SIGTERM, wpa_cli_terminate);
1765 #endif /* _WIN32_WCE */
1766 #ifndef CONFIG_NATIVE_WINDOWS
1767         signal(SIGALRM, wpa_cli_alarm);
1768 #endif /* CONFIG_NATIVE_WINDOWS */
1769
1770         if (interactive || action_file) {
1771                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1772                         wpa_cli_attached = 1;
1773                 } else {
1774                         printf("Warning: Failed to attach to "
1775                                "wpa_supplicant.\n");
1776                         if (!interactive)
1777                                 return -1;
1778                 }
1779         }
1780
1781         if (daemonize && os_daemonize(pid_file))
1782                 return -1;
1783
1784         if (interactive)
1785                 wpa_cli_interactive();
1786         else if (action_file)
1787                 wpa_cli_action(ctrl_conn);
1788         else
1789                 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1790
1791         os_free(ctrl_ifname);
1792         wpa_cli_cleanup();
1793
1794         return ret;
1795 }
1796
1797 #else /* CONFIG_CTRL_IFACE */
1798 int main(int argc, char *argv[])
1799 {
1800         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1801         return -1;
1802 }
1803 #endif /* CONFIG_CTRL_IFACE */