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