]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
MFP: Add SA Query Request processing in AP mode
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
CommitLineData
6fc6879b
JM
1/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
dff0f701 3 * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
6fc6879b
JM
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 */
cbf78558
JM
26#ifdef CONFIG_WPA_CLI_FORK
27#include <sys/wait.h>
28#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b 29
90973fb2 30#include "common/wpa_ctrl.h"
6fc6879b 31#include "common.h"
90973fb2 32#include "common/version.h"
6fc6879b
JM
33
34
35static const char *wpa_cli_version =
36"wpa_cli v" VERSION_STR "\n"
dff0f701 37"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
6fc6879b
JM
38
39
40static const char *wpa_cli_license =
41"This program is free software. You can distribute it and/or modify it\n"
42"under the terms of the GNU General Public License version 2.\n"
43"\n"
44"Alternatively, this software may be distributed under the terms of the\n"
45"BSD license. See README and COPYING for more details.\n";
46
47static const char *wpa_cli_full_license =
48"This program is free software; you can redistribute it and/or modify\n"
49"it under the terms of the GNU General Public License version 2 as\n"
50"published by the Free Software Foundation.\n"
51"\n"
52"This program is distributed in the hope that it will be useful,\n"
53"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
54"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
55"GNU General Public License for more details.\n"
56"\n"
57"You should have received a copy of the GNU General Public License\n"
58"along with this program; if not, write to the Free Software\n"
59"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
60"\n"
61"Alternatively, this software may be distributed under the terms of the\n"
62"BSD license.\n"
63"\n"
64"Redistribution and use in source and binary forms, with or without\n"
65"modification, are permitted provided that the following conditions are\n"
66"met:\n"
67"\n"
68"1. Redistributions of source code must retain the above copyright\n"
69" notice, this list of conditions and the following disclaimer.\n"
70"\n"
71"2. Redistributions in binary form must reproduce the above copyright\n"
72" notice, this list of conditions and the following disclaimer in the\n"
73" documentation and/or other materials provided with the distribution.\n"
74"\n"
75"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
76" names of its contributors may be used to endorse or promote products\n"
77" derived from this software without specific prior written permission.\n"
78"\n"
79"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
80"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
81"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
82"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
83"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
84"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
85"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
86"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
87"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
88"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
89"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
90"\n";
91
6fc6879b 92static struct wpa_ctrl *ctrl_conn;
4a3ade4e 93static struct wpa_ctrl *mon_conn;
cbf78558
JM
94#ifdef CONFIG_WPA_CLI_FORK
95static pid_t mon_pid = 0;
96#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
97static int wpa_cli_quit = 0;
98static int wpa_cli_attached = 0;
99static int wpa_cli_connected = 0;
100static int wpa_cli_last_id = 0;
101static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
102static char *ctrl_ifname = NULL;
103static const char *pid_file = NULL;
104static const char *action_file = NULL;
1cc84c1c 105static int ping_interval = 5;
4a3ade4e 106static int interactive = 0;
6fc6879b
JM
107
108
dfa141b1
ER
109static void print_help();
110
111
6fc6879b
JM
112static void usage(void)
113{
114 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
115 "[-a<action file>] \\\n"
1cc84c1c
JM
116 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
117 "[command..]\n"
6fc6879b
JM
118 " -h = help (show this usage text)\n"
119 " -v = shown version information\n"
120 " -a = run in daemon mode executing the action file based on "
121 "events from\n"
122 " wpa_supplicant\n"
123 " -B = run a daemon in the background\n"
124 " default path: /var/run/wpa_supplicant\n"
dfa141b1
ER
125 " default interface: first interface found in socket path\n");
126 print_help();
6fc6879b
JM
127}
128
129
cbf78558 130#ifdef CONFIG_WPA_CLI_FORK
dd63f314
JM
131static int in_query = 0;
132
133static void wpa_cli_monitor_sig(int sig)
134{
135 if (sig == SIGUSR1)
136 in_query = 1;
137 else if (sig == SIGUSR2)
138 in_query = 0;
139}
140
cbf78558
JM
141static void wpa_cli_monitor(void)
142{
143 char buf[256];
144 size_t len = sizeof(buf) - 1;
145 struct timeval tv;
146 fd_set rfds;
147
dd63f314
JM
148 signal(SIGUSR1, wpa_cli_monitor_sig);
149 signal(SIGUSR2, wpa_cli_monitor_sig);
150
cbf78558
JM
151 while (mon_conn) {
152 int s = wpa_ctrl_get_fd(mon_conn);
153 tv.tv_sec = 5;
154 tv.tv_usec = 0;
155 FD_ZERO(&rfds);
156 FD_SET(s, &rfds);
157 if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) {
dd63f314
JM
158 if (errno == EINTR)
159 continue;
cbf78558
JM
160 perror("select");
161 break;
162 }
163 if (mon_conn == NULL)
164 break;
165 if (FD_ISSET(s, &rfds)) {
166 len = sizeof(buf) - 1;
167 int res = wpa_ctrl_recv(mon_conn, buf, &len);
168 if (res < 0) {
169 perror("wpa_ctrl_recv");
170 break;
171 }
172 buf[len] = '\0';
dd63f314
JM
173 if (in_query)
174 printf("\r");
cbf78558 175 printf("%s\n", buf);
dd63f314 176 kill(getppid(), SIGUSR1);
cbf78558
JM
177 }
178 }
179}
180#endif /* CONFIG_WPA_CLI_FORK */
181
182
4a3ade4e 183static int wpa_cli_open_connection(const char *ifname, int attach)
6fc6879b
JM
184{
185#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
186 ctrl_conn = wpa_ctrl_open(ifname);
4a3ade4e
JM
187 if (ctrl_conn == NULL)
188 return -1;
189
190 if (attach && interactive)
191 mon_conn = wpa_ctrl_open(ifname);
192 else
193 mon_conn = NULL;
6fc6879b
JM
194#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
195 char *cfile;
196 int flen, res;
197
198 if (ifname == NULL)
4a3ade4e 199 return -1;
6fc6879b
JM
200
201 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
202 cfile = os_malloc(flen);
203 if (cfile == NULL)
4a3ade4e 204 return -1L;
6fc6879b
JM
205 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
206 if (res < 0 || res >= flen) {
207 os_free(cfile);
4a3ade4e 208 return -1;
6fc6879b
JM
209 }
210
211 ctrl_conn = wpa_ctrl_open(cfile);
4a3ade4e
JM
212 if (ctrl_conn == NULL) {
213 os_free(cfile);
214 return -1;
215 }
216
217 if (attach && interactive)
218 mon_conn = wpa_ctrl_open(cfile);
219 else
220 mon_conn = NULL;
6fc6879b 221 os_free(cfile);
6fc6879b 222#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
4a3ade4e
JM
223
224 if (mon_conn) {
225 if (wpa_ctrl_attach(mon_conn) == 0) {
226 wpa_cli_attached = 1;
227 } else {
228 printf("Warning: Failed to attach to "
229 "wpa_supplicant.\n");
230 return -1;
231 }
cbf78558
JM
232
233#ifdef CONFIG_WPA_CLI_FORK
234 {
235 pid_t p = fork();
236 if (p < 0) {
237 perror("fork");
238 return -1;
239 }
240 if (p == 0) {
241 wpa_cli_monitor();
242 exit(0);
243 } else
244 mon_pid = p;
245 }
246#endif /* CONFIG_WPA_CLI_FORK */
4a3ade4e
JM
247 }
248
249 return 0;
6fc6879b
JM
250}
251
252
253static void wpa_cli_close_connection(void)
254{
255 if (ctrl_conn == NULL)
256 return;
257
037f83eb
JM
258#ifdef CONFIG_WPA_CLI_FORK
259 if (mon_pid) {
260 int status;
261 kill(mon_pid, SIGPIPE);
262 wait(&status);
263 mon_pid = 0;
264 }
265#endif /* CONFIG_WPA_CLI_FORK */
266
6fc6879b 267 if (wpa_cli_attached) {
4a3ade4e 268 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
6fc6879b
JM
269 wpa_cli_attached = 0;
270 }
271 wpa_ctrl_close(ctrl_conn);
272 ctrl_conn = NULL;
4a3ade4e
JM
273 if (mon_conn) {
274 wpa_ctrl_close(mon_conn);
275 mon_conn = NULL;
276 }
6fc6879b
JM
277}
278
279
280static void wpa_cli_msg_cb(char *msg, size_t len)
281{
282 printf("%s\n", msg);
283}
284
285
286static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
287{
288 char buf[2048];
289 size_t len;
290 int ret;
291
292 if (ctrl_conn == NULL) {
293 printf("Not connected to wpa_supplicant - command dropped.\n");
294 return -1;
295 }
296 len = sizeof(buf) - 1;
297 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
298 wpa_cli_msg_cb);
299 if (ret == -2) {
300 printf("'%s' command timed out.\n", cmd);
301 return -2;
302 } else if (ret < 0) {
303 printf("'%s' command failed.\n", cmd);
304 return -1;
305 }
306 if (print) {
307 buf[len] = '\0';
308 printf("%s", buf);
309 }
310 return 0;
311}
312
313
314static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
315{
316 return _wpa_ctrl_command(ctrl, cmd, 1);
317}
318
319
320static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
321{
322 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
323 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
324}
325
326
327static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
328{
329 return wpa_ctrl_command(ctrl, "PING");
330}
331
332
333static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
334{
335 return wpa_ctrl_command(ctrl, "MIB");
336}
337
338
339static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
340{
341 return wpa_ctrl_command(ctrl, "PMKSA");
342}
343
344
345static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
346{
dfa141b1 347 print_help();
6fc6879b
JM
348 return 0;
349}
350
351
352static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
353{
354 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
355 return 0;
356}
357
358
359static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
360{
361 wpa_cli_quit = 1;
362 return 0;
363}
364
365
366static void wpa_cli_show_variables(void)
367{
368 printf("set variables:\n"
369 " EAPOL::heldPeriod (EAPOL state machine held period, "
370 "in seconds)\n"
371 " EAPOL::authPeriod (EAPOL state machine authentication "
372 "period, in seconds)\n"
373 " EAPOL::startPeriod (EAPOL state machine start period, in "
374 "seconds)\n"
375 " EAPOL::maxStart (EAPOL state machine maximum start "
376 "attempts)\n");
377 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
378 "seconds)\n"
379 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
380 " threshold\n\tpercentage)\n"
381 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
382 "security\n\tassociation in seconds)\n");
383}
384
385
386static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
387{
388 char cmd[256];
389 int res;
390
391 if (argc == 0) {
392 wpa_cli_show_variables();
393 return 0;
394 }
395
396 if (argc != 2) {
397 printf("Invalid SET command: needs two arguments (variable "
398 "name and value)\n");
399 return -1;
400 }
401
402 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
403 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
404 printf("Too long SET command.\n");
405 return -1;
406 }
407 return wpa_ctrl_command(ctrl, cmd);
408}
409
410
411static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
412{
413 return wpa_ctrl_command(ctrl, "LOGOFF");
414}
415
416
417static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
418{
419 return wpa_ctrl_command(ctrl, "LOGON");
420}
421
422
423static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
424 char *argv[])
425{
426 return wpa_ctrl_command(ctrl, "REASSOCIATE");
427}
428
429
430static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
431 char *argv[])
432{
433 char cmd[256];
434 int res;
435
436 if (argc != 1) {
437 printf("Invalid PREAUTH command: needs one argument "
438 "(BSSID)\n");
439 return -1;
440 }
441
442 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
443 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
444 printf("Too long PREAUTH command.\n");
445 return -1;
446 }
447 return wpa_ctrl_command(ctrl, cmd);
448}
449
450
451static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
452{
453 char cmd[256];
454 int res;
455
456 if (argc != 1) {
457 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
458 "value)\n");
459 return -1;
460 }
461 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
462 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
463 printf("Too long AP_SCAN command.\n");
464 return -1;
465 }
466 return wpa_ctrl_command(ctrl, cmd);
467}
468
469
470static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
471 char *argv[])
472{
473 char cmd[256];
474 int res;
475
476 if (argc != 1) {
477 printf("Invalid STKSTART command: needs one argument "
478 "(Peer STA MAC address)\n");
479 return -1;
480 }
481
482 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
483 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
484 printf("Too long STKSTART command.\n");
485 return -1;
486 }
487 return wpa_ctrl_command(ctrl, cmd);
488}
489
490
491static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
492{
493 char cmd[256];
494 int res;
495
496 if (argc != 1) {
497 printf("Invalid FT_DS command: needs one argument "
498 "(Target AP MAC address)\n");
499 return -1;
500 }
501
502 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
503 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
504 printf("Too long FT_DS command.\n");
505 return -1;
506 }
507 return wpa_ctrl_command(ctrl, cmd);
508}
509
510
fcc60db4
JM
511static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 char cmd[256];
514 int res;
515
516 if (argc == 0) {
517 /* Any BSSID */
518 return wpa_ctrl_command(ctrl, "WPS_PBC");
519 }
520
521 /* Specific BSSID */
522 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
523 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
524 printf("Too long WPS_PBC command.\n");
525 return -1;
526 }
527 return wpa_ctrl_command(ctrl, cmd);
528}
529
530
531static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
532{
533 char cmd[256];
534 int res;
535
536 if (argc == 0) {
537 printf("Invalid WPS_PIN command: need one or two arguments:\n"
538 "- BSSID: use 'any' to select any\n"
539 "- PIN: optional, used only with devices that have no "
540 "display\n");
541 return -1;
542 }
543
544 if (argc == 1) {
545 /* Use dynamically generated PIN (returned as reply) */
546 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
547 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
548 printf("Too long WPS_PIN command.\n");
549 return -1;
550 }
551 return wpa_ctrl_command(ctrl, cmd);
552 }
553
554 /* Use hardcoded PIN from a label */
555 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
556 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
557 printf("Too long WPS_PIN command.\n");
558 return -1;
559 }
560 return wpa_ctrl_command(ctrl, cmd);
561}
562
563
116f7bb0 564#ifdef CONFIG_WPS_OOB
46bdb83a
MH
565static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
566{
567 char cmd[256];
568 int res;
569
e1ee6b60
MH
570 if (argc != 3 && argc != 4) {
571 printf("Invalid WPS_OOB command: need three or four "
572 "arguments:\n"
573 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
574 "- PATH: path of OOB device like '/mnt'\n"
575 "- METHOD: OOB method 'pin-e' or 'pin-r', "
576 "'cred'\n"
577 "- DEV_NAME: (only for NFC) device name like "
578 "'pn531'\n");
46bdb83a
MH
579 return -1;
580 }
581
e1ee6b60
MH
582 if (argc == 3)
583 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
584 argv[0], argv[1], argv[2]);
585 else
586 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
587 argv[0], argv[1], argv[2], argv[3]);
46bdb83a
MH
588 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
589 printf("Too long WPS_OOB command.\n");
590 return -1;
591 }
592 return wpa_ctrl_command(ctrl, cmd);
593}
116f7bb0 594#endif /* CONFIG_WPS_OOB */
46bdb83a
MH
595
596
fcc60db4
JM
597static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
598{
599 char cmd[256];
600 int res;
601
52eb293d
JM
602 if (argc == 2)
603 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
604 argv[0], argv[1]);
605 else if (argc == 6) {
606 char ssid_hex[2 * 32 + 1];
607 char key_hex[2 * 64 + 1];
608 int i;
609
610 ssid_hex[0] = '\0';
611 for (i = 0; i < 32; i++) {
612 if (argv[2][i] == '\0')
613 break;
614 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
615 }
616
617 key_hex[0] = '\0';
618 for (i = 0; i < 64; i++) {
619 if (argv[5][i] == '\0')
620 break;
621 os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
622 }
623
624 res = os_snprintf(cmd, sizeof(cmd),
625 "WPS_REG %s %s %s %s %s %s",
626 argv[0], argv[1], ssid_hex, argv[3], argv[4],
627 key_hex);
628 } else {
fcc60db4
JM
629 printf("Invalid WPS_REG command: need two arguments:\n"
630 "- BSSID: use 'any' to select any\n"
631 "- AP PIN\n");
52eb293d
JM
632 printf("Alternatively, six arguments can be used to "
633 "reconfigure the AP:\n"
634 "- BSSID: use 'any' to select any\n"
635 "- AP PIN\n"
636 "- new SSID\n"
637 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
638 "- new encr (NONE, WEP, TKIP, CCMP)\n"
639 "- new key\n");
fcc60db4
JM
640 return -1;
641 }
642
fcc60db4
JM
643 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
644 printf("Too long WPS_REG command.\n");
645 return -1;
646 }
647 return wpa_ctrl_command(ctrl, cmd);
648}
649
650
e9bcfebf
JM
651static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
652 char *argv[])
653{
654 return wpa_ctrl_command(ctrl, "WPS_ER_START");
655
656}
657
658
659static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
660 char *argv[])
661{
662 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
663
664}
665
666
72df2f5f
JM
667static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
668 char *argv[])
669{
670 char cmd[256];
671 int res;
672
673 if (argc != 2) {
674 printf("Invalid WPS_ER_PIN command: need two arguments:\n"
675 "- UUID: use 'any' to select any\n"
676 "- PIN: Enrollee PIN\n");
677 return -1;
678 }
679
680 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
681 argv[0], argv[1]);
682 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
683 printf("Too long WPS_ER_PIN command.\n");
684 return -1;
685 }
686 return wpa_ctrl_command(ctrl, cmd);
687}
688
689
564cd7fa
JM
690static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
691 char *argv[])
692{
693 char cmd[256];
694 int res;
695
696 if (argc != 1) {
697 printf("Invalid WPS_ER_PBC command: need one argument:\n"
698 "- UUID: Specify the Enrollee\n");
699 return -1;
700 }
701
702 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
703 argv[0]);
704 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
705 printf("Too long WPS_ER_PBC command.\n");
706 return -1;
707 }
708 return wpa_ctrl_command(ctrl, cmd);
709}
710
711
e64dcfd5
JM
712static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
713 char *argv[])
714{
715 char cmd[256];
716 int res;
717
718 if (argc != 2) {
719 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
720 "- UUID: specify which AP to use\n"
721 "- PIN: AP PIN\n");
722 return -1;
723 }
724
725 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
726 argv[0], argv[1]);
727 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
728 printf("Too long WPS_ER_LEARN command.\n");
729 return -1;
730 }
731 return wpa_ctrl_command(ctrl, cmd);
732}
733
734
11ef8d35
JM
735static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
736{
737 char cmd[256];
738 int res;
739
740 if (argc != 1) {
741 printf("Invalid IBSS_RSN command: needs one argument "
742 "(Peer STA MAC address)\n");
743 return -1;
744 }
745
746 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
747 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
748 printf("Too long IBSS_RSN command.\n");
749 return -1;
750 }
751 return wpa_ctrl_command(ctrl, cmd);
752}
753
754
6fc6879b
JM
755static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
757 char cmd[256];
758 int res;
759
760 if (argc != 1) {
761 printf("Invalid LEVEL command: needs one argument (debug "
762 "level)\n");
763 return -1;
764 }
765 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
766 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
767 printf("Too long LEVEL command.\n");
768 return -1;
769 }
770 return wpa_ctrl_command(ctrl, cmd);
771}
772
773
774static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
775{
776 char cmd[256], *pos, *end;
777 int i, ret;
778
779 if (argc < 2) {
780 printf("Invalid IDENTITY command: needs two arguments "
781 "(network id and identity)\n");
782 return -1;
783 }
784
785 end = cmd + sizeof(cmd);
786 pos = cmd;
787 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
788 argv[0], argv[1]);
789 if (ret < 0 || ret >= end - pos) {
790 printf("Too long IDENTITY command.\n");
791 return -1;
792 }
793 pos += ret;
794 for (i = 2; i < argc; i++) {
795 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
796 if (ret < 0 || ret >= end - pos) {
797 printf("Too long IDENTITY command.\n");
798 return -1;
799 }
800 pos += ret;
801 }
802
803 return wpa_ctrl_command(ctrl, cmd);
804}
805
806
807static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
808{
809 char cmd[256], *pos, *end;
810 int i, ret;
811
812 if (argc < 2) {
813 printf("Invalid PASSWORD command: needs two arguments "
814 "(network id and password)\n");
815 return -1;
816 }
817
818 end = cmd + sizeof(cmd);
819 pos = cmd;
820 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
821 argv[0], argv[1]);
822 if (ret < 0 || ret >= end - pos) {
823 printf("Too long PASSWORD command.\n");
824 return -1;
825 }
826 pos += ret;
827 for (i = 2; i < argc; i++) {
828 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
829 if (ret < 0 || ret >= end - pos) {
830 printf("Too long PASSWORD command.\n");
831 return -1;
832 }
833 pos += ret;
834 }
835
836 return wpa_ctrl_command(ctrl, cmd);
837}
838
839
840static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
841 char *argv[])
842{
843 char cmd[256], *pos, *end;
844 int i, ret;
845
846 if (argc < 2) {
847 printf("Invalid NEW_PASSWORD command: needs two arguments "
848 "(network id and password)\n");
849 return -1;
850 }
851
852 end = cmd + sizeof(cmd);
853 pos = cmd;
854 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
855 argv[0], argv[1]);
856 if (ret < 0 || ret >= end - pos) {
857 printf("Too long NEW_PASSWORD command.\n");
858 return -1;
859 }
860 pos += ret;
861 for (i = 2; i < argc; i++) {
862 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
863 if (ret < 0 || ret >= end - pos) {
864 printf("Too long NEW_PASSWORD command.\n");
865 return -1;
866 }
867 pos += ret;
868 }
869
870 return wpa_ctrl_command(ctrl, cmd);
871}
872
873
874static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
875{
876 char cmd[256], *pos, *end;
877 int i, ret;
878
879 if (argc < 2) {
880 printf("Invalid PIN command: needs two arguments "
881 "(network id and pin)\n");
882 return -1;
883 }
884
885 end = cmd + sizeof(cmd);
886 pos = cmd;
887 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
888 argv[0], argv[1]);
889 if (ret < 0 || ret >= end - pos) {
890 printf("Too long PIN command.\n");
891 return -1;
892 }
893 pos += ret;
894 for (i = 2; i < argc; i++) {
895 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
896 if (ret < 0 || ret >= end - pos) {
897 printf("Too long PIN command.\n");
898 return -1;
899 }
900 pos += ret;
901 }
902 return wpa_ctrl_command(ctrl, cmd);
903}
904
905
906static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
907{
908 char cmd[256], *pos, *end;
909 int i, ret;
910
911 if (argc < 2) {
912 printf("Invalid OTP command: needs two arguments (network "
913 "id and password)\n");
914 return -1;
915 }
916
917 end = cmd + sizeof(cmd);
918 pos = cmd;
919 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
920 argv[0], argv[1]);
921 if (ret < 0 || ret >= end - pos) {
922 printf("Too long OTP command.\n");
923 return -1;
924 }
925 pos += ret;
926 for (i = 2; i < argc; i++) {
927 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
928 if (ret < 0 || ret >= end - pos) {
929 printf("Too long OTP command.\n");
930 return -1;
931 }
932 pos += ret;
933 }
934
935 return wpa_ctrl_command(ctrl, cmd);
936}
937
938
939static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
940 char *argv[])
941{
942 char cmd[256], *pos, *end;
943 int i, ret;
944
945 if (argc < 2) {
946 printf("Invalid PASSPHRASE command: needs two arguments "
947 "(network id and passphrase)\n");
948 return -1;
949 }
950
951 end = cmd + sizeof(cmd);
952 pos = cmd;
953 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
954 argv[0], argv[1]);
955 if (ret < 0 || ret >= end - pos) {
956 printf("Too long PASSPHRASE command.\n");
957 return -1;
958 }
959 pos += ret;
960 for (i = 2; i < argc; i++) {
961 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
962 if (ret < 0 || ret >= end - pos) {
963 printf("Too long PASSPHRASE command.\n");
964 return -1;
965 }
966 pos += ret;
967 }
968
969 return wpa_ctrl_command(ctrl, cmd);
970}
971
972
973static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
974{
975 char cmd[256], *pos, *end;
976 int i, ret;
977
978 if (argc < 2) {
979 printf("Invalid BSSID command: needs two arguments (network "
980 "id and BSSID)\n");
981 return -1;
982 }
983
984 end = cmd + sizeof(cmd);
985 pos = cmd;
986 ret = os_snprintf(pos, end - pos, "BSSID");
987 if (ret < 0 || ret >= end - pos) {
988 printf("Too long BSSID command.\n");
989 return -1;
990 }
991 pos += ret;
992 for (i = 0; i < argc; i++) {
993 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
994 if (ret < 0 || ret >= end - pos) {
995 printf("Too long BSSID command.\n");
996 return -1;
997 }
998 pos += ret;
999 }
1000
1001 return wpa_ctrl_command(ctrl, cmd);
1002}
1003
1004
1005static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1006 char *argv[])
1007{
1008 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1009}
1010
1011
1012static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1013 char *argv[])
1014{
1015 char cmd[32];
1016 int res;
1017
1018 if (argc < 1) {
1019 printf("Invalid SELECT_NETWORK command: needs one argument "
1020 "(network id)\n");
1021 return -1;
1022 }
1023
1024 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1025 if (res < 0 || (size_t) res >= sizeof(cmd))
1026 return -1;
1027 cmd[sizeof(cmd) - 1] = '\0';
1028
1029 return wpa_ctrl_command(ctrl, cmd);
1030}
1031
1032
1033static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1034 char *argv[])
1035{
1036 char cmd[32];
1037 int res;
1038
1039 if (argc < 1) {
1040 printf("Invalid ENABLE_NETWORK command: needs one argument "
1041 "(network id)\n");
1042 return -1;
1043 }
1044
1045 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1046 if (res < 0 || (size_t) res >= sizeof(cmd))
1047 return -1;
1048 cmd[sizeof(cmd) - 1] = '\0';
1049
1050 return wpa_ctrl_command(ctrl, cmd);
1051}
1052
1053
1054static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1055 char *argv[])
1056{
1057 char cmd[32];
1058 int res;
1059
1060 if (argc < 1) {
1061 printf("Invalid DISABLE_NETWORK command: needs one argument "
1062 "(network id)\n");
1063 return -1;
1064 }
1065
1066 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1067 if (res < 0 || (size_t) res >= sizeof(cmd))
1068 return -1;
1069 cmd[sizeof(cmd) - 1] = '\0';
1070
1071 return wpa_ctrl_command(ctrl, cmd);
1072}
1073
1074
1075static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1076 char *argv[])
1077{
1078 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1079}
1080
1081
1082static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1083 char *argv[])
1084{
1085 char cmd[32];
1086 int res;
1087
1088 if (argc < 1) {
1089 printf("Invalid REMOVE_NETWORK command: needs one argument "
1090 "(network id)\n");
1091 return -1;
1092 }
1093
1094 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1095 if (res < 0 || (size_t) res >= sizeof(cmd))
1096 return -1;
1097 cmd[sizeof(cmd) - 1] = '\0';
1098
1099 return wpa_ctrl_command(ctrl, cmd);
1100}
1101
1102
1103static void wpa_cli_show_network_variables(void)
1104{
1105 printf("set_network variables:\n"
1106 " ssid (network name, SSID)\n"
1107 " psk (WPA passphrase or pre-shared key)\n"
1108 " key_mgmt (key management protocol)\n"
1109 " identity (EAP identity)\n"
1110 " password (EAP password)\n"
1111 " ...\n"
1112 "\n"
1113 "Note: Values are entered in the same format as the "
1114 "configuration file is using,\n"
1115 "i.e., strings values need to be inside double quotation "
1116 "marks.\n"
1117 "For example: set_network 1 ssid \"network name\"\n"
1118 "\n"
1119 "Please see wpa_supplicant.conf documentation for full list "
1120 "of\navailable variables.\n");
1121}
1122
1123
1124static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1125 char *argv[])
1126{
1127 char cmd[256];
1128 int res;
1129
1130 if (argc == 0) {
1131 wpa_cli_show_network_variables();
1132 return 0;
1133 }
1134
1135 if (argc != 3) {
1136 printf("Invalid SET_NETWORK command: needs three arguments\n"
1137 "(network id, variable name, and value)\n");
1138 return -1;
1139 }
1140
1141 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1142 argv[0], argv[1], argv[2]);
1143 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1144 printf("Too long SET_NETWORK command.\n");
1145 return -1;
1146 }
1147 return wpa_ctrl_command(ctrl, cmd);
1148}
1149
1150
1151static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1152 char *argv[])
1153{
1154 char cmd[256];
1155 int res;
1156
1157 if (argc == 0) {
1158 wpa_cli_show_network_variables();
1159 return 0;
1160 }
1161
1162 if (argc != 2) {
1163 printf("Invalid GET_NETWORK command: needs two arguments\n"
1164 "(network id and variable name)\n");
1165 return -1;
1166 }
1167
1168 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1169 argv[0], argv[1]);
1170 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1171 printf("Too long GET_NETWORK command.\n");
1172 return -1;
1173 }
1174 return wpa_ctrl_command(ctrl, cmd);
1175}
1176
1177
1178static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1179 char *argv[])
1180{
1181 return wpa_ctrl_command(ctrl, "DISCONNECT");
1182}
1183
1184
1185static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1186 char *argv[])
1187{
1188 return wpa_ctrl_command(ctrl, "RECONNECT");
1189}
1190
1191
1192static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1193 char *argv[])
1194{
1195 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1196}
1197
1198
1199static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1200{
1201 return wpa_ctrl_command(ctrl, "SCAN");
1202}
1203
1204
1205static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1206 char *argv[])
1207{
1208 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1209}
1210
1211
1212static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1213{
1214 char cmd[64];
1215 int res;
1216
1217 if (argc != 1) {
1218 printf("Invalid BSS command: need one argument (index or "
1219 "BSSID)\n");
1220 return -1;
1221 }
1222
1223 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1224 if (res < 0 || (size_t) res >= sizeof(cmd))
1225 return -1;
1226 cmd[sizeof(cmd) - 1] = '\0';
1227
1228 return wpa_ctrl_command(ctrl, cmd);
1229}
1230
1231
1232static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1233 char *argv[])
1234{
1235 char cmd[64];
1236 int res;
1237
1238 if (argc < 1 || argc > 2) {
1239 printf("Invalid GET_CAPABILITY command: need either one or "
1240 "two arguments\n");
1241 return -1;
1242 }
1243
1244 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1245 printf("Invalid GET_CAPABILITY command: second argument, "
1246 "if any, must be 'strict'\n");
1247 return -1;
1248 }
1249
1250 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1251 (argc == 2) ? " strict" : "");
1252 if (res < 0 || (size_t) res >= sizeof(cmd))
1253 return -1;
1254 cmd[sizeof(cmd) - 1] = '\0';
1255
1256 return wpa_ctrl_command(ctrl, cmd);
1257}
1258
1259
1260static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1261{
1262 printf("Available interfaces:\n");
1263 return wpa_ctrl_command(ctrl, "INTERFACES");
1264}
1265
1266
1267static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1268{
1269 if (argc < 1) {
1270 wpa_cli_list_interfaces(ctrl);
1271 return 0;
1272 }
1273
1274 wpa_cli_close_connection();
1275 os_free(ctrl_ifname);
1276 ctrl_ifname = os_strdup(argv[0]);
1277
4a3ade4e 1278 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
6fc6879b 1279 printf("Connected to interface '%s.\n", ctrl_ifname);
6fc6879b
JM
1280 } else {
1281 printf("Could not connect to interface '%s' - re-trying\n",
1282 ctrl_ifname);
1283 }
1284 return 0;
1285}
1286
1287
1288static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1289 char *argv[])
1290{
1291 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1292}
1293
1294
1295static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1296 char *argv[])
1297{
1298 return wpa_ctrl_command(ctrl, "TERMINATE");
1299}
1300
1301
1302static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1303 char *argv[])
1304{
1305 char cmd[256];
1306 int res;
1307
1308 if (argc < 1) {
1309 printf("Invalid INTERFACE_ADD command: needs at least one "
1310 "argument (interface name)\n"
1311 "All arguments: ifname confname driver ctrl_interface "
1312 "driver_param bridge_name\n");
1313 return -1;
1314 }
1315
1316 /*
1317 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1318 * <driver_param>TAB<bridge_name>
1319 */
1320 res = os_snprintf(cmd, sizeof(cmd),
1321 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1322 argv[0],
1323 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1324 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1325 argc > 5 ? argv[5] : "");
1326 if (res < 0 || (size_t) res >= sizeof(cmd))
1327 return -1;
1328 cmd[sizeof(cmd) - 1] = '\0';
1329 return wpa_ctrl_command(ctrl, cmd);
1330}
1331
1332
1333static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1334 char *argv[])
1335{
1336 char cmd[128];
1337 int res;
1338
1339 if (argc != 1) {
1340 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1341 "(interface name)\n");
1342 return -1;
1343 }
1344
1345 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1346 if (res < 0 || (size_t) res >= sizeof(cmd))
1347 return -1;
1348 cmd[sizeof(cmd) - 1] = '\0';
1349 return wpa_ctrl_command(ctrl, cmd);
1350}
1351
1352
4b4a8ae5
JM
1353static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1354 char *argv[])
1355{
1356 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1357}
1358
1359
e653b622
JM
1360#ifdef CONFIG_AP
1361static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1362{
1363 char buf[64];
1364 if (argc != 1) {
1365 printf("Invalid 'sta' command - exactly one argument, STA "
1366 "address, is required.\n");
1367 return -1;
1368 }
e824cc46 1369 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
e653b622
JM
1370 return wpa_ctrl_command(ctrl, buf);
1371}
1372
1373
1374static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1375 char *addr, size_t addr_len)
1376{
1377 char buf[4096], *pos;
1378 size_t len;
1379 int ret;
1380
1381 if (ctrl_conn == NULL) {
1382 printf("Not connected to hostapd - command dropped.\n");
1383 return -1;
1384 }
1385 len = sizeof(buf) - 1;
1386 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1387 wpa_cli_msg_cb);
1388 if (ret == -2) {
1389 printf("'%s' command timed out.\n", cmd);
1390 return -2;
1391 } else if (ret < 0) {
1392 printf("'%s' command failed.\n", cmd);
1393 return -1;
1394 }
1395
1396 buf[len] = '\0';
1397 if (memcmp(buf, "FAIL", 4) == 0)
1398 return -1;
1399 printf("%s", buf);
1400
1401 pos = buf;
1402 while (*pos != '\0' && *pos != '\n')
1403 pos++;
1404 *pos = '\0';
1405 os_strlcpy(addr, buf, addr_len);
1406 return 0;
1407}
1408
1409
1410static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1411{
1412 char addr[32], cmd[64];
1413
1414 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1415 return 0;
1416 do {
e824cc46 1417 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
e653b622
JM
1418 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1419
1420 return -1;
1421}
1422#endif /* CONFIG_AP */
1423
1424
207ef3fb
JM
1425static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1426{
1427 return wpa_ctrl_command(ctrl, "SUSPEND");
1428}
1429
1430
1431static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1432{
1433 return wpa_ctrl_command(ctrl, "RESUME");
1434}
1435
1436
40fd868c
ER
1437enum wpa_cli_cmd_flags {
1438 cli_cmd_flag_none = 0x00,
1439 cli_cmd_flag_sensitive = 0x01
1440};
1441
6fc6879b
JM
1442struct wpa_cli_cmd {
1443 const char *cmd;
1444 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 1445 enum wpa_cli_cmd_flags flags;
dfa141b1 1446 const char *usage;
6fc6879b
JM
1447};
1448
1449static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 1450 { "status", wpa_cli_cmd_status,
dfa141b1
ER
1451 cli_cmd_flag_none,
1452 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 1453 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
1454 cli_cmd_flag_none,
1455 "= pings wpa_supplicant" },
40fd868c 1456 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
1457 cli_cmd_flag_none,
1458 "= get MIB variables (dot1x, dot11)" },
40fd868c 1459 { "help", wpa_cli_cmd_help,
dfa141b1
ER
1460 cli_cmd_flag_none,
1461 "= show this usage help" },
40fd868c 1462 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
1463 cli_cmd_flag_none,
1464 "[ifname] = show interfaces/select interface" },
40fd868c 1465 { "level", wpa_cli_cmd_level,
dfa141b1
ER
1466 cli_cmd_flag_none,
1467 "<debug level> = change debug level" },
40fd868c 1468 { "license", wpa_cli_cmd_license,
dfa141b1
ER
1469 cli_cmd_flag_none,
1470 "= show full wpa_cli license" },
40fd868c 1471 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
1472 cli_cmd_flag_none,
1473 "= exit wpa_cli" },
40fd868c 1474 { "set", wpa_cli_cmd_set,
dfa141b1
ER
1475 cli_cmd_flag_none,
1476 "= set variables (shows list of variables when run without "
1477 "arguments)" },
40fd868c 1478 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
1479 cli_cmd_flag_none,
1480 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 1481 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
1482 cli_cmd_flag_none,
1483 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 1484 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
1485 cli_cmd_flag_none,
1486 "= show PMKSA cache" },
40fd868c 1487 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
1488 cli_cmd_flag_none,
1489 "= force reassociation" },
40fd868c 1490 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
1491 cli_cmd_flag_none,
1492 "<BSSID> = force preauthentication" },
40fd868c 1493 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
1494 cli_cmd_flag_none,
1495 "<network id> <identity> = configure identity for an SSID" },
40fd868c 1496 { "password", wpa_cli_cmd_password,
dfa141b1
ER
1497 cli_cmd_flag_sensitive,
1498 "<network id> <password> = configure password for an SSID" },
40fd868c 1499 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
1500 cli_cmd_flag_sensitive,
1501 "<network id> <password> = change password for an SSID" },
40fd868c 1502 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
1503 cli_cmd_flag_sensitive,
1504 "<network id> <pin> = configure pin for an SSID" },
40fd868c 1505 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
1506 cli_cmd_flag_sensitive,
1507 "<network id> <password> = configure one-time-password for an SSID"
1508 },
40fd868c 1509 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
1510 cli_cmd_flag_sensitive,
1511 "<network id> <passphrase> = configure private key passphrase\n"
1512 " for an SSID" },
40fd868c 1513 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
1514 cli_cmd_flag_none,
1515 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 1516 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
1517 cli_cmd_flag_none,
1518 "= list configured networks" },
40fd868c 1519 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
1520 cli_cmd_flag_none,
1521 "<network id> = select a network (disable others)" },
40fd868c 1522 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
1523 cli_cmd_flag_none,
1524 "<network id> = enable a network" },
40fd868c 1525 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
1526 cli_cmd_flag_none,
1527 "<network id> = disable a network" },
40fd868c 1528 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
1529 cli_cmd_flag_none,
1530 "= add a network" },
40fd868c 1531 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
1532 cli_cmd_flag_none,
1533 "<network id> = remove a network" },
40fd868c 1534 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
1535 cli_cmd_flag_sensitive,
1536 "<network id> <variable> <value> = set network variables (shows\n"
1537 " list of variables when run without arguments)" },
40fd868c 1538 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
1539 cli_cmd_flag_none,
1540 "<network id> <variable> = get network variables" },
40fd868c 1541 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
1542 cli_cmd_flag_none,
1543 "= save the current configuration" },
40fd868c 1544 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
1545 cli_cmd_flag_none,
1546 "= disconnect and wait for reassociate/reconnect command before\n"
1547 " connecting" },
40fd868c 1548 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
1549 cli_cmd_flag_none,
1550 "= like reassociate, but only takes effect if already disconnected"
1551 },
40fd868c 1552 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
1553 cli_cmd_flag_none,
1554 "= request new BSS scan" },
40fd868c 1555 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
1556 cli_cmd_flag_none,
1557 "= get latest scan results" },
40fd868c 1558 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
1559 cli_cmd_flag_none,
1560 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 1561 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
1562 cli_cmd_flag_none,
1563 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 1564 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
1565 cli_cmd_flag_none,
1566 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 1567 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
1568 cli_cmd_flag_none,
1569 "= terminate wpa_supplicant" },
40fd868c 1570 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
1571 cli_cmd_flag_none,
1572 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1573 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1574 " are optional" },
40fd868c 1575 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
1576 cli_cmd_flag_none,
1577 "<ifname> = removes the interface" },
40fd868c 1578 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
1579 cli_cmd_flag_none,
1580 "= list available interfaces" },
40fd868c 1581 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
1582 cli_cmd_flag_none,
1583 "<value> = set ap_scan parameter" },
40fd868c 1584 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
1585 cli_cmd_flag_none,
1586 "<addr> = request STK negotiation with <addr>" },
40fd868c 1587 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
1588 cli_cmd_flag_none,
1589 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 1590 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
1591 cli_cmd_flag_none,
1592 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 1593 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
1594 cli_cmd_flag_sensitive,
1595 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1596 "hardcoded)" },
116f7bb0 1597#ifdef CONFIG_WPS_OOB
46bdb83a
MH
1598 { "wps_oob", wpa_cli_cmd_wps_oob,
1599 cli_cmd_flag_sensitive,
e1ee6b60 1600 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 1601#endif /* CONFIG_WPS_OOB */
40fd868c 1602 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
1603 cli_cmd_flag_sensitive,
1604 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
e9bcfebf
JM
1605 { "wps_er_start", wpa_cli_cmd_wps_er_start,
1606 cli_cmd_flag_none,
1607 "= start Wi-Fi Protected Setup External Registrar" },
1608 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1609 cli_cmd_flag_none,
1610 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
1611 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1612 cli_cmd_flag_sensitive,
1613 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
1614 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
1615 cli_cmd_flag_none,
1616 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
1617 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
1618 cli_cmd_flag_sensitive,
1619 "<UUID> <PIN> = learn AP configuration" },
11ef8d35
JM
1620 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1621 cli_cmd_flag_none,
1622 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
1623#ifdef CONFIG_AP
1624 { "sta", wpa_cli_cmd_sta,
1625 cli_cmd_flag_none,
1626 "<addr> = get information about an associated station (AP)" },
1627 { "all_sta", wpa_cli_cmd_all_sta,
1628 cli_cmd_flag_none,
1629 "= get information about all associated stations (AP)" },
1630#endif /* CONFIG_AP */
207ef3fb
JM
1631 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
1632 "= notification of suspend/hibernate" },
1633 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
1634 "= notification of resume/thaw" },
dfa141b1 1635 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
1636};
1637
1638
dfa141b1
ER
1639/*
1640 * Prints command usage, lines are padded with the specified string.
1641 */
1642static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1643{
1644 char c;
1645 size_t n;
1646
1647 printf("%s%s ", pad, cmd->cmd);
1648 for (n = 0; (c = cmd->usage[n]); n++) {
1649 printf("%c", c);
1650 if (c == '\n')
1651 printf("%s", pad);
1652 }
1653 printf("\n");
1654}
1655
1656
1657static void print_help(void)
1658{
1659 int n;
1660 printf("commands:\n");
1661 for (n = 0; wpa_cli_commands[n].cmd; n++)
1662 print_cmd_help(&wpa_cli_commands[n], " ");
1663}
1664
1665
40fd868c
ER
1666#ifdef CONFIG_READLINE
1667static int cmd_has_sensitive_data(const char *cmd)
1668{
1669 const char *c, *delim;
1670 int n;
1671 size_t len;
1672
1673 delim = os_strchr(cmd, ' ');
1674 if (delim)
1675 len = delim - cmd;
1676 else
1677 len = os_strlen(cmd);
1678
1679 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1680 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1681 return (wpa_cli_commands[n].flags &
1682 cli_cmd_flag_sensitive);
1683 }
1684 return 0;
1685}
1686#endif /* CONFIG_READLINE */
1687
1688
6fc6879b
JM
1689static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1690{
1691 struct wpa_cli_cmd *cmd, *match = NULL;
1692 int count;
1693 int ret = 0;
1694
1695 count = 0;
1696 cmd = wpa_cli_commands;
1697 while (cmd->cmd) {
1698 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1699 {
1700 match = cmd;
1701 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1702 /* we have an exact match */
1703 count = 1;
1704 break;
1705 }
1706 count++;
1707 }
1708 cmd++;
1709 }
1710
1711 if (count > 1) {
1712 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1713 cmd = wpa_cli_commands;
1714 while (cmd->cmd) {
1715 if (os_strncasecmp(cmd->cmd, argv[0],
1716 os_strlen(argv[0])) == 0) {
1717 printf(" %s", cmd->cmd);
1718 }
1719 cmd++;
1720 }
1721 printf("\n");
1722 ret = 1;
1723 } else if (count == 0) {
1724 printf("Unknown command '%s'\n", argv[0]);
1725 ret = 1;
1726 } else {
1727 ret = match->handler(ctrl, argc - 1, &argv[1]);
1728 }
1729
1730 return ret;
1731}
1732
1733
1734static int str_match(const char *a, const char *b)
1735{
1736 return os_strncmp(a, b, os_strlen(b)) == 0;
1737}
1738
1739
1740static int wpa_cli_exec(const char *program, const char *arg1,
1741 const char *arg2)
1742{
1743 char *cmd;
1744 size_t len;
1745 int res;
308a4ec8 1746 int ret = 0;
6fc6879b
JM
1747
1748 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1749 cmd = os_malloc(len);
1750 if (cmd == NULL)
1751 return -1;
1752 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1753 if (res < 0 || (size_t) res >= len) {
1754 os_free(cmd);
1755 return -1;
1756 }
1757 cmd[len - 1] = '\0';
1758#ifndef _WIN32_WCE
308a4ec8
JM
1759 if (system(cmd) < 0)
1760 ret = -1;
6fc6879b
JM
1761#endif /* _WIN32_WCE */
1762 os_free(cmd);
1763
308a4ec8 1764 return ret;
6fc6879b
JM
1765}
1766
1767
1768static void wpa_cli_action_process(const char *msg)
1769{
1770 const char *pos;
1771 char *copy = NULL, *id, *pos2;
1772
1773 pos = msg;
1774 if (*pos == '<') {
1775 /* skip priority */
1776 pos = os_strchr(pos, '>');
1777 if (pos)
1778 pos++;
1779 else
1780 pos = msg;
1781 }
1782
1783 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1784 int new_id = -1;
1785 os_unsetenv("WPA_ID");
1786 os_unsetenv("WPA_ID_STR");
1787 os_unsetenv("WPA_CTRL_DIR");
1788
1789 pos = os_strstr(pos, "[id=");
1790 if (pos)
1791 copy = os_strdup(pos + 4);
1792
1793 if (copy) {
1794 pos2 = id = copy;
1795 while (*pos2 && *pos2 != ' ')
1796 pos2++;
1797 *pos2++ = '\0';
1798 new_id = atoi(id);
1799 os_setenv("WPA_ID", id, 1);
1800 while (*pos2 && *pos2 != '=')
1801 pos2++;
1802 if (*pos2 == '=')
1803 pos2++;
1804 id = pos2;
1805 while (*pos2 && *pos2 != ']')
1806 pos2++;
1807 *pos2 = '\0';
1808 os_setenv("WPA_ID_STR", id, 1);
1809 os_free(copy);
1810 }
1811
1812 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1813
1814 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1815 wpa_cli_connected = 1;
1816 wpa_cli_last_id = new_id;
1817 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1818 }
1819 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1820 if (wpa_cli_connected) {
1821 wpa_cli_connected = 0;
1822 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1823 }
1824 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1825 printf("wpa_supplicant is terminating - stop monitoring\n");
1826 wpa_cli_quit = 1;
1827 }
1828}
1829
1830
1831#ifndef CONFIG_ANSI_C_EXTRA
1832static void wpa_cli_action_cb(char *msg, size_t len)
1833{
1834 wpa_cli_action_process(msg);
1835}
1836#endif /* CONFIG_ANSI_C_EXTRA */
1837
1838
1839static void wpa_cli_reconnect(void)
1840{
1841 wpa_cli_close_connection();
4a3ade4e 1842 wpa_cli_open_connection(ctrl_ifname, 1);
6fc6879b
JM
1843}
1844
1845
1846static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1847 int action_monitor)
1848{
1849 int first = 1;
1850 if (ctrl_conn == NULL) {
1851 wpa_cli_reconnect();
1852 return;
1853 }
1854 while (wpa_ctrl_pending(ctrl) > 0) {
1855 char buf[256];
1856 size_t len = sizeof(buf) - 1;
1857 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1858 buf[len] = '\0';
1859 if (action_monitor)
1860 wpa_cli_action_process(buf);
1861 else {
1862 if (in_read && first)
dd63f314 1863 printf("\r");
6fc6879b
JM
1864 first = 0;
1865 printf("%s\n", buf);
dd63f314
JM
1866#ifdef CONFIG_READLINE
1867 rl_on_new_line();
1868 rl_redisplay();
1869#endif /* CONFIG_READLINE */
6fc6879b
JM
1870 }
1871 } else {
1872 printf("Could not read pending message.\n");
1873 break;
1874 }
1875 }
1876
1877 if (wpa_ctrl_pending(ctrl) < 0) {
1878 printf("Connection to wpa_supplicant lost - trying to "
1879 "reconnect\n");
1880 wpa_cli_reconnect();
1881 }
1882}
1883
1884
1885#ifdef CONFIG_READLINE
1886static char * wpa_cli_cmd_gen(const char *text, int state)
1887{
1888 static int i, len;
1889 const char *cmd;
1890
1891 if (state == 0) {
1892 i = 0;
1893 len = os_strlen(text);
1894 }
1895
1896 while ((cmd = wpa_cli_commands[i].cmd)) {
1897 i++;
1898 if (os_strncasecmp(cmd, text, len) == 0)
d566f415 1899 return strdup(cmd);
6fc6879b
JM
1900 }
1901
1902 return NULL;
1903}
1904
1905
1906static char * wpa_cli_dummy_gen(const char *text, int state)
1907{
a7918ec7
JM
1908 int i;
1909
1910 for (i = 0; wpa_cli_commands[i].cmd; i++) {
1911 const char *cmd = wpa_cli_commands[i].cmd;
1912 size_t len = os_strlen(cmd);
1913 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
1914 rl_line_buffer[len] == ' ') {
1915 printf("\n%s\n", wpa_cli_commands[i].usage);
1916 rl_on_new_line();
1917 rl_redisplay();
1918 break;
1919 }
1920 }
1921
1922 rl_attempted_completion_over = 1;
1923 return NULL;
1924}
1925
1926
1927static char * wpa_cli_status_gen(const char *text, int state)
1928{
1929 static int i, len;
1930 char *options[] = {
1931 "verbose", NULL
1932 };
1933 char *t;
1934
1935 if (state == 0) {
1936 i = 0;
1937 len = os_strlen(text);
1938 }
1939
1940 while ((t = options[i])) {
1941 i++;
1942 if (os_strncasecmp(t, text, len) == 0)
1943 return strdup(t);
1944 }
1945
1946 rl_attempted_completion_over = 1;
6fc6879b
JM
1947 return NULL;
1948}
1949
1950
1951static char ** wpa_cli_completion(const char *text, int start, int end)
1952{
a7918ec7
JM
1953 char * (*func)(const char *text, int state);
1954
1955 if (start == 0)
1956 func = wpa_cli_cmd_gen;
1957 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
1958 func = wpa_cli_status_gen;
1959 else
1960 func = wpa_cli_dummy_gen;
1961 return rl_completion_matches(text, func);
6fc6879b
JM
1962}
1963#endif /* CONFIG_READLINE */
1964
1965
1966static void wpa_cli_interactive(void)
1967{
1968#define max_args 10
1969 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1970 int argc;
1971#ifdef CONFIG_READLINE
1972 char *home, *hfile = NULL;
1973#endif /* CONFIG_READLINE */
1974
1975 printf("\nInteractive mode\n\n");
1976
1977#ifdef CONFIG_READLINE
1978 rl_attempted_completion_function = wpa_cli_completion;
1979 home = getenv("HOME");
1980 if (home) {
1981 const char *fname = ".wpa_cli_history";
1982 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1983 hfile = os_malloc(hfile_len);
1984 if (hfile) {
1985 int res;
1986 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1987 fname);
1988 if (res >= 0 && res < hfile_len) {
1989 hfile[hfile_len - 1] = '\0';
1990 read_history(hfile);
1991 stifle_history(100);
1992 }
1993 }
1994 }
1995#endif /* CONFIG_READLINE */
1996
1997 do {
4a3ade4e 1998 wpa_cli_recv_pending(mon_conn, 0, 0);
6fc6879b 1999#ifndef CONFIG_NATIVE_WINDOWS
1cc84c1c 2000 alarm(ping_interval);
6fc6879b 2001#endif /* CONFIG_NATIVE_WINDOWS */
dd63f314
JM
2002#ifdef CONFIG_WPA_CLI_FORK
2003 if (mon_pid)
2004 kill(mon_pid, SIGUSR1);
2005#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
2006#ifdef CONFIG_READLINE
2007 cmd = readline("> ");
2008 if (cmd && *cmd) {
2009 HIST_ENTRY *h;
2010 while (next_history())
2011 ;
2012 h = previous_history();
2013 if (h == NULL || os_strcmp(cmd, h->line) != 0)
2014 add_history(cmd);
2015 next_history();
2016 }
2017#else /* CONFIG_READLINE */
2018 printf("> ");
2019 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2020#endif /* CONFIG_READLINE */
2021#ifndef CONFIG_NATIVE_WINDOWS
2022 alarm(0);
2023#endif /* CONFIG_NATIVE_WINDOWS */
2024 if (cmd == NULL)
2025 break;
4a3ade4e 2026 wpa_cli_recv_pending(mon_conn, 0, 0);
6fc6879b
JM
2027 pos = cmd;
2028 while (*pos != '\0') {
2029 if (*pos == '\n') {
2030 *pos = '\0';
2031 break;
2032 }
2033 pos++;
2034 }
2035 argc = 0;
2036 pos = cmd;
2037 for (;;) {
2038 while (*pos == ' ')
2039 pos++;
2040 if (*pos == '\0')
2041 break;
2042 argv[argc] = pos;
2043 argc++;
2044 if (argc == max_args)
2045 break;
2046 if (*pos == '"') {
2047 char *pos2 = os_strrchr(pos, '"');
2048 if (pos2)
2049 pos = pos2 + 1;
2050 }
2051 while (*pos != '\0' && *pos != ' ')
2052 pos++;
2053 if (*pos == ' ')
2054 *pos++ = '\0';
2055 }
2056 if (argc)
2057 wpa_request(ctrl_conn, argc, argv);
2058
2059 if (cmd != cmdbuf)
a24eb842 2060 free(cmd);
dd63f314
JM
2061#ifdef CONFIG_WPA_CLI_FORK
2062 if (mon_pid)
2063 kill(mon_pid, SIGUSR2);
2064#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b
JM
2065 } while (!wpa_cli_quit);
2066
2067#ifdef CONFIG_READLINE
2068 if (hfile) {
2069 /* Save command history, excluding lines that may contain
2070 * passwords. */
2071 HIST_ENTRY *h;
2072 history_set_pos(0);
413653e8 2073 while ((h = current_history())) {
6fc6879b
JM
2074 char *p = h->line;
2075 while (*p == ' ' || *p == '\t')
2076 p++;
40fd868c 2077 if (cmd_has_sensitive_data(p)) {
6fc6879b
JM
2078 h = remove_history(where_history());
2079 if (h) {
2080 os_free(h->line);
2081 os_free(h->data);
2082 os_free(h);
413653e8
ER
2083 } else
2084 next_history();
2085 } else
2086 next_history();
6fc6879b
JM
2087 }
2088 write_history(hfile);
2089 os_free(hfile);
2090 }
2091#endif /* CONFIG_READLINE */
2092}
2093
2094
2095static void wpa_cli_action(struct wpa_ctrl *ctrl)
2096{
2097#ifdef CONFIG_ANSI_C_EXTRA
2098 /* TODO: ANSI C version(?) */
2099 printf("Action processing not supported in ANSI C build.\n");
2100#else /* CONFIG_ANSI_C_EXTRA */
2101 fd_set rfds;
2102 int fd, res;
2103 struct timeval tv;
2104 char buf[256]; /* note: large enough to fit in unsolicited messages */
2105 size_t len;
2106
2107 fd = wpa_ctrl_get_fd(ctrl);
2108
2109 while (!wpa_cli_quit) {
2110 FD_ZERO(&rfds);
2111 FD_SET(fd, &rfds);
1cc84c1c 2112 tv.tv_sec = ping_interval;
6fc6879b
JM
2113 tv.tv_usec = 0;
2114 res = select(fd + 1, &rfds, NULL, NULL, &tv);
2115 if (res < 0 && errno != EINTR) {
2116 perror("select");
2117 break;
2118 }
2119
2120 if (FD_ISSET(fd, &rfds))
2121 wpa_cli_recv_pending(ctrl, 0, 1);
2122 else {
2123 /* verify that connection is still working */
2124 len = sizeof(buf) - 1;
2125 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2126 wpa_cli_action_cb) < 0 ||
2127 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2128 printf("wpa_supplicant did not reply to PING "
2129 "command - exiting\n");
2130 break;
2131 }
2132 }
2133 }
2134#endif /* CONFIG_ANSI_C_EXTRA */
2135}
2136
2137
2138static void wpa_cli_cleanup(void)
2139{
2140 wpa_cli_close_connection();
2141 if (pid_file)
2142 os_daemonize_terminate(pid_file);
2143
2144 os_program_deinit();
2145}
2146
2147static void wpa_cli_terminate(int sig)
2148{
2149 wpa_cli_cleanup();
2150 exit(0);
2151}
2152
2153
dd63f314
JM
2154#ifdef CONFIG_WPA_CLI_FORK
2155static void wpa_cli_usr1(int sig)
2156{
2157#ifdef CONFIG_READLINE
2158 rl_on_new_line();
2159 rl_redisplay();
2160#endif /* CONFIG_READLINE */
2161}
2162#endif /* CONFIG_WPA_CLI_FORK */
2163
2164
6fc6879b
JM
2165#ifndef CONFIG_NATIVE_WINDOWS
2166static void wpa_cli_alarm(int sig)
2167{
2168 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2169 printf("Connection to wpa_supplicant lost - trying to "
2170 "reconnect\n");
2171 wpa_cli_close_connection();
2172 }
2173 if (!ctrl_conn)
2174 wpa_cli_reconnect();
4a3ade4e
JM
2175 if (mon_conn)
2176 wpa_cli_recv_pending(mon_conn, 1, 0);
1cc84c1c 2177 alarm(ping_interval);
6fc6879b
JM
2178}
2179#endif /* CONFIG_NATIVE_WINDOWS */
2180
2181
2182static char * wpa_cli_get_default_ifname(void)
2183{
2184 char *ifname = NULL;
2185
2186#ifdef CONFIG_CTRL_IFACE_UNIX
2187 struct dirent *dent;
2188 DIR *dir = opendir(ctrl_iface_dir);
2189 if (!dir)
2190 return NULL;
2191 while ((dent = readdir(dir))) {
2192#ifdef _DIRENT_HAVE_D_TYPE
2193 /*
2194 * Skip the file if it is not a socket. Also accept
2195 * DT_UNKNOWN (0) in case the C library or underlying
2196 * file system does not support d_type.
2197 */
2198 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2199 continue;
2200#endif /* _DIRENT_HAVE_D_TYPE */
2201 if (os_strcmp(dent->d_name, ".") == 0 ||
2202 os_strcmp(dent->d_name, "..") == 0)
2203 continue;
2204 printf("Selected interface '%s'\n", dent->d_name);
2205 ifname = os_strdup(dent->d_name);
2206 break;
2207 }
2208 closedir(dir);
2209#endif /* CONFIG_CTRL_IFACE_UNIX */
2210
2211#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2212 char buf[2048], *pos;
2213 size_t len;
2214 struct wpa_ctrl *ctrl;
2215 int ret;
2216
2217 ctrl = wpa_ctrl_open(NULL);
2218 if (ctrl == NULL)
2219 return NULL;
2220
2221 len = sizeof(buf) - 1;
2222 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2223 if (ret >= 0) {
2224 buf[len] = '\0';
2225 pos = os_strchr(buf, '\n');
2226 if (pos)
2227 *pos = '\0';
2228 ifname = os_strdup(buf);
2229 }
2230 wpa_ctrl_close(ctrl);
2231#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2232
2233 return ifname;
2234}
2235
2236
2237int main(int argc, char *argv[])
2238{
6fc6879b
JM
2239 int warning_displayed = 0;
2240 int c;
2241 int daemonize = 0;
2242 int ret = 0;
2243 const char *global = NULL;
2244
2245 if (os_program_init())
2246 return -1;
2247
2248 for (;;) {
1cc84c1c 2249 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
2250 if (c < 0)
2251 break;
2252 switch (c) {
2253 case 'a':
2254 action_file = optarg;
2255 break;
2256 case 'B':
2257 daemonize = 1;
2258 break;
2259 case 'g':
2260 global = optarg;
2261 break;
1cc84c1c
JM
2262 case 'G':
2263 ping_interval = atoi(optarg);
2264 break;
6fc6879b
JM
2265 case 'h':
2266 usage();
2267 return 0;
2268 case 'v':
2269 printf("%s\n", wpa_cli_version);
2270 return 0;
2271 case 'i':
2272 os_free(ctrl_ifname);
2273 ctrl_ifname = os_strdup(optarg);
2274 break;
2275 case 'p':
2276 ctrl_iface_dir = optarg;
2277 break;
2278 case 'P':
2279 pid_file = optarg;
2280 break;
2281 default:
2282 usage();
2283 return -1;
2284 }
2285 }
2286
2287 interactive = (argc == optind) && (action_file == NULL);
2288
2289 if (interactive)
2290 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2291
2292 if (global) {
2293#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2294 ctrl_conn = wpa_ctrl_open(NULL);
2295#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2296 ctrl_conn = wpa_ctrl_open(global);
2297#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2298 if (ctrl_conn == NULL) {
2299 perror("Failed to connect to wpa_supplicant - "
2300 "wpa_ctrl_open");
2301 return -1;
2302 }
2303 }
2304
6fc6879b
JM
2305#ifndef _WIN32_WCE
2306 signal(SIGINT, wpa_cli_terminate);
2307 signal(SIGTERM, wpa_cli_terminate);
2308#endif /* _WIN32_WCE */
2309#ifndef CONFIG_NATIVE_WINDOWS
2310 signal(SIGALRM, wpa_cli_alarm);
2311#endif /* CONFIG_NATIVE_WINDOWS */
dd63f314
JM
2312#ifdef CONFIG_WPA_CLI_FORK
2313 signal(SIGUSR1, wpa_cli_usr1);
2314#endif /* CONFIG_WPA_CLI_FORK */
6fc6879b 2315
4a3ade4e
JM
2316 if (ctrl_ifname == NULL)
2317 ctrl_ifname = wpa_cli_get_default_ifname();
2318
2319 if (interactive) {
2320 for (; !global;) {
2321 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
2322 if (warning_displayed)
2323 printf("Connection established.\n");
2324 break;
2325 }
2326
2327 if (!warning_displayed) {
2328 printf("Could not connect to wpa_supplicant - "
2329 "re-trying\n");
2330 warning_displayed = 1;
2331 }
2332 os_sleep(1, 0);
2333 continue;
2334 }
2335 } else {
2336 if (!global &&
2337 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
2338 perror("Failed to connect to wpa_supplicant - "
2339 "wpa_ctrl_open");
2340 return -1;
2341 }
2342
2343 if (action_file) {
2344 if (wpa_ctrl_attach(ctrl_conn) == 0) {
2345 wpa_cli_attached = 1;
2346 } else {
2347 printf("Warning: Failed to attach to "
2348 "wpa_supplicant.\n");
6fc6879b 2349 return -1;
4a3ade4e 2350 }
6fc6879b
JM
2351 }
2352 }
2353
2354 if (daemonize && os_daemonize(pid_file))
2355 return -1;
2356
2357 if (interactive)
2358 wpa_cli_interactive();
2359 else if (action_file)
2360 wpa_cli_action(ctrl_conn);
2361 else
2362 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2363
2364 os_free(ctrl_ifname);
2365 wpa_cli_cleanup();
2366
2367 return ret;
2368}
2369
2370#else /* CONFIG_CTRL_IFACE */
2371int main(int argc, char *argv[])
2372{
2373 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2374 return -1;
2375}
2376#endif /* CONFIG_CTRL_IFACE */