]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
wpa_cli: fix readline history cleaning
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
CommitLineData
6fc6879b
JM
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
32static 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
37static 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
44static 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
89static 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"
fcc60db4
JM
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"
6fc6879b
JM
139" terminate = terminate wpa_supplicant\n"
140" quit = exit wpa_cli\n";
141
142static struct wpa_ctrl *ctrl_conn;
143static int wpa_cli_quit = 0;
144static int wpa_cli_attached = 0;
145static int wpa_cli_connected = 0;
146static int wpa_cli_last_id = 0;
147static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
148static char *ctrl_ifname = NULL;
149static const char *pid_file = NULL;
150static const char *action_file = NULL;
151
152
153static 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
171static 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
200static 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
214static void wpa_cli_msg_cb(char *msg, size_t len)
215{
216 printf("%s\n", msg);
217}
218
219
220static 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
248static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
249{
250 return _wpa_ctrl_command(ctrl, cmd, 1);
251}
252
253
254static 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
261static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
262{
263 return wpa_ctrl_command(ctrl, "PING");
264}
265
266
267static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
268{
269 return wpa_ctrl_command(ctrl, "MIB");
270}
271
272
273static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
274{
275 return wpa_ctrl_command(ctrl, "PMKSA");
276}
277
278
279static 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
286static 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
293static 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
300static 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
320static 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
345static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
346{
347 return wpa_ctrl_command(ctrl, "LOGOFF");
348}
349
350
351static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
352{
353 return wpa_ctrl_command(ctrl, "LOGON");
354}
355
356
357static 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
364static 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
385static 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
404static 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
425static 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
fcc60db4
JM
445static 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
465static 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
498static 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
6fc6879b
JM
519static 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
538static 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
571static 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
604static 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
638static 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
670static 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
703static 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
737static 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
769static 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
776static 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
797static 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
818static 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
839static 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
846static 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
867static 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
888static 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
915static 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
942static 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
949static 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
956static 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
963static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
964{
965 return wpa_ctrl_command(ctrl, "SCAN");
966}
967
968
969static 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
976static 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
996static 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
1024static 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
1031static 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
1058static 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
1065static 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
1072static 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
1103static 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
4b4a8ae5
JM
1123static 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
6fc6879b
JM
1130struct wpa_cli_cmd {
1131 const char *cmd;
1132 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1133};
1134
1135static 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 },
4b4a8ae5 1176 { "interface_list", wpa_cli_cmd_interface_list },
6fc6879b
JM
1177 { "ap_scan", wpa_cli_cmd_ap_scan },
1178 { "stkstart", wpa_cli_cmd_stkstart },
1179 { "ft_ds", wpa_cli_cmd_ft_ds },
fcc60db4
JM
1180 { "wps_pbc", wpa_cli_cmd_wps_pbc },
1181 { "wps_pin", wpa_cli_cmd_wps_pin },
1182 { "wps_reg", wpa_cli_cmd_wps_reg },
6fc6879b
JM
1183 { NULL, NULL }
1184};
1185
1186
1187static 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
1232static int str_match(const char *a, const char *b)
1233{
1234 return os_strncmp(a, b, os_strlen(b)) == 0;
1235}
1236
1237
1238static 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;
308a4ec8 1244 int ret = 0;
6fc6879b
JM
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
308a4ec8
JM
1257 if (system(cmd) < 0)
1258 ret = -1;
6fc6879b
JM
1259#endif /* _WIN32_WCE */
1260 os_free(cmd);
1261
308a4ec8 1262 return ret;
6fc6879b
JM
1263}
1264
1265
1266static 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
1330static 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
1337static 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
1353static 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
1389static 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
1409static char * wpa_cli_dummy_gen(const char *text, int state)
1410{
1411 return NULL;
1412}
1413
1414
1415static 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
1423static 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);
413653e8 1522 while ((h = current_history())) {
6fc6879b
JM
1523 char *p = h->line;
1524 while (*p == ' ' || *p == '\t')
1525 p++;
1526 if (os_strncasecmp(p, "pa", 2) == 0 ||
1527 os_strncasecmp(p, "o", 1) == 0 ||
413653e8 1528 os_strncasecmp(p, "n", 1) == 0) {
6fc6879b
JM
1529 h = remove_history(where_history());
1530 if (h) {
1531 os_free(h->line);
1532 os_free(h->data);
1533 os_free(h);
413653e8
ER
1534 } else
1535 next_history();
1536 } else
1537 next_history();
6fc6879b
JM
1538 }
1539 write_history(hfile);
1540 os_free(hfile);
1541 }
1542#endif /* CONFIG_READLINE */
1543}
1544
1545
1546static void wpa_cli_action(struct wpa_ctrl *ctrl)
1547{
1548#ifdef CONFIG_ANSI_C_EXTRA
1549 /* TODO: ANSI C version(?) */
1550 printf("Action processing not supported in ANSI C build.\n");
1551#else /* CONFIG_ANSI_C_EXTRA */
1552 fd_set rfds;
1553 int fd, res;
1554 struct timeval tv;
1555 char buf[256]; /* note: large enough to fit in unsolicited messages */
1556 size_t len;
1557
1558 fd = wpa_ctrl_get_fd(ctrl);
1559
1560 while (!wpa_cli_quit) {
1561 FD_ZERO(&rfds);
1562 FD_SET(fd, &rfds);
1563 tv.tv_sec = 2;
1564 tv.tv_usec = 0;
1565 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1566 if (res < 0 && errno != EINTR) {
1567 perror("select");
1568 break;
1569 }
1570
1571 if (FD_ISSET(fd, &rfds))
1572 wpa_cli_recv_pending(ctrl, 0, 1);
1573 else {
1574 /* verify that connection is still working */
1575 len = sizeof(buf) - 1;
1576 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1577 wpa_cli_action_cb) < 0 ||
1578 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1579 printf("wpa_supplicant did not reply to PING "
1580 "command - exiting\n");
1581 break;
1582 }
1583 }
1584 }
1585#endif /* CONFIG_ANSI_C_EXTRA */
1586}
1587
1588
1589static void wpa_cli_cleanup(void)
1590{
1591 wpa_cli_close_connection();
1592 if (pid_file)
1593 os_daemonize_terminate(pid_file);
1594
1595 os_program_deinit();
1596}
1597
1598static void wpa_cli_terminate(int sig)
1599{
1600 wpa_cli_cleanup();
1601 exit(0);
1602}
1603
1604
1605#ifndef CONFIG_NATIVE_WINDOWS
1606static void wpa_cli_alarm(int sig)
1607{
1608 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1609 printf("Connection to wpa_supplicant lost - trying to "
1610 "reconnect\n");
1611 wpa_cli_close_connection();
1612 }
1613 if (!ctrl_conn)
1614 wpa_cli_reconnect();
1615 if (ctrl_conn)
1616 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1617 alarm(1);
1618}
1619#endif /* CONFIG_NATIVE_WINDOWS */
1620
1621
1622static char * wpa_cli_get_default_ifname(void)
1623{
1624 char *ifname = NULL;
1625
1626#ifdef CONFIG_CTRL_IFACE_UNIX
1627 struct dirent *dent;
1628 DIR *dir = opendir(ctrl_iface_dir);
1629 if (!dir)
1630 return NULL;
1631 while ((dent = readdir(dir))) {
1632#ifdef _DIRENT_HAVE_D_TYPE
1633 /*
1634 * Skip the file if it is not a socket. Also accept
1635 * DT_UNKNOWN (0) in case the C library or underlying
1636 * file system does not support d_type.
1637 */
1638 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1639 continue;
1640#endif /* _DIRENT_HAVE_D_TYPE */
1641 if (os_strcmp(dent->d_name, ".") == 0 ||
1642 os_strcmp(dent->d_name, "..") == 0)
1643 continue;
1644 printf("Selected interface '%s'\n", dent->d_name);
1645 ifname = os_strdup(dent->d_name);
1646 break;
1647 }
1648 closedir(dir);
1649#endif /* CONFIG_CTRL_IFACE_UNIX */
1650
1651#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1652 char buf[2048], *pos;
1653 size_t len;
1654 struct wpa_ctrl *ctrl;
1655 int ret;
1656
1657 ctrl = wpa_ctrl_open(NULL);
1658 if (ctrl == NULL)
1659 return NULL;
1660
1661 len = sizeof(buf) - 1;
1662 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1663 if (ret >= 0) {
1664 buf[len] = '\0';
1665 pos = os_strchr(buf, '\n');
1666 if (pos)
1667 *pos = '\0';
1668 ifname = os_strdup(buf);
1669 }
1670 wpa_ctrl_close(ctrl);
1671#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1672
1673 return ifname;
1674}
1675
1676
1677int main(int argc, char *argv[])
1678{
1679 int interactive;
1680 int warning_displayed = 0;
1681 int c;
1682 int daemonize = 0;
1683 int ret = 0;
1684 const char *global = NULL;
1685
1686 if (os_program_init())
1687 return -1;
1688
1689 for (;;) {
1690 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1691 if (c < 0)
1692 break;
1693 switch (c) {
1694 case 'a':
1695 action_file = optarg;
1696 break;
1697 case 'B':
1698 daemonize = 1;
1699 break;
1700 case 'g':
1701 global = optarg;
1702 break;
1703 case 'h':
1704 usage();
1705 return 0;
1706 case 'v':
1707 printf("%s\n", wpa_cli_version);
1708 return 0;
1709 case 'i':
1710 os_free(ctrl_ifname);
1711 ctrl_ifname = os_strdup(optarg);
1712 break;
1713 case 'p':
1714 ctrl_iface_dir = optarg;
1715 break;
1716 case 'P':
1717 pid_file = optarg;
1718 break;
1719 default:
1720 usage();
1721 return -1;
1722 }
1723 }
1724
1725 interactive = (argc == optind) && (action_file == NULL);
1726
1727 if (interactive)
1728 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1729
1730 if (global) {
1731#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1732 ctrl_conn = wpa_ctrl_open(NULL);
1733#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1734 ctrl_conn = wpa_ctrl_open(global);
1735#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1736 if (ctrl_conn == NULL) {
1737 perror("Failed to connect to wpa_supplicant - "
1738 "wpa_ctrl_open");
1739 return -1;
1740 }
1741 }
1742
1743 for (; !global;) {
1744 if (ctrl_ifname == NULL)
1745 ctrl_ifname = wpa_cli_get_default_ifname();
1746 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1747 if (ctrl_conn) {
1748 if (warning_displayed)
1749 printf("Connection established.\n");
1750 break;
1751 }
1752
1753 if (!interactive) {
1754 perror("Failed to connect to wpa_supplicant - "
1755 "wpa_ctrl_open");
1756 return -1;
1757 }
1758
1759 if (!warning_displayed) {
1760 printf("Could not connect to wpa_supplicant - "
1761 "re-trying\n");
1762 warning_displayed = 1;
1763 }
1764 os_sleep(1, 0);
1765 continue;
1766 }
1767
1768#ifndef _WIN32_WCE
1769 signal(SIGINT, wpa_cli_terminate);
1770 signal(SIGTERM, wpa_cli_terminate);
1771#endif /* _WIN32_WCE */
1772#ifndef CONFIG_NATIVE_WINDOWS
1773 signal(SIGALRM, wpa_cli_alarm);
1774#endif /* CONFIG_NATIVE_WINDOWS */
1775
1776 if (interactive || action_file) {
1777 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1778 wpa_cli_attached = 1;
1779 } else {
1780 printf("Warning: Failed to attach to "
1781 "wpa_supplicant.\n");
1782 if (!interactive)
1783 return -1;
1784 }
1785 }
1786
1787 if (daemonize && os_daemonize(pid_file))
1788 return -1;
1789
1790 if (interactive)
1791 wpa_cli_interactive();
1792 else if (action_file)
1793 wpa_cli_action(ctrl_conn);
1794 else
1795 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1796
1797 os_free(ctrl_ifname);
1798 wpa_cli_cleanup();
1799
1800 return ret;
1801}
1802
1803#else /* CONFIG_CTRL_IFACE */
1804int main(int argc, char *argv[])
1805{
1806 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1807 return -1;
1808}
1809#endif /* CONFIG_CTRL_IFACE */