]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
Re-initialize hostapd/wpa_supplicant git repository based on 0.6.3 release
[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;
1155
1156 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1157 cmd = os_malloc(len);
1158 if (cmd == NULL)
1159 return -1;
1160 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1161 if (res < 0 || (size_t) res >= len) {
1162 os_free(cmd);
1163 return -1;
1164 }
1165 cmd[len - 1] = '\0';
1166#ifndef _WIN32_WCE
1167 system(cmd);
1168#endif /* _WIN32_WCE */
1169 os_free(cmd);
1170
1171 return 0;
1172}
1173
1174
1175static void wpa_cli_action_process(const char *msg)
1176{
1177 const char *pos;
1178 char *copy = NULL, *id, *pos2;
1179
1180 pos = msg;
1181 if (*pos == '<') {
1182 /* skip priority */
1183 pos = os_strchr(pos, '>');
1184 if (pos)
1185 pos++;
1186 else
1187 pos = msg;
1188 }
1189
1190 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1191 int new_id = -1;
1192 os_unsetenv("WPA_ID");
1193 os_unsetenv("WPA_ID_STR");
1194 os_unsetenv("WPA_CTRL_DIR");
1195
1196 pos = os_strstr(pos, "[id=");
1197 if (pos)
1198 copy = os_strdup(pos + 4);
1199
1200 if (copy) {
1201 pos2 = id = copy;
1202 while (*pos2 && *pos2 != ' ')
1203 pos2++;
1204 *pos2++ = '\0';
1205 new_id = atoi(id);
1206 os_setenv("WPA_ID", id, 1);
1207 while (*pos2 && *pos2 != '=')
1208 pos2++;
1209 if (*pos2 == '=')
1210 pos2++;
1211 id = pos2;
1212 while (*pos2 && *pos2 != ']')
1213 pos2++;
1214 *pos2 = '\0';
1215 os_setenv("WPA_ID_STR", id, 1);
1216 os_free(copy);
1217 }
1218
1219 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1220
1221 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1222 wpa_cli_connected = 1;
1223 wpa_cli_last_id = new_id;
1224 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1225 }
1226 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1227 if (wpa_cli_connected) {
1228 wpa_cli_connected = 0;
1229 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1230 }
1231 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1232 printf("wpa_supplicant is terminating - stop monitoring\n");
1233 wpa_cli_quit = 1;
1234 }
1235}
1236
1237
1238#ifndef CONFIG_ANSI_C_EXTRA
1239static void wpa_cli_action_cb(char *msg, size_t len)
1240{
1241 wpa_cli_action_process(msg);
1242}
1243#endif /* CONFIG_ANSI_C_EXTRA */
1244
1245
1246static void wpa_cli_reconnect(void)
1247{
1248 wpa_cli_close_connection();
1249 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1250 if (ctrl_conn) {
1251 printf("Connection to wpa_supplicant re-established\n");
1252 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1253 wpa_cli_attached = 1;
1254 } else {
1255 printf("Warning: Failed to attach to "
1256 "wpa_supplicant.\n");
1257 }
1258 }
1259}
1260
1261
1262static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1263 int action_monitor)
1264{
1265 int first = 1;
1266 if (ctrl_conn == NULL) {
1267 wpa_cli_reconnect();
1268 return;
1269 }
1270 while (wpa_ctrl_pending(ctrl) > 0) {
1271 char buf[256];
1272 size_t len = sizeof(buf) - 1;
1273 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1274 buf[len] = '\0';
1275 if (action_monitor)
1276 wpa_cli_action_process(buf);
1277 else {
1278 if (in_read && first)
1279 printf("\n");
1280 first = 0;
1281 printf("%s\n", buf);
1282 }
1283 } else {
1284 printf("Could not read pending message.\n");
1285 break;
1286 }
1287 }
1288
1289 if (wpa_ctrl_pending(ctrl) < 0) {
1290 printf("Connection to wpa_supplicant lost - trying to "
1291 "reconnect\n");
1292 wpa_cli_reconnect();
1293 }
1294}
1295
1296
1297#ifdef CONFIG_READLINE
1298static char * wpa_cli_cmd_gen(const char *text, int state)
1299{
1300 static int i, len;
1301 const char *cmd;
1302
1303 if (state == 0) {
1304 i = 0;
1305 len = os_strlen(text);
1306 }
1307
1308 while ((cmd = wpa_cli_commands[i].cmd)) {
1309 i++;
1310 if (os_strncasecmp(cmd, text, len) == 0)
1311 return os_strdup(cmd);
1312 }
1313
1314 return NULL;
1315}
1316
1317
1318static char * wpa_cli_dummy_gen(const char *text, int state)
1319{
1320 return NULL;
1321}
1322
1323
1324static char ** wpa_cli_completion(const char *text, int start, int end)
1325{
1326 return rl_completion_matches(text, start == 0 ?
1327 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1328}
1329#endif /* CONFIG_READLINE */
1330
1331
1332static void wpa_cli_interactive(void)
1333{
1334#define max_args 10
1335 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1336 int argc;
1337#ifdef CONFIG_READLINE
1338 char *home, *hfile = NULL;
1339#endif /* CONFIG_READLINE */
1340
1341 printf("\nInteractive mode\n\n");
1342
1343#ifdef CONFIG_READLINE
1344 rl_attempted_completion_function = wpa_cli_completion;
1345 home = getenv("HOME");
1346 if (home) {
1347 const char *fname = ".wpa_cli_history";
1348 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1349 hfile = os_malloc(hfile_len);
1350 if (hfile) {
1351 int res;
1352 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1353 fname);
1354 if (res >= 0 && res < hfile_len) {
1355 hfile[hfile_len - 1] = '\0';
1356 read_history(hfile);
1357 stifle_history(100);
1358 }
1359 }
1360 }
1361#endif /* CONFIG_READLINE */
1362
1363 do {
1364 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1365#ifndef CONFIG_NATIVE_WINDOWS
1366 alarm(1);
1367#endif /* CONFIG_NATIVE_WINDOWS */
1368#ifdef CONFIG_READLINE
1369 cmd = readline("> ");
1370 if (cmd && *cmd) {
1371 HIST_ENTRY *h;
1372 while (next_history())
1373 ;
1374 h = previous_history();
1375 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1376 add_history(cmd);
1377 next_history();
1378 }
1379#else /* CONFIG_READLINE */
1380 printf("> ");
1381 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1382#endif /* CONFIG_READLINE */
1383#ifndef CONFIG_NATIVE_WINDOWS
1384 alarm(0);
1385#endif /* CONFIG_NATIVE_WINDOWS */
1386 if (cmd == NULL)
1387 break;
1388 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1389 pos = cmd;
1390 while (*pos != '\0') {
1391 if (*pos == '\n') {
1392 *pos = '\0';
1393 break;
1394 }
1395 pos++;
1396 }
1397 argc = 0;
1398 pos = cmd;
1399 for (;;) {
1400 while (*pos == ' ')
1401 pos++;
1402 if (*pos == '\0')
1403 break;
1404 argv[argc] = pos;
1405 argc++;
1406 if (argc == max_args)
1407 break;
1408 if (*pos == '"') {
1409 char *pos2 = os_strrchr(pos, '"');
1410 if (pos2)
1411 pos = pos2 + 1;
1412 }
1413 while (*pos != '\0' && *pos != ' ')
1414 pos++;
1415 if (*pos == ' ')
1416 *pos++ = '\0';
1417 }
1418 if (argc)
1419 wpa_request(ctrl_conn, argc, argv);
1420
1421 if (cmd != cmdbuf)
1422 os_free(cmd);
1423 } while (!wpa_cli_quit);
1424
1425#ifdef CONFIG_READLINE
1426 if (hfile) {
1427 /* Save command history, excluding lines that may contain
1428 * passwords. */
1429 HIST_ENTRY *h;
1430 history_set_pos(0);
1431 h = next_history();
1432 while (h) {
1433 char *p = h->line;
1434 while (*p == ' ' || *p == '\t')
1435 p++;
1436 if (os_strncasecmp(p, "pa", 2) == 0 ||
1437 os_strncasecmp(p, "o", 1) == 0 ||
1438 os_strncasecmp(p, "n", 1)) {
1439 h = remove_history(where_history());
1440 if (h) {
1441 os_free(h->line);
1442 os_free(h->data);
1443 os_free(h);
1444 }
1445 h = current_history();
1446 } else {
1447 h = next_history();
1448 }
1449 }
1450 write_history(hfile);
1451 os_free(hfile);
1452 }
1453#endif /* CONFIG_READLINE */
1454}
1455
1456
1457static void wpa_cli_action(struct wpa_ctrl *ctrl)
1458{
1459#ifdef CONFIG_ANSI_C_EXTRA
1460 /* TODO: ANSI C version(?) */
1461 printf("Action processing not supported in ANSI C build.\n");
1462#else /* CONFIG_ANSI_C_EXTRA */
1463 fd_set rfds;
1464 int fd, res;
1465 struct timeval tv;
1466 char buf[256]; /* note: large enough to fit in unsolicited messages */
1467 size_t len;
1468
1469 fd = wpa_ctrl_get_fd(ctrl);
1470
1471 while (!wpa_cli_quit) {
1472 FD_ZERO(&rfds);
1473 FD_SET(fd, &rfds);
1474 tv.tv_sec = 2;
1475 tv.tv_usec = 0;
1476 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1477 if (res < 0 && errno != EINTR) {
1478 perror("select");
1479 break;
1480 }
1481
1482 if (FD_ISSET(fd, &rfds))
1483 wpa_cli_recv_pending(ctrl, 0, 1);
1484 else {
1485 /* verify that connection is still working */
1486 len = sizeof(buf) - 1;
1487 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1488 wpa_cli_action_cb) < 0 ||
1489 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1490 printf("wpa_supplicant did not reply to PING "
1491 "command - exiting\n");
1492 break;
1493 }
1494 }
1495 }
1496#endif /* CONFIG_ANSI_C_EXTRA */
1497}
1498
1499
1500static void wpa_cli_cleanup(void)
1501{
1502 wpa_cli_close_connection();
1503 if (pid_file)
1504 os_daemonize_terminate(pid_file);
1505
1506 os_program_deinit();
1507}
1508
1509static void wpa_cli_terminate(int sig)
1510{
1511 wpa_cli_cleanup();
1512 exit(0);
1513}
1514
1515
1516#ifndef CONFIG_NATIVE_WINDOWS
1517static void wpa_cli_alarm(int sig)
1518{
1519 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1520 printf("Connection to wpa_supplicant lost - trying to "
1521 "reconnect\n");
1522 wpa_cli_close_connection();
1523 }
1524 if (!ctrl_conn)
1525 wpa_cli_reconnect();
1526 if (ctrl_conn)
1527 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1528 alarm(1);
1529}
1530#endif /* CONFIG_NATIVE_WINDOWS */
1531
1532
1533static char * wpa_cli_get_default_ifname(void)
1534{
1535 char *ifname = NULL;
1536
1537#ifdef CONFIG_CTRL_IFACE_UNIX
1538 struct dirent *dent;
1539 DIR *dir = opendir(ctrl_iface_dir);
1540 if (!dir)
1541 return NULL;
1542 while ((dent = readdir(dir))) {
1543#ifdef _DIRENT_HAVE_D_TYPE
1544 /*
1545 * Skip the file if it is not a socket. Also accept
1546 * DT_UNKNOWN (0) in case the C library or underlying
1547 * file system does not support d_type.
1548 */
1549 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1550 continue;
1551#endif /* _DIRENT_HAVE_D_TYPE */
1552 if (os_strcmp(dent->d_name, ".") == 0 ||
1553 os_strcmp(dent->d_name, "..") == 0)
1554 continue;
1555 printf("Selected interface '%s'\n", dent->d_name);
1556 ifname = os_strdup(dent->d_name);
1557 break;
1558 }
1559 closedir(dir);
1560#endif /* CONFIG_CTRL_IFACE_UNIX */
1561
1562#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1563 char buf[2048], *pos;
1564 size_t len;
1565 struct wpa_ctrl *ctrl;
1566 int ret;
1567
1568 ctrl = wpa_ctrl_open(NULL);
1569 if (ctrl == NULL)
1570 return NULL;
1571
1572 len = sizeof(buf) - 1;
1573 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1574 if (ret >= 0) {
1575 buf[len] = '\0';
1576 pos = os_strchr(buf, '\n');
1577 if (pos)
1578 *pos = '\0';
1579 ifname = os_strdup(buf);
1580 }
1581 wpa_ctrl_close(ctrl);
1582#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1583
1584 return ifname;
1585}
1586
1587
1588int main(int argc, char *argv[])
1589{
1590 int interactive;
1591 int warning_displayed = 0;
1592 int c;
1593 int daemonize = 0;
1594 int ret = 0;
1595 const char *global = NULL;
1596
1597 if (os_program_init())
1598 return -1;
1599
1600 for (;;) {
1601 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1602 if (c < 0)
1603 break;
1604 switch (c) {
1605 case 'a':
1606 action_file = optarg;
1607 break;
1608 case 'B':
1609 daemonize = 1;
1610 break;
1611 case 'g':
1612 global = optarg;
1613 break;
1614 case 'h':
1615 usage();
1616 return 0;
1617 case 'v':
1618 printf("%s\n", wpa_cli_version);
1619 return 0;
1620 case 'i':
1621 os_free(ctrl_ifname);
1622 ctrl_ifname = os_strdup(optarg);
1623 break;
1624 case 'p':
1625 ctrl_iface_dir = optarg;
1626 break;
1627 case 'P':
1628 pid_file = optarg;
1629 break;
1630 default:
1631 usage();
1632 return -1;
1633 }
1634 }
1635
1636 interactive = (argc == optind) && (action_file == NULL);
1637
1638 if (interactive)
1639 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1640
1641 if (global) {
1642#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1643 ctrl_conn = wpa_ctrl_open(NULL);
1644#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1645 ctrl_conn = wpa_ctrl_open(global);
1646#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1647 if (ctrl_conn == NULL) {
1648 perror("Failed to connect to wpa_supplicant - "
1649 "wpa_ctrl_open");
1650 return -1;
1651 }
1652 }
1653
1654 for (; !global;) {
1655 if (ctrl_ifname == NULL)
1656 ctrl_ifname = wpa_cli_get_default_ifname();
1657 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1658 if (ctrl_conn) {
1659 if (warning_displayed)
1660 printf("Connection established.\n");
1661 break;
1662 }
1663
1664 if (!interactive) {
1665 perror("Failed to connect to wpa_supplicant - "
1666 "wpa_ctrl_open");
1667 return -1;
1668 }
1669
1670 if (!warning_displayed) {
1671 printf("Could not connect to wpa_supplicant - "
1672 "re-trying\n");
1673 warning_displayed = 1;
1674 }
1675 os_sleep(1, 0);
1676 continue;
1677 }
1678
1679#ifndef _WIN32_WCE
1680 signal(SIGINT, wpa_cli_terminate);
1681 signal(SIGTERM, wpa_cli_terminate);
1682#endif /* _WIN32_WCE */
1683#ifndef CONFIG_NATIVE_WINDOWS
1684 signal(SIGALRM, wpa_cli_alarm);
1685#endif /* CONFIG_NATIVE_WINDOWS */
1686
1687 if (interactive || action_file) {
1688 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1689 wpa_cli_attached = 1;
1690 } else {
1691 printf("Warning: Failed to attach to "
1692 "wpa_supplicant.\n");
1693 if (!interactive)
1694 return -1;
1695 }
1696 }
1697
1698 if (daemonize && os_daemonize(pid_file))
1699 return -1;
1700
1701 if (interactive)
1702 wpa_cli_interactive();
1703 else if (action_file)
1704 wpa_cli_action(ctrl_conn);
1705 else
1706 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1707
1708 os_free(ctrl_ifname);
1709 wpa_cli_cleanup();
1710
1711 return ret;
1712}
1713
1714#else /* CONFIG_CTRL_IFACE */
1715int main(int argc, char *argv[])
1716{
1717 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1718 return -1;
1719}
1720#endif /* CONFIG_CTRL_IFACE */