]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/wpa_cli.c
wpa_cli: Add internal line edit implementation
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2010, 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 #ifdef CONFIG_WPA_CLI_EDIT
17 #include <termios.h>
18 #endif /* CONFIG_WPA_CLI_EDIT */
19
20 #ifdef CONFIG_CTRL_IFACE
21
22 #ifdef CONFIG_CTRL_IFACE_UNIX
23 #include <dirent.h>
24 #endif /* CONFIG_CTRL_IFACE_UNIX */
25 #ifdef CONFIG_READLINE
26 #include <readline/readline.h>
27 #include <readline/history.h>
28 #endif /* CONFIG_READLINE */
29
30 #include "common/wpa_ctrl.h"
31 #include "utils/common.h"
32 #include "utils/eloop.h"
33 #include "common/version.h"
34
35
36 static const char *wpa_cli_version =
37 "wpa_cli v" VERSION_STR "\n"
38 "Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
39
40
41 static const char *wpa_cli_license =
42 "This program is free software. You can distribute it and/or modify it\n"
43 "under the terms of the GNU General Public License version 2.\n"
44 "\n"
45 "Alternatively, this software may be distributed under the terms of the\n"
46 "BSD license. See README and COPYING for more details.\n";
47
48 static const char *wpa_cli_full_license =
49 "This program is free software; you can redistribute it and/or modify\n"
50 "it under the terms of the GNU General Public License version 2 as\n"
51 "published by the Free Software Foundation.\n"
52 "\n"
53 "This program is distributed in the hope that it will be useful,\n"
54 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
55 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
56 "GNU General Public License for more details.\n"
57 "\n"
58 "You should have received a copy of the GNU General Public License\n"
59 "along with this program; if not, write to the Free Software\n"
60 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
61 "\n"
62 "Alternatively, this software may be distributed under the terms of the\n"
63 "BSD license.\n"
64 "\n"
65 "Redistribution and use in source and binary forms, with or without\n"
66 "modification, are permitted provided that the following conditions are\n"
67 "met:\n"
68 "\n"
69 "1. Redistributions of source code must retain the above copyright\n"
70 " notice, this list of conditions and the following disclaimer.\n"
71 "\n"
72 "2. Redistributions in binary form must reproduce the above copyright\n"
73 " notice, this list of conditions and the following disclaimer in the\n"
74 " documentation and/or other materials provided with the distribution.\n"
75 "\n"
76 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
77 " names of its contributors may be used to endorse or promote products\n"
78 " derived from this software without specific prior written permission.\n"
79 "\n"
80 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
81 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
82 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
83 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
84 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
85 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
86 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
87 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
88 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
89 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
90 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
91 "\n";
92
93 static struct wpa_ctrl *ctrl_conn;
94 static struct wpa_ctrl *mon_conn;
95 static int wpa_cli_quit = 0;
96 static int wpa_cli_attached = 0;
97 static int wpa_cli_connected = 0;
98 static int wpa_cli_last_id = 0;
99 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
100 static char *ctrl_ifname = NULL;
101 static const char *pid_file = NULL;
102 static const char *action_file = NULL;
103 static int ping_interval = 5;
104 static int interactive = 0;
105 #ifndef CONFIG_READLINE
106 #define CMD_BUF_LEN 256
107 static char cmdbuf[CMD_BUF_LEN];
108 static int cmdbuf_pos = 0;
109 static int cmdbuf_len = 0;
110 #endif /* CONFIG_READLINE */
111 #ifdef CONFIG_WPA_CLI_EDIT
112 #define CMD_HISTORY_LEN 20
113 static char history_buf[CMD_HISTORY_LEN][CMD_BUF_LEN];
114 static int history_pos = 0;
115 static int history_current = 0;
116 #endif /* CONFIG_WPA_CLI_EDIT */
117
118
119 static void print_help(void);
120 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
121
122
123 static void usage(void)
124 {
125 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
126 "[-a<action file>] \\\n"
127 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
128 "[command..]\n"
129 " -h = help (show this usage text)\n"
130 " -v = shown version information\n"
131 " -a = run in daemon mode executing the action file based on "
132 "events from\n"
133 " wpa_supplicant\n"
134 " -B = run a daemon in the background\n"
135 " default path: /var/run/wpa_supplicant\n"
136 " default interface: first interface found in socket path\n");
137 print_help();
138 }
139
140
141 static void readline_redraw()
142 {
143 #ifdef CONFIG_READLINE
144 rl_on_new_line();
145 rl_redisplay();
146 #else /* CONFIG_READLINE */
147 char tmp;
148 cmdbuf[cmdbuf_len] = '\0';
149 printf("\r> %s", cmdbuf);
150 if (cmdbuf_pos != cmdbuf_len) {
151 tmp = cmdbuf[cmdbuf_pos];
152 cmdbuf[cmdbuf_pos] = '\0';
153 printf("\r> %s", cmdbuf);
154 cmdbuf[cmdbuf_pos] = tmp;
155 }
156 fflush(stdout);
157 #endif /* CONFIG_READLINE */
158 }
159
160
161 static int str_starts(const char *src, const char *match)
162 {
163 return os_strncmp(src, match, os_strlen(match)) == 0;
164 }
165
166
167 static int wpa_cli_show_event(const char *event)
168 {
169 const char *start;
170
171 start = os_strchr(event, '>');
172 if (start == NULL)
173 return 1;
174
175 start++;
176 /*
177 * Skip BSS added/removed events since they can be relatively frequent
178 * and are likely of not much use for an interactive user.
179 */
180 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
181 str_starts(start, WPA_EVENT_BSS_REMOVED))
182 return 0;
183
184 return 1;
185 }
186
187
188 static int wpa_cli_open_connection(const char *ifname, int attach)
189 {
190 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
191 ctrl_conn = wpa_ctrl_open(ifname);
192 if (ctrl_conn == NULL)
193 return -1;
194
195 if (attach && interactive)
196 mon_conn = wpa_ctrl_open(ifname);
197 else
198 mon_conn = NULL;
199 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
200 char *cfile;
201 int flen, res;
202
203 if (ifname == NULL)
204 return -1;
205
206 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
207 cfile = os_malloc(flen);
208 if (cfile == NULL)
209 return -1L;
210 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
211 if (res < 0 || res >= flen) {
212 os_free(cfile);
213 return -1;
214 }
215
216 ctrl_conn = wpa_ctrl_open(cfile);
217 if (ctrl_conn == NULL) {
218 os_free(cfile);
219 return -1;
220 }
221
222 if (attach && interactive)
223 mon_conn = wpa_ctrl_open(cfile);
224 else
225 mon_conn = NULL;
226 os_free(cfile);
227 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
228
229 if (mon_conn) {
230 if (wpa_ctrl_attach(mon_conn) == 0) {
231 wpa_cli_attached = 1;
232 if (interactive)
233 eloop_register_read_sock(
234 wpa_ctrl_get_fd(mon_conn),
235 wpa_cli_mon_receive, NULL, NULL);
236 } else {
237 printf("Warning: Failed to attach to "
238 "wpa_supplicant.\n");
239 return -1;
240 }
241 }
242
243 return 0;
244 }
245
246
247 static void wpa_cli_close_connection(void)
248 {
249 if (ctrl_conn == NULL)
250 return;
251
252 if (wpa_cli_attached) {
253 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
254 wpa_cli_attached = 0;
255 }
256 wpa_ctrl_close(ctrl_conn);
257 ctrl_conn = NULL;
258 if (mon_conn) {
259 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
260 wpa_ctrl_close(mon_conn);
261 mon_conn = NULL;
262 }
263 }
264
265
266 static void wpa_cli_msg_cb(char *msg, size_t len)
267 {
268 printf("%s\n", msg);
269 }
270
271
272 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
273 {
274 char buf[2048];
275 size_t len;
276 int ret;
277
278 if (ctrl_conn == NULL) {
279 printf("Not connected to wpa_supplicant - command dropped.\n");
280 return -1;
281 }
282 len = sizeof(buf) - 1;
283 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
284 wpa_cli_msg_cb);
285 if (ret == -2) {
286 printf("'%s' command timed out.\n", cmd);
287 return -2;
288 } else if (ret < 0) {
289 printf("'%s' command failed.\n", cmd);
290 return -1;
291 }
292 if (print) {
293 buf[len] = '\0';
294 printf("%s", buf);
295 }
296 return 0;
297 }
298
299
300 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
301 {
302 return _wpa_ctrl_command(ctrl, cmd, 1);
303 }
304
305
306 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
307 {
308 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
309 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
310 }
311
312
313 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
314 {
315 return wpa_ctrl_command(ctrl, "PING");
316 }
317
318
319 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
320 {
321 char cmd[256];
322 int ret;
323 if (argc == 0)
324 return -1;
325 ret = os_snprintf(cmd, sizeof(cmd), "NOTE %s", argv[0]);
326 if (ret < 0 || (size_t) ret >= sizeof(cmd))
327 return -1;
328 return wpa_ctrl_command(ctrl, cmd);
329 }
330
331
332 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
333 {
334 return wpa_ctrl_command(ctrl, "MIB");
335 }
336
337
338 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
339 {
340 return wpa_ctrl_command(ctrl, "PMKSA");
341 }
342
343
344 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
345 {
346 print_help();
347 return 0;
348 }
349
350
351 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
352 {
353 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
354 return 0;
355 }
356
357
358 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
359 {
360 wpa_cli_quit = 1;
361 if (interactive)
362 eloop_terminate();
363 return 0;
364 }
365
366
367 static void wpa_cli_show_variables(void)
368 {
369 printf("set variables:\n"
370 " EAPOL::heldPeriod (EAPOL state machine held period, "
371 "in seconds)\n"
372 " EAPOL::authPeriod (EAPOL state machine authentication "
373 "period, in seconds)\n"
374 " EAPOL::startPeriod (EAPOL state machine start period, in "
375 "seconds)\n"
376 " EAPOL::maxStart (EAPOL state machine maximum start "
377 "attempts)\n");
378 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
379 "seconds)\n"
380 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
381 " threshold\n\tpercentage)\n"
382 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
383 "security\n\tassociation in seconds)\n");
384 }
385
386
387 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
388 {
389 char cmd[256];
390 int res;
391
392 if (argc == 0) {
393 wpa_cli_show_variables();
394 return 0;
395 }
396
397 if (argc != 2) {
398 printf("Invalid SET command: needs two arguments (variable "
399 "name and value)\n");
400 return -1;
401 }
402
403 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
404 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
405 printf("Too long SET command.\n");
406 return -1;
407 }
408 return wpa_ctrl_command(ctrl, cmd);
409 }
410
411
412 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
413 {
414 char cmd[256];
415 int res;
416
417 if (argc != 1) {
418 printf("Invalid GET command: need one argument (variable "
419 "name)\n");
420 return -1;
421 }
422
423 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
424 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
425 printf("Too long GET command.\n");
426 return -1;
427 }
428 return wpa_ctrl_command(ctrl, cmd);
429 }
430
431
432 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
433 {
434 return wpa_ctrl_command(ctrl, "LOGOFF");
435 }
436
437
438 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
439 {
440 return wpa_ctrl_command(ctrl, "LOGON");
441 }
442
443
444 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
445 char *argv[])
446 {
447 return wpa_ctrl_command(ctrl, "REASSOCIATE");
448 }
449
450
451 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
452 char *argv[])
453 {
454 char cmd[256];
455 int res;
456
457 if (argc != 1) {
458 printf("Invalid PREAUTH command: needs one argument "
459 "(BSSID)\n");
460 return -1;
461 }
462
463 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
464 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
465 printf("Too long PREAUTH command.\n");
466 return -1;
467 }
468 return wpa_ctrl_command(ctrl, cmd);
469 }
470
471
472 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
473 {
474 char cmd[256];
475 int res;
476
477 if (argc != 1) {
478 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
479 "value)\n");
480 return -1;
481 }
482 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
483 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
484 printf("Too long AP_SCAN command.\n");
485 return -1;
486 }
487 return wpa_ctrl_command(ctrl, cmd);
488 }
489
490
491 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
492 char *argv[])
493 {
494 char cmd[256];
495 int res;
496
497 if (argc != 1) {
498 printf("Invalid STKSTART command: needs one argument "
499 "(Peer STA MAC address)\n");
500 return -1;
501 }
502
503 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
504 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
505 printf("Too long STKSTART command.\n");
506 return -1;
507 }
508 return wpa_ctrl_command(ctrl, cmd);
509 }
510
511
512 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
513 {
514 char cmd[256];
515 int res;
516
517 if (argc != 1) {
518 printf("Invalid FT_DS command: needs one argument "
519 "(Target AP MAC address)\n");
520 return -1;
521 }
522
523 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
524 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
525 printf("Too long FT_DS command.\n");
526 return -1;
527 }
528 return wpa_ctrl_command(ctrl, cmd);
529 }
530
531
532 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
533 {
534 char cmd[256];
535 int res;
536
537 if (argc == 0) {
538 /* Any BSSID */
539 return wpa_ctrl_command(ctrl, "WPS_PBC");
540 }
541
542 /* Specific BSSID */
543 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
544 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
545 printf("Too long WPS_PBC command.\n");
546 return -1;
547 }
548 return wpa_ctrl_command(ctrl, cmd);
549 }
550
551
552 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
553 {
554 char cmd[256];
555 int res;
556
557 if (argc == 0) {
558 printf("Invalid WPS_PIN command: need one or two arguments:\n"
559 "- BSSID: use 'any' to select any\n"
560 "- PIN: optional, used only with devices that have no "
561 "display\n");
562 return -1;
563 }
564
565 if (argc == 1) {
566 /* Use dynamically generated PIN (returned as reply) */
567 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
568 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
569 printf("Too long WPS_PIN command.\n");
570 return -1;
571 }
572 return wpa_ctrl_command(ctrl, cmd);
573 }
574
575 /* Use hardcoded PIN from a label */
576 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
577 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
578 printf("Too long WPS_PIN command.\n");
579 return -1;
580 }
581 return wpa_ctrl_command(ctrl, cmd);
582 }
583
584
585 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
586 char *argv[])
587 {
588 char cmd[256];
589 int res;
590
591 if (argc != 1 && argc != 2) {
592 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
593 "- PIN to be verified\n");
594 return -1;
595 }
596
597 if (argc == 2)
598 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
599 argv[0], argv[1]);
600 else
601 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
602 argv[0]);
603 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
604 printf("Too long WPS_CHECK_PIN command.\n");
605 return -1;
606 }
607 return wpa_ctrl_command(ctrl, cmd);
608 }
609
610
611 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
612 char *argv[])
613 {
614 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
615 }
616
617
618 #ifdef CONFIG_WPS_OOB
619 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
620 {
621 char cmd[256];
622 int res;
623
624 if (argc != 3 && argc != 4) {
625 printf("Invalid WPS_OOB command: need three or four "
626 "arguments:\n"
627 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
628 "- PATH: path of OOB device like '/mnt'\n"
629 "- METHOD: OOB method 'pin-e' or 'pin-r', "
630 "'cred'\n"
631 "- DEV_NAME: (only for NFC) device name like "
632 "'pn531'\n");
633 return -1;
634 }
635
636 if (argc == 3)
637 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
638 argv[0], argv[1], argv[2]);
639 else
640 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
641 argv[0], argv[1], argv[2], argv[3]);
642 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
643 printf("Too long WPS_OOB command.\n");
644 return -1;
645 }
646 return wpa_ctrl_command(ctrl, cmd);
647 }
648 #endif /* CONFIG_WPS_OOB */
649
650
651 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
652 {
653 char cmd[256];
654 int res;
655
656 if (argc == 2)
657 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
658 argv[0], argv[1]);
659 else if (argc == 5 || argc == 6) {
660 char ssid_hex[2 * 32 + 1];
661 char key_hex[2 * 64 + 1];
662 int i;
663
664 ssid_hex[0] = '\0';
665 for (i = 0; i < 32; i++) {
666 if (argv[2][i] == '\0')
667 break;
668 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
669 }
670
671 key_hex[0] = '\0';
672 if (argc == 6) {
673 for (i = 0; i < 64; i++) {
674 if (argv[5][i] == '\0')
675 break;
676 os_snprintf(&key_hex[i * 2], 3, "%02x",
677 argv[5][i]);
678 }
679 }
680
681 res = os_snprintf(cmd, sizeof(cmd),
682 "WPS_REG %s %s %s %s %s %s",
683 argv[0], argv[1], ssid_hex, argv[3], argv[4],
684 key_hex);
685 } else {
686 printf("Invalid WPS_REG command: need two arguments:\n"
687 "- BSSID of the target AP\n"
688 "- AP PIN\n");
689 printf("Alternatively, six arguments can be used to "
690 "reconfigure the AP:\n"
691 "- BSSID of the target AP\n"
692 "- AP PIN\n"
693 "- new SSID\n"
694 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
695 "- new encr (NONE, WEP, TKIP, CCMP)\n"
696 "- new key\n");
697 return -1;
698 }
699
700 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
701 printf("Too long WPS_REG command.\n");
702 return -1;
703 }
704 return wpa_ctrl_command(ctrl, cmd);
705 }
706
707
708 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
709 char *argv[])
710 {
711 char cmd[100];
712 if (argc > 0) {
713 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
714 return wpa_ctrl_command(ctrl, cmd);
715 }
716 return wpa_ctrl_command(ctrl, "WPS_ER_START");
717 }
718
719
720 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
721 char *argv[])
722 {
723 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
724
725 }
726
727
728 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
729 char *argv[])
730 {
731 char cmd[256];
732 int res;
733
734 if (argc < 2) {
735 printf("Invalid WPS_ER_PIN command: need at least two "
736 "arguments:\n"
737 "- UUID: use 'any' to select any\n"
738 "- PIN: Enrollee PIN\n"
739 "optional: - Enrollee MAC address\n");
740 return -1;
741 }
742
743 if (argc > 2)
744 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
745 argv[0], argv[1], argv[2]);
746 else
747 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
748 argv[0], argv[1]);
749 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
750 printf("Too long WPS_ER_PIN command.\n");
751 return -1;
752 }
753 return wpa_ctrl_command(ctrl, cmd);
754 }
755
756
757 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
758 char *argv[])
759 {
760 char cmd[256];
761 int res;
762
763 if (argc != 1) {
764 printf("Invalid WPS_ER_PBC command: need one argument:\n"
765 "- UUID: Specify the Enrollee\n");
766 return -1;
767 }
768
769 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
770 argv[0]);
771 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
772 printf("Too long WPS_ER_PBC command.\n");
773 return -1;
774 }
775 return wpa_ctrl_command(ctrl, cmd);
776 }
777
778
779 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
780 char *argv[])
781 {
782 char cmd[256];
783 int res;
784
785 if (argc != 2) {
786 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
787 "- UUID: specify which AP to use\n"
788 "- PIN: AP PIN\n");
789 return -1;
790 }
791
792 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
793 argv[0], argv[1]);
794 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
795 printf("Too long WPS_ER_LEARN command.\n");
796 return -1;
797 }
798 return wpa_ctrl_command(ctrl, cmd);
799 }
800
801
802 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
803 char *argv[])
804 {
805 char cmd[256];
806 int res;
807
808 if (argc != 2) {
809 printf("Invalid WPS_ER_SET_CONFIG command: need two "
810 "arguments:\n"
811 "- UUID: specify which AP to use\n"
812 "- Network configuration id\n");
813 return -1;
814 }
815
816 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_SET_CONFIG %s %s",
817 argv[0], argv[1]);
818 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
819 printf("Too long WPS_ER_SET_CONFIG command.\n");
820 return -1;
821 }
822 return wpa_ctrl_command(ctrl, cmd);
823 }
824
825
826 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
827 char *argv[])
828 {
829 char cmd[256];
830 int res;
831
832 if (argc == 5 || argc == 6) {
833 char ssid_hex[2 * 32 + 1];
834 char key_hex[2 * 64 + 1];
835 int i;
836
837 ssid_hex[0] = '\0';
838 for (i = 0; i < 32; i++) {
839 if (argv[2][i] == '\0')
840 break;
841 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
842 }
843
844 key_hex[0] = '\0';
845 if (argc == 6) {
846 for (i = 0; i < 64; i++) {
847 if (argv[5][i] == '\0')
848 break;
849 os_snprintf(&key_hex[i * 2], 3, "%02x",
850 argv[5][i]);
851 }
852 }
853
854 res = os_snprintf(cmd, sizeof(cmd),
855 "WPS_ER_CONFIG %s %s %s %s %s %s",
856 argv[0], argv[1], ssid_hex, argv[3], argv[4],
857 key_hex);
858 } else {
859 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
860 "- AP UUID\n"
861 "- AP PIN\n"
862 "- new SSID\n"
863 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
864 "- new encr (NONE, WEP, TKIP, CCMP)\n"
865 "- new key\n");
866 return -1;
867 }
868
869 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
870 printf("Too long WPS_ER_CONFIG command.\n");
871 return -1;
872 }
873 return wpa_ctrl_command(ctrl, cmd);
874 }
875
876
877 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
878 {
879 char cmd[256];
880 int res;
881
882 if (argc != 1) {
883 printf("Invalid IBSS_RSN command: needs one argument "
884 "(Peer STA MAC address)\n");
885 return -1;
886 }
887
888 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
889 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
890 printf("Too long IBSS_RSN command.\n");
891 return -1;
892 }
893 return wpa_ctrl_command(ctrl, cmd);
894 }
895
896
897 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
898 {
899 char cmd[256];
900 int res;
901
902 if (argc != 1) {
903 printf("Invalid LEVEL command: needs one argument (debug "
904 "level)\n");
905 return -1;
906 }
907 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
908 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
909 printf("Too long LEVEL command.\n");
910 return -1;
911 }
912 return wpa_ctrl_command(ctrl, cmd);
913 }
914
915
916 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
917 {
918 char cmd[256], *pos, *end;
919 int i, ret;
920
921 if (argc < 2) {
922 printf("Invalid IDENTITY command: needs two arguments "
923 "(network id and identity)\n");
924 return -1;
925 }
926
927 end = cmd + sizeof(cmd);
928 pos = cmd;
929 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
930 argv[0], argv[1]);
931 if (ret < 0 || ret >= end - pos) {
932 printf("Too long IDENTITY command.\n");
933 return -1;
934 }
935 pos += ret;
936 for (i = 2; i < argc; i++) {
937 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
938 if (ret < 0 || ret >= end - pos) {
939 printf("Too long IDENTITY command.\n");
940 return -1;
941 }
942 pos += ret;
943 }
944
945 return wpa_ctrl_command(ctrl, cmd);
946 }
947
948
949 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
950 {
951 char cmd[256], *pos, *end;
952 int i, ret;
953
954 if (argc < 2) {
955 printf("Invalid PASSWORD command: needs two arguments "
956 "(network id and password)\n");
957 return -1;
958 }
959
960 end = cmd + sizeof(cmd);
961 pos = cmd;
962 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
963 argv[0], argv[1]);
964 if (ret < 0 || ret >= end - pos) {
965 printf("Too long PASSWORD command.\n");
966 return -1;
967 }
968 pos += ret;
969 for (i = 2; i < argc; i++) {
970 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
971 if (ret < 0 || ret >= end - pos) {
972 printf("Too long PASSWORD command.\n");
973 return -1;
974 }
975 pos += ret;
976 }
977
978 return wpa_ctrl_command(ctrl, cmd);
979 }
980
981
982 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
983 char *argv[])
984 {
985 char cmd[256], *pos, *end;
986 int i, ret;
987
988 if (argc < 2) {
989 printf("Invalid NEW_PASSWORD command: needs two arguments "
990 "(network id and password)\n");
991 return -1;
992 }
993
994 end = cmd + sizeof(cmd);
995 pos = cmd;
996 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
997 argv[0], argv[1]);
998 if (ret < 0 || ret >= end - pos) {
999 printf("Too long NEW_PASSWORD command.\n");
1000 return -1;
1001 }
1002 pos += ret;
1003 for (i = 2; i < argc; i++) {
1004 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1005 if (ret < 0 || ret >= end - pos) {
1006 printf("Too long NEW_PASSWORD command.\n");
1007 return -1;
1008 }
1009 pos += ret;
1010 }
1011
1012 return wpa_ctrl_command(ctrl, cmd);
1013 }
1014
1015
1016 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1017 {
1018 char cmd[256], *pos, *end;
1019 int i, ret;
1020
1021 if (argc < 2) {
1022 printf("Invalid PIN command: needs two arguments "
1023 "(network id and pin)\n");
1024 return -1;
1025 }
1026
1027 end = cmd + sizeof(cmd);
1028 pos = cmd;
1029 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1030 argv[0], argv[1]);
1031 if (ret < 0 || ret >= end - pos) {
1032 printf("Too long PIN command.\n");
1033 return -1;
1034 }
1035 pos += ret;
1036 for (i = 2; i < argc; i++) {
1037 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1038 if (ret < 0 || ret >= end - pos) {
1039 printf("Too long PIN command.\n");
1040 return -1;
1041 }
1042 pos += ret;
1043 }
1044 return wpa_ctrl_command(ctrl, cmd);
1045 }
1046
1047
1048 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1049 {
1050 char cmd[256], *pos, *end;
1051 int i, ret;
1052
1053 if (argc < 2) {
1054 printf("Invalid OTP command: needs two arguments (network "
1055 "id and password)\n");
1056 return -1;
1057 }
1058
1059 end = cmd + sizeof(cmd);
1060 pos = cmd;
1061 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1062 argv[0], argv[1]);
1063 if (ret < 0 || ret >= end - pos) {
1064 printf("Too long OTP command.\n");
1065 return -1;
1066 }
1067 pos += ret;
1068 for (i = 2; i < argc; i++) {
1069 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1070 if (ret < 0 || ret >= end - pos) {
1071 printf("Too long OTP command.\n");
1072 return -1;
1073 }
1074 pos += ret;
1075 }
1076
1077 return wpa_ctrl_command(ctrl, cmd);
1078 }
1079
1080
1081 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1082 char *argv[])
1083 {
1084 char cmd[256], *pos, *end;
1085 int i, ret;
1086
1087 if (argc < 2) {
1088 printf("Invalid PASSPHRASE command: needs two arguments "
1089 "(network id and passphrase)\n");
1090 return -1;
1091 }
1092
1093 end = cmd + sizeof(cmd);
1094 pos = cmd;
1095 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1096 argv[0], argv[1]);
1097 if (ret < 0 || ret >= end - pos) {
1098 printf("Too long PASSPHRASE command.\n");
1099 return -1;
1100 }
1101 pos += ret;
1102 for (i = 2; i < argc; i++) {
1103 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1104 if (ret < 0 || ret >= end - pos) {
1105 printf("Too long PASSPHRASE command.\n");
1106 return -1;
1107 }
1108 pos += ret;
1109 }
1110
1111 return wpa_ctrl_command(ctrl, cmd);
1112 }
1113
1114
1115 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1116 {
1117 char cmd[256], *pos, *end;
1118 int i, ret;
1119
1120 if (argc < 2) {
1121 printf("Invalid BSSID command: needs two arguments (network "
1122 "id and BSSID)\n");
1123 return -1;
1124 }
1125
1126 end = cmd + sizeof(cmd);
1127 pos = cmd;
1128 ret = os_snprintf(pos, end - pos, "BSSID");
1129 if (ret < 0 || ret >= end - pos) {
1130 printf("Too long BSSID command.\n");
1131 return -1;
1132 }
1133 pos += ret;
1134 for (i = 0; i < argc; i++) {
1135 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1136 if (ret < 0 || ret >= end - pos) {
1137 printf("Too long BSSID command.\n");
1138 return -1;
1139 }
1140 pos += ret;
1141 }
1142
1143 return wpa_ctrl_command(ctrl, cmd);
1144 }
1145
1146
1147 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1148 char *argv[])
1149 {
1150 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1151 }
1152
1153
1154 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1155 char *argv[])
1156 {
1157 char cmd[32];
1158 int res;
1159
1160 if (argc < 1) {
1161 printf("Invalid SELECT_NETWORK command: needs one argument "
1162 "(network id)\n");
1163 return -1;
1164 }
1165
1166 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1167 if (res < 0 || (size_t) res >= sizeof(cmd))
1168 return -1;
1169 cmd[sizeof(cmd) - 1] = '\0';
1170
1171 return wpa_ctrl_command(ctrl, cmd);
1172 }
1173
1174
1175 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1176 char *argv[])
1177 {
1178 char cmd[32];
1179 int res;
1180
1181 if (argc < 1) {
1182 printf("Invalid ENABLE_NETWORK command: needs one argument "
1183 "(network id)\n");
1184 return -1;
1185 }
1186
1187 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1188 if (res < 0 || (size_t) res >= sizeof(cmd))
1189 return -1;
1190 cmd[sizeof(cmd) - 1] = '\0';
1191
1192 return wpa_ctrl_command(ctrl, cmd);
1193 }
1194
1195
1196 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1197 char *argv[])
1198 {
1199 char cmd[32];
1200 int res;
1201
1202 if (argc < 1) {
1203 printf("Invalid DISABLE_NETWORK command: needs one argument "
1204 "(network id)\n");
1205 return -1;
1206 }
1207
1208 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1209 if (res < 0 || (size_t) res >= sizeof(cmd))
1210 return -1;
1211 cmd[sizeof(cmd) - 1] = '\0';
1212
1213 return wpa_ctrl_command(ctrl, cmd);
1214 }
1215
1216
1217 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1218 char *argv[])
1219 {
1220 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1221 }
1222
1223
1224 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1225 char *argv[])
1226 {
1227 char cmd[32];
1228 int res;
1229
1230 if (argc < 1) {
1231 printf("Invalid REMOVE_NETWORK command: needs one argument "
1232 "(network id)\n");
1233 return -1;
1234 }
1235
1236 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1237 if (res < 0 || (size_t) res >= sizeof(cmd))
1238 return -1;
1239 cmd[sizeof(cmd) - 1] = '\0';
1240
1241 return wpa_ctrl_command(ctrl, cmd);
1242 }
1243
1244
1245 static void wpa_cli_show_network_variables(void)
1246 {
1247 printf("set_network variables:\n"
1248 " ssid (network name, SSID)\n"
1249 " psk (WPA passphrase or pre-shared key)\n"
1250 " key_mgmt (key management protocol)\n"
1251 " identity (EAP identity)\n"
1252 " password (EAP password)\n"
1253 " ...\n"
1254 "\n"
1255 "Note: Values are entered in the same format as the "
1256 "configuration file is using,\n"
1257 "i.e., strings values need to be inside double quotation "
1258 "marks.\n"
1259 "For example: set_network 1 ssid \"network name\"\n"
1260 "\n"
1261 "Please see wpa_supplicant.conf documentation for full list "
1262 "of\navailable variables.\n");
1263 }
1264
1265
1266 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1267 char *argv[])
1268 {
1269 char cmd[256];
1270 int res;
1271
1272 if (argc == 0) {
1273 wpa_cli_show_network_variables();
1274 return 0;
1275 }
1276
1277 if (argc != 3) {
1278 printf("Invalid SET_NETWORK command: needs three arguments\n"
1279 "(network id, variable name, and value)\n");
1280 return -1;
1281 }
1282
1283 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1284 argv[0], argv[1], argv[2]);
1285 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1286 printf("Too long SET_NETWORK command.\n");
1287 return -1;
1288 }
1289 return wpa_ctrl_command(ctrl, cmd);
1290 }
1291
1292
1293 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1294 char *argv[])
1295 {
1296 char cmd[256];
1297 int res;
1298
1299 if (argc == 0) {
1300 wpa_cli_show_network_variables();
1301 return 0;
1302 }
1303
1304 if (argc != 2) {
1305 printf("Invalid GET_NETWORK command: needs two arguments\n"
1306 "(network id and variable name)\n");
1307 return -1;
1308 }
1309
1310 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1311 argv[0], argv[1]);
1312 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1313 printf("Too long GET_NETWORK command.\n");
1314 return -1;
1315 }
1316 return wpa_ctrl_command(ctrl, cmd);
1317 }
1318
1319
1320 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1321 char *argv[])
1322 {
1323 return wpa_ctrl_command(ctrl, "DISCONNECT");
1324 }
1325
1326
1327 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1328 char *argv[])
1329 {
1330 return wpa_ctrl_command(ctrl, "RECONNECT");
1331 }
1332
1333
1334 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1335 char *argv[])
1336 {
1337 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1338 }
1339
1340
1341 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1342 {
1343 return wpa_ctrl_command(ctrl, "SCAN");
1344 }
1345
1346
1347 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1348 char *argv[])
1349 {
1350 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1351 }
1352
1353
1354 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1355 {
1356 char cmd[64];
1357 int res;
1358
1359 if (argc != 1) {
1360 printf("Invalid BSS command: need one argument (index or "
1361 "BSSID)\n");
1362 return -1;
1363 }
1364
1365 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1366 if (res < 0 || (size_t) res >= sizeof(cmd))
1367 return -1;
1368 cmd[sizeof(cmd) - 1] = '\0';
1369
1370 return wpa_ctrl_command(ctrl, cmd);
1371 }
1372
1373
1374 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1375 char *argv[])
1376 {
1377 char cmd[64];
1378 int res;
1379
1380 if (argc < 1 || argc > 2) {
1381 printf("Invalid GET_CAPABILITY command: need either one or "
1382 "two arguments\n");
1383 return -1;
1384 }
1385
1386 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1387 printf("Invalid GET_CAPABILITY command: second argument, "
1388 "if any, must be 'strict'\n");
1389 return -1;
1390 }
1391
1392 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1393 (argc == 2) ? " strict" : "");
1394 if (res < 0 || (size_t) res >= sizeof(cmd))
1395 return -1;
1396 cmd[sizeof(cmd) - 1] = '\0';
1397
1398 return wpa_ctrl_command(ctrl, cmd);
1399 }
1400
1401
1402 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1403 {
1404 printf("Available interfaces:\n");
1405 return wpa_ctrl_command(ctrl, "INTERFACES");
1406 }
1407
1408
1409 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1410 {
1411 if (argc < 1) {
1412 wpa_cli_list_interfaces(ctrl);
1413 return 0;
1414 }
1415
1416 wpa_cli_close_connection();
1417 os_free(ctrl_ifname);
1418 ctrl_ifname = os_strdup(argv[0]);
1419
1420 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1421 printf("Connected to interface '%s.\n", ctrl_ifname);
1422 } else {
1423 printf("Could not connect to interface '%s' - re-trying\n",
1424 ctrl_ifname);
1425 }
1426 return 0;
1427 }
1428
1429
1430 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1431 char *argv[])
1432 {
1433 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1434 }
1435
1436
1437 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1438 char *argv[])
1439 {
1440 return wpa_ctrl_command(ctrl, "TERMINATE");
1441 }
1442
1443
1444 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1445 char *argv[])
1446 {
1447 char cmd[256];
1448 int res;
1449
1450 if (argc < 1) {
1451 printf("Invalid INTERFACE_ADD command: needs at least one "
1452 "argument (interface name)\n"
1453 "All arguments: ifname confname driver ctrl_interface "
1454 "driver_param bridge_name\n");
1455 return -1;
1456 }
1457
1458 /*
1459 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1460 * <driver_param>TAB<bridge_name>
1461 */
1462 res = os_snprintf(cmd, sizeof(cmd),
1463 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1464 argv[0],
1465 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1466 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1467 argc > 5 ? argv[5] : "");
1468 if (res < 0 || (size_t) res >= sizeof(cmd))
1469 return -1;
1470 cmd[sizeof(cmd) - 1] = '\0';
1471 return wpa_ctrl_command(ctrl, cmd);
1472 }
1473
1474
1475 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1476 char *argv[])
1477 {
1478 char cmd[128];
1479 int res;
1480
1481 if (argc != 1) {
1482 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1483 "(interface name)\n");
1484 return -1;
1485 }
1486
1487 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1488 if (res < 0 || (size_t) res >= sizeof(cmd))
1489 return -1;
1490 cmd[sizeof(cmd) - 1] = '\0';
1491 return wpa_ctrl_command(ctrl, cmd);
1492 }
1493
1494
1495 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1496 char *argv[])
1497 {
1498 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1499 }
1500
1501
1502 #ifdef CONFIG_AP
1503 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1504 {
1505 char buf[64];
1506 if (argc != 1) {
1507 printf("Invalid 'sta' command - exactly one argument, STA "
1508 "address, is required.\n");
1509 return -1;
1510 }
1511 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1512 return wpa_ctrl_command(ctrl, buf);
1513 }
1514
1515
1516 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1517 char *addr, size_t addr_len)
1518 {
1519 char buf[4096], *pos;
1520 size_t len;
1521 int ret;
1522
1523 if (ctrl_conn == NULL) {
1524 printf("Not connected to hostapd - command dropped.\n");
1525 return -1;
1526 }
1527 len = sizeof(buf) - 1;
1528 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1529 wpa_cli_msg_cb);
1530 if (ret == -2) {
1531 printf("'%s' command timed out.\n", cmd);
1532 return -2;
1533 } else if (ret < 0) {
1534 printf("'%s' command failed.\n", cmd);
1535 return -1;
1536 }
1537
1538 buf[len] = '\0';
1539 if (memcmp(buf, "FAIL", 4) == 0)
1540 return -1;
1541 printf("%s", buf);
1542
1543 pos = buf;
1544 while (*pos != '\0' && *pos != '\n')
1545 pos++;
1546 *pos = '\0';
1547 os_strlcpy(addr, buf, addr_len);
1548 return 0;
1549 }
1550
1551
1552 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1553 {
1554 char addr[32], cmd[64];
1555
1556 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1557 return 0;
1558 do {
1559 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1560 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1561
1562 return -1;
1563 }
1564 #endif /* CONFIG_AP */
1565
1566
1567 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1568 {
1569 return wpa_ctrl_command(ctrl, "SUSPEND");
1570 }
1571
1572
1573 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1574 {
1575 return wpa_ctrl_command(ctrl, "RESUME");
1576 }
1577
1578
1579 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1580 {
1581 return wpa_ctrl_command(ctrl, "DROP_SA");
1582 }
1583
1584
1585 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1586 {
1587 char cmd[128];
1588 int res;
1589
1590 if (argc != 1) {
1591 printf("Invalid ROAM command: needs one argument "
1592 "(target AP's BSSID)\n");
1593 return -1;
1594 }
1595
1596 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1597 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1598 printf("Too long ROAM command.\n");
1599 return -1;
1600 }
1601 return wpa_ctrl_command(ctrl, cmd);
1602 }
1603
1604
1605 #ifdef CONFIG_P2P
1606
1607 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1608 {
1609 char cmd[128];
1610 int res;
1611
1612 if (argc == 0)
1613 return wpa_ctrl_command(ctrl, "P2P_FIND");
1614
1615 if (argc > 1)
1616 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1617 argv[0], argv[1]);
1618 else
1619 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
1620 if (res < 0 || (size_t) res >= sizeof(cmd))
1621 return -1;
1622 cmd[sizeof(cmd) - 1] = '\0';
1623 return wpa_ctrl_command(ctrl, cmd);
1624 }
1625
1626
1627 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1628 char *argv[])
1629 {
1630 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1631 }
1632
1633
1634 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1635 char *argv[])
1636 {
1637 char cmd[128];
1638 int res;
1639
1640 if (argc < 2) {
1641 printf("Invalid P2P_CONNECT command: needs at least two "
1642 "arguments (address and pbc/PIN)\n");
1643 return -1;
1644 }
1645
1646 if (argc > 4)
1647 res = os_snprintf(cmd, sizeof(cmd),
1648 "P2P_CONNECT %s %s %s %s %s",
1649 argv[0], argv[1], argv[2], argv[3],
1650 argv[4]);
1651 else if (argc > 3)
1652 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1653 argv[0], argv[1], argv[2], argv[3]);
1654 else if (argc > 2)
1655 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1656 argv[0], argv[1], argv[2]);
1657 else
1658 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1659 argv[0], argv[1]);
1660 if (res < 0 || (size_t) res >= sizeof(cmd))
1661 return -1;
1662 cmd[sizeof(cmd) - 1] = '\0';
1663 return wpa_ctrl_command(ctrl, cmd);
1664 }
1665
1666
1667 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1668 char *argv[])
1669 {
1670 char cmd[128];
1671 int res;
1672
1673 if (argc == 0)
1674 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
1675
1676 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
1677 if (res < 0 || (size_t) res >= sizeof(cmd))
1678 return -1;
1679 cmd[sizeof(cmd) - 1] = '\0';
1680 return wpa_ctrl_command(ctrl, cmd);
1681 }
1682
1683
1684 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1685 char *argv[])
1686 {
1687 char cmd[128];
1688 int res;
1689
1690 if (argc != 1) {
1691 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
1692 "(interface name)\n");
1693 return -1;
1694 }
1695
1696 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
1697 if (res < 0 || (size_t) res >= sizeof(cmd))
1698 return -1;
1699 cmd[sizeof(cmd) - 1] = '\0';
1700 return wpa_ctrl_command(ctrl, cmd);
1701 }
1702
1703
1704 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1705 char *argv[])
1706 {
1707 char cmd[128];
1708 int res;
1709
1710 if (argc == 0)
1711 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
1712
1713 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s", argv[0]);
1714 if (res < 0 || (size_t) res >= sizeof(cmd))
1715 return -1;
1716 cmd[sizeof(cmd) - 1] = '\0';
1717 return wpa_ctrl_command(ctrl, cmd);
1718 }
1719
1720
1721 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1722 char *argv[])
1723 {
1724 char cmd[128];
1725 int res;
1726
1727 if (argc != 2) {
1728 printf("Invalid P2P_PROV_DISC command: needs two arguments "
1729 "(address and config method\n"
1730 "(display, keypad, or pbc)\n");
1731 return -1;
1732 }
1733
1734 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
1735 argv[0], argv[1]);
1736 if (res < 0 || (size_t) res >= sizeof(cmd))
1737 return -1;
1738 cmd[sizeof(cmd) - 1] = '\0';
1739 return wpa_ctrl_command(ctrl, cmd);
1740 }
1741
1742
1743 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1744 char *argv[])
1745 {
1746 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1747 }
1748
1749
1750 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1751 char *argv[])
1752 {
1753 char cmd[4096];
1754 int res;
1755
1756 if (argc != 2 && argc != 4) {
1757 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1758 "arguments (address and TLVs) or four arguments "
1759 "(address, \"upnp\", version, search target "
1760 "(SSDP ST:)\n");
1761 return -1;
1762 }
1763
1764 if (argc == 4)
1765 res = os_snprintf(cmd, sizeof(cmd),
1766 "P2P_SERV_DISC_REQ %s %s %s %s",
1767 argv[0], argv[1], argv[2], argv[3]);
1768 else
1769 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
1770 argv[0], argv[1]);
1771 if (res < 0 || (size_t) res >= sizeof(cmd))
1772 return -1;
1773 cmd[sizeof(cmd) - 1] = '\0';
1774 return wpa_ctrl_command(ctrl, cmd);
1775 }
1776
1777
1778 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1779 int argc, char *argv[])
1780 {
1781 char cmd[128];
1782 int res;
1783
1784 if (argc != 1) {
1785 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
1786 "argument (pending request identifier)\n");
1787 return -1;
1788 }
1789
1790 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
1791 argv[0]);
1792 if (res < 0 || (size_t) res >= sizeof(cmd))
1793 return -1;
1794 cmd[sizeof(cmd) - 1] = '\0';
1795 return wpa_ctrl_command(ctrl, cmd);
1796 }
1797
1798
1799 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1800 char *argv[])
1801 {
1802 char cmd[4096];
1803 int res;
1804
1805 if (argc != 4) {
1806 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1807 "arguments (freq, address, dialog token, and TLVs)\n");
1808 return -1;
1809 }
1810
1811 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1812 argv[0], argv[1], argv[2], argv[3]);
1813 if (res < 0 || (size_t) res >= sizeof(cmd))
1814 return -1;
1815 cmd[sizeof(cmd) - 1] = '\0';
1816 return wpa_ctrl_command(ctrl, cmd);
1817 }
1818
1819
1820 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1821 char *argv[])
1822 {
1823 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1824 }
1825
1826
1827 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1828 int argc, char *argv[])
1829 {
1830 char cmd[128];
1831 int res;
1832
1833 if (argc != 1) {
1834 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
1835 "argument (external processing: 0/1)\n");
1836 return -1;
1837 }
1838
1839 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
1840 argv[0]);
1841 if (res < 0 || (size_t) res >= sizeof(cmd))
1842 return -1;
1843 cmd[sizeof(cmd) - 1] = '\0';
1844 return wpa_ctrl_command(ctrl, cmd);
1845 }
1846
1847
1848 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1849 char *argv[])
1850 {
1851 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1852 }
1853
1854
1855 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1856 char *argv[])
1857 {
1858 char cmd[4096];
1859 int res;
1860
1861 if (argc != 3 && argc != 4) {
1862 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1863 "arguments\n");
1864 return -1;
1865 }
1866
1867 if (argc == 4)
1868 res = os_snprintf(cmd, sizeof(cmd),
1869 "P2P_SERVICE_ADD %s %s %s %s",
1870 argv[0], argv[1], argv[2], argv[3]);
1871 else
1872 res = os_snprintf(cmd, sizeof(cmd),
1873 "P2P_SERVICE_ADD %s %s %s",
1874 argv[0], argv[1], argv[2]);
1875 if (res < 0 || (size_t) res >= sizeof(cmd))
1876 return -1;
1877 cmd[sizeof(cmd) - 1] = '\0';
1878 return wpa_ctrl_command(ctrl, cmd);
1879 }
1880
1881
1882 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1883 char *argv[])
1884 {
1885 char cmd[4096];
1886 int res;
1887
1888 if (argc != 2 && argc != 3) {
1889 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1890 "arguments\n");
1891 return -1;
1892 }
1893
1894 if (argc == 3)
1895 res = os_snprintf(cmd, sizeof(cmd),
1896 "P2P_SERVICE_DEL %s %s %s",
1897 argv[0], argv[1], argv[2]);
1898 else
1899 res = os_snprintf(cmd, sizeof(cmd),
1900 "P2P_SERVICE_DEL %s %s",
1901 argv[0], argv[1]);
1902 if (res < 0 || (size_t) res >= sizeof(cmd))
1903 return -1;
1904 cmd[sizeof(cmd) - 1] = '\0';
1905 return wpa_ctrl_command(ctrl, cmd);
1906 }
1907
1908
1909 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1910 int argc, char *argv[])
1911 {
1912 char cmd[128];
1913 int res;
1914
1915 if (argc != 1) {
1916 printf("Invalid P2P_REJECT command: needs one argument "
1917 "(peer address)\n");
1918 return -1;
1919 }
1920
1921 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
1922 if (res < 0 || (size_t) res >= sizeof(cmd))
1923 return -1;
1924 cmd[sizeof(cmd) - 1] = '\0';
1925 return wpa_ctrl_command(ctrl, cmd);
1926 }
1927
1928
1929 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1930 int argc, char *argv[])
1931 {
1932 char cmd[128];
1933 int res;
1934
1935 if (argc < 1) {
1936 printf("Invalid P2P_INVITE command: needs at least one "
1937 "argument\n");
1938 return -1;
1939 }
1940
1941 if (argc > 2)
1942 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
1943 argv[0], argv[1], argv[2]);
1944 else if (argc > 1)
1945 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
1946 argv[0], argv[1]);
1947 else
1948 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
1949 if (res < 0 || (size_t) res >= sizeof(cmd))
1950 return -1;
1951 cmd[sizeof(cmd) - 1] = '\0';
1952 return wpa_ctrl_command(ctrl, cmd);
1953 }
1954
1955
1956 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1957 {
1958 char buf[64];
1959 if (argc != 1) {
1960 printf("Invalid 'p2p_peer' command - exactly one argument, "
1961 "P2P peer device address, is required.\n");
1962 return -1;
1963 }
1964 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
1965 return wpa_ctrl_command(ctrl, buf);
1966 }
1967
1968
1969 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1970 char *addr, size_t addr_len,
1971 int discovered)
1972 {
1973 char buf[4096], *pos;
1974 size_t len;
1975 int ret;
1976
1977 if (ctrl_conn == NULL)
1978 return -1;
1979 len = sizeof(buf) - 1;
1980 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1981 wpa_cli_msg_cb);
1982 if (ret == -2) {
1983 printf("'%s' command timed out.\n", cmd);
1984 return -2;
1985 } else if (ret < 0) {
1986 printf("'%s' command failed.\n", cmd);
1987 return -1;
1988 }
1989
1990 buf[len] = '\0';
1991 if (memcmp(buf, "FAIL", 4) == 0)
1992 return -1;
1993
1994 pos = buf;
1995 while (*pos != '\0' && *pos != '\n')
1996 pos++;
1997 *pos++ = '\0';
1998 os_strlcpy(addr, buf, addr_len);
1999 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2000 printf("%s\n", addr);
2001 return 0;
2002 }
2003
2004
2005 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2006 {
2007 char addr[32], cmd[64];
2008 int discovered;
2009
2010 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2011
2012 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2013 addr, sizeof(addr), discovered))
2014 return 0;
2015 do {
2016 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2017 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2018 discovered) == 0);
2019
2020 return -1;
2021 }
2022
2023
2024 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2025 {
2026 char cmd[100];
2027 int res;
2028
2029 if (argc != 2) {
2030 printf("Invalid P2P_SET command: needs two arguments (field, "
2031 "value)\n");
2032 return -1;
2033 }
2034
2035 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2036 if (res < 0 || (size_t) res >= sizeof(cmd))
2037 return -1;
2038 cmd[sizeof(cmd) - 1] = '\0';
2039 return wpa_ctrl_command(ctrl, cmd);
2040 }
2041
2042
2043 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2044 {
2045 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2046 }
2047
2048
2049 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2050 char *argv[])
2051 {
2052 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2053 }
2054
2055
2056 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2057 char *argv[])
2058 {
2059 char cmd[100];
2060 int res;
2061
2062 if (argc != 0 && argc != 2 && argc != 4) {
2063 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2064 "(preferred duration, interval; in microsecods).\n"
2065 "Optional second pair can be used to provide "
2066 "acceptable values.\n");
2067 return -1;
2068 }
2069
2070 if (argc == 4)
2071 res = os_snprintf(cmd, sizeof(cmd),
2072 "P2P_PRESENCE_REQ %s %s %s %s",
2073 argv[0], argv[1], argv[2], argv[3]);
2074 else if (argc == 2)
2075 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2076 argv[0], argv[1]);
2077 else
2078 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2079 if (res < 0 || (size_t) res >= sizeof(cmd))
2080 return -1;
2081 cmd[sizeof(cmd) - 1] = '\0';
2082 return wpa_ctrl_command(ctrl, cmd);
2083 }
2084
2085
2086 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2087 char *argv[])
2088 {
2089 char cmd[100];
2090 int res;
2091
2092 if (argc != 0 && argc != 2) {
2093 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2094 "(availability period, availability interval; in "
2095 "millisecods).\n"
2096 "Extended Listen Timing can be cancelled with this "
2097 "command when used without parameters.\n");
2098 return -1;
2099 }
2100
2101 if (argc == 2)
2102 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2103 argv[0], argv[1]);
2104 else
2105 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2106 if (res < 0 || (size_t) res >= sizeof(cmd))
2107 return -1;
2108 cmd[sizeof(cmd) - 1] = '\0';
2109 return wpa_ctrl_command(ctrl, cmd);
2110 }
2111
2112 #endif /* CONFIG_P2P */
2113
2114
2115 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2116 char *argv[])
2117 {
2118 char cmd[256];
2119 int res;
2120
2121 if (argc != 1) {
2122 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2123 "(0/1 = disable/enable automatic reconnection)\n");
2124 return -1;
2125 }
2126 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2127 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2128 printf("Too long STA_AUTOCONNECT command.\n");
2129 return -1;
2130 }
2131 return wpa_ctrl_command(ctrl, cmd);
2132 }
2133
2134
2135 enum wpa_cli_cmd_flags {
2136 cli_cmd_flag_none = 0x00,
2137 cli_cmd_flag_sensitive = 0x01
2138 };
2139
2140 struct wpa_cli_cmd {
2141 const char *cmd;
2142 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2143 enum wpa_cli_cmd_flags flags;
2144 const char *usage;
2145 };
2146
2147 static struct wpa_cli_cmd wpa_cli_commands[] = {
2148 { "status", wpa_cli_cmd_status,
2149 cli_cmd_flag_none,
2150 "[verbose] = get current WPA/EAPOL/EAP status" },
2151 { "ping", wpa_cli_cmd_ping,
2152 cli_cmd_flag_none,
2153 "= pings wpa_supplicant" },
2154 { "note", wpa_cli_cmd_note,
2155 cli_cmd_flag_none,
2156 "<text> = add a note to wpa_supplicant debug log" },
2157 { "mib", wpa_cli_cmd_mib,
2158 cli_cmd_flag_none,
2159 "= get MIB variables (dot1x, dot11)" },
2160 { "help", wpa_cli_cmd_help,
2161 cli_cmd_flag_none,
2162 "= show this usage help" },
2163 { "interface", wpa_cli_cmd_interface,
2164 cli_cmd_flag_none,
2165 "[ifname] = show interfaces/select interface" },
2166 { "level", wpa_cli_cmd_level,
2167 cli_cmd_flag_none,
2168 "<debug level> = change debug level" },
2169 { "license", wpa_cli_cmd_license,
2170 cli_cmd_flag_none,
2171 "= show full wpa_cli license" },
2172 { "quit", wpa_cli_cmd_quit,
2173 cli_cmd_flag_none,
2174 "= exit wpa_cli" },
2175 { "set", wpa_cli_cmd_set,
2176 cli_cmd_flag_none,
2177 "= set variables (shows list of variables when run without "
2178 "arguments)" },
2179 { "get", wpa_cli_cmd_get,
2180 cli_cmd_flag_none,
2181 "<name> = get information" },
2182 { "logon", wpa_cli_cmd_logon,
2183 cli_cmd_flag_none,
2184 "= IEEE 802.1X EAPOL state machine logon" },
2185 { "logoff", wpa_cli_cmd_logoff,
2186 cli_cmd_flag_none,
2187 "= IEEE 802.1X EAPOL state machine logoff" },
2188 { "pmksa", wpa_cli_cmd_pmksa,
2189 cli_cmd_flag_none,
2190 "= show PMKSA cache" },
2191 { "reassociate", wpa_cli_cmd_reassociate,
2192 cli_cmd_flag_none,
2193 "= force reassociation" },
2194 { "preauthenticate", wpa_cli_cmd_preauthenticate,
2195 cli_cmd_flag_none,
2196 "<BSSID> = force preauthentication" },
2197 { "identity", wpa_cli_cmd_identity,
2198 cli_cmd_flag_none,
2199 "<network id> <identity> = configure identity for an SSID" },
2200 { "password", wpa_cli_cmd_password,
2201 cli_cmd_flag_sensitive,
2202 "<network id> <password> = configure password for an SSID" },
2203 { "new_password", wpa_cli_cmd_new_password,
2204 cli_cmd_flag_sensitive,
2205 "<network id> <password> = change password for an SSID" },
2206 { "pin", wpa_cli_cmd_pin,
2207 cli_cmd_flag_sensitive,
2208 "<network id> <pin> = configure pin for an SSID" },
2209 { "otp", wpa_cli_cmd_otp,
2210 cli_cmd_flag_sensitive,
2211 "<network id> <password> = configure one-time-password for an SSID"
2212 },
2213 { "passphrase", wpa_cli_cmd_passphrase,
2214 cli_cmd_flag_sensitive,
2215 "<network id> <passphrase> = configure private key passphrase\n"
2216 " for an SSID" },
2217 { "bssid", wpa_cli_cmd_bssid,
2218 cli_cmd_flag_none,
2219 "<network id> <BSSID> = set preferred BSSID for an SSID" },
2220 { "list_networks", wpa_cli_cmd_list_networks,
2221 cli_cmd_flag_none,
2222 "= list configured networks" },
2223 { "select_network", wpa_cli_cmd_select_network,
2224 cli_cmd_flag_none,
2225 "<network id> = select a network (disable others)" },
2226 { "enable_network", wpa_cli_cmd_enable_network,
2227 cli_cmd_flag_none,
2228 "<network id> = enable a network" },
2229 { "disable_network", wpa_cli_cmd_disable_network,
2230 cli_cmd_flag_none,
2231 "<network id> = disable a network" },
2232 { "add_network", wpa_cli_cmd_add_network,
2233 cli_cmd_flag_none,
2234 "= add a network" },
2235 { "remove_network", wpa_cli_cmd_remove_network,
2236 cli_cmd_flag_none,
2237 "<network id> = remove a network" },
2238 { "set_network", wpa_cli_cmd_set_network,
2239 cli_cmd_flag_sensitive,
2240 "<network id> <variable> <value> = set network variables (shows\n"
2241 " list of variables when run without arguments)" },
2242 { "get_network", wpa_cli_cmd_get_network,
2243 cli_cmd_flag_none,
2244 "<network id> <variable> = get network variables" },
2245 { "save_config", wpa_cli_cmd_save_config,
2246 cli_cmd_flag_none,
2247 "= save the current configuration" },
2248 { "disconnect", wpa_cli_cmd_disconnect,
2249 cli_cmd_flag_none,
2250 "= disconnect and wait for reassociate/reconnect command before\n"
2251 " connecting" },
2252 { "reconnect", wpa_cli_cmd_reconnect,
2253 cli_cmd_flag_none,
2254 "= like reassociate, but only takes effect if already disconnected"
2255 },
2256 { "scan", wpa_cli_cmd_scan,
2257 cli_cmd_flag_none,
2258 "= request new BSS scan" },
2259 { "scan_results", wpa_cli_cmd_scan_results,
2260 cli_cmd_flag_none,
2261 "= get latest scan results" },
2262 { "bss", wpa_cli_cmd_bss,
2263 cli_cmd_flag_none,
2264 "<<idx> | <bssid>> = get detailed scan result info" },
2265 { "get_capability", wpa_cli_cmd_get_capability,
2266 cli_cmd_flag_none,
2267 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2268 { "reconfigure", wpa_cli_cmd_reconfigure,
2269 cli_cmd_flag_none,
2270 "= force wpa_supplicant to re-read its configuration file" },
2271 { "terminate", wpa_cli_cmd_terminate,
2272 cli_cmd_flag_none,
2273 "= terminate wpa_supplicant" },
2274 { "interface_add", wpa_cli_cmd_interface_add,
2275 cli_cmd_flag_none,
2276 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2277 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2278 " are optional" },
2279 { "interface_remove", wpa_cli_cmd_interface_remove,
2280 cli_cmd_flag_none,
2281 "<ifname> = removes the interface" },
2282 { "interface_list", wpa_cli_cmd_interface_list,
2283 cli_cmd_flag_none,
2284 "= list available interfaces" },
2285 { "ap_scan", wpa_cli_cmd_ap_scan,
2286 cli_cmd_flag_none,
2287 "<value> = set ap_scan parameter" },
2288 { "stkstart", wpa_cli_cmd_stkstart,
2289 cli_cmd_flag_none,
2290 "<addr> = request STK negotiation with <addr>" },
2291 { "ft_ds", wpa_cli_cmd_ft_ds,
2292 cli_cmd_flag_none,
2293 "<addr> = request over-the-DS FT with <addr>" },
2294 { "wps_pbc", wpa_cli_cmd_wps_pbc,
2295 cli_cmd_flag_none,
2296 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2297 { "wps_pin", wpa_cli_cmd_wps_pin,
2298 cli_cmd_flag_sensitive,
2299 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2300 "hardcoded)" },
2301 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2302 cli_cmd_flag_sensitive,
2303 "<PIN> = verify PIN checksum" },
2304 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2305 "Cancels the pending WPS operation" },
2306 #ifdef CONFIG_WPS_OOB
2307 { "wps_oob", wpa_cli_cmd_wps_oob,
2308 cli_cmd_flag_sensitive,
2309 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2310 #endif /* CONFIG_WPS_OOB */
2311 { "wps_reg", wpa_cli_cmd_wps_reg,
2312 cli_cmd_flag_sensitive,
2313 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2314 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2315 cli_cmd_flag_none,
2316 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2317 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2318 cli_cmd_flag_none,
2319 "= stop Wi-Fi Protected Setup External Registrar" },
2320 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2321 cli_cmd_flag_sensitive,
2322 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2323 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2324 cli_cmd_flag_none,
2325 "<UUID> = accept an Enrollee PBC using External Registrar" },
2326 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2327 cli_cmd_flag_sensitive,
2328 "<UUID> <PIN> = learn AP configuration" },
2329 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2330 cli_cmd_flag_none,
2331 "<UUID> <network id> = set AP configuration for enrolling" },
2332 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2333 cli_cmd_flag_sensitive,
2334 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2335 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2336 cli_cmd_flag_none,
2337 "<addr> = request RSN authentication with <addr> in IBSS" },
2338 #ifdef CONFIG_AP
2339 { "sta", wpa_cli_cmd_sta,
2340 cli_cmd_flag_none,
2341 "<addr> = get information about an associated station (AP)" },
2342 { "all_sta", wpa_cli_cmd_all_sta,
2343 cli_cmd_flag_none,
2344 "= get information about all associated stations (AP)" },
2345 #endif /* CONFIG_AP */
2346 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2347 "= notification of suspend/hibernate" },
2348 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2349 "= notification of resume/thaw" },
2350 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2351 "= drop SA without deauth/disassoc (test command)" },
2352 { "roam", wpa_cli_cmd_roam,
2353 cli_cmd_flag_none,
2354 "<addr> = roam to the specified BSS" },
2355 #ifdef CONFIG_P2P
2356 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2357 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2358 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2359 "= stop P2P Devices search" },
2360 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2361 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2362 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2363 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2364 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2365 "<ifname> = remote P2P group interface (terminate group if GO)" },
2366 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2367 "= add a new P2P group (local end as GO)" },
2368 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2369 "<addr> <method> = request provisioning discovery" },
2370 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2371 cli_cmd_flag_none,
2372 "= get the passphrase for a group (GO only)" },
2373 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2374 cli_cmd_flag_none,
2375 "<addr> <TLVs> = schedule service discovery request" },
2376 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2377 cli_cmd_flag_none,
2378 "<id> = cancel pending service discovery request" },
2379 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2380 cli_cmd_flag_none,
2381 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2382 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2383 cli_cmd_flag_none,
2384 "= indicate change in local services" },
2385 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2386 cli_cmd_flag_none,
2387 "<external> = set external processing of service discovery" },
2388 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2389 cli_cmd_flag_none,
2390 "= remove all stored service entries" },
2391 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2392 cli_cmd_flag_none,
2393 "<bonjour|upnp> <query|version> <response|service> = add a local "
2394 "service" },
2395 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2396 cli_cmd_flag_none,
2397 "<bonjour|upnp> <query|version> [|service] = remove a local "
2398 "service" },
2399 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2400 cli_cmd_flag_none,
2401 "<addr> = reject connection attempts from a specific peer" },
2402 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2403 cli_cmd_flag_none,
2404 "<cmd> [peer=addr] = invite peer" },
2405 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2406 "[discovered] = list known (optionally, only fully discovered) P2P "
2407 "peers" },
2408 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2409 "<address> = show information about known P2P peer" },
2410 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2411 "<field> <value> = set a P2P parameter" },
2412 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2413 "= flush P2P state" },
2414 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
2415 "= cancel P2P group formation" },
2416 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2417 "[<duration> <interval>] [<duration> <interval>] = request GO "
2418 "presence" },
2419 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2420 "[<period> <interval>] = set extended listen timing" },
2421 #endif /* CONFIG_P2P */
2422 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2423 "<0/1> = disable/enable automatic reconnection" },
2424 { NULL, NULL, cli_cmd_flag_none, NULL }
2425 };
2426
2427
2428 /*
2429 * Prints command usage, lines are padded with the specified string.
2430 */
2431 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2432 {
2433 char c;
2434 size_t n;
2435
2436 printf("%s%s ", pad, cmd->cmd);
2437 for (n = 0; (c = cmd->usage[n]); n++) {
2438 printf("%c", c);
2439 if (c == '\n')
2440 printf("%s", pad);
2441 }
2442 printf("\n");
2443 }
2444
2445
2446 static void print_help(void)
2447 {
2448 int n;
2449 printf("commands:\n");
2450 for (n = 0; wpa_cli_commands[n].cmd; n++)
2451 print_cmd_help(&wpa_cli_commands[n], " ");
2452 }
2453
2454
2455 #ifdef CONFIG_READLINE
2456 static int cmd_has_sensitive_data(const char *cmd)
2457 {
2458 const char *c, *delim;
2459 int n;
2460 size_t len;
2461
2462 delim = os_strchr(cmd, ' ');
2463 if (delim)
2464 len = delim - cmd;
2465 else
2466 len = os_strlen(cmd);
2467
2468 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2469 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2470 return (wpa_cli_commands[n].flags &
2471 cli_cmd_flag_sensitive);
2472 }
2473 return 0;
2474 }
2475 #endif /* CONFIG_READLINE */
2476
2477
2478 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2479 {
2480 struct wpa_cli_cmd *cmd, *match = NULL;
2481 int count;
2482 int ret = 0;
2483
2484 count = 0;
2485 cmd = wpa_cli_commands;
2486 while (cmd->cmd) {
2487 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2488 {
2489 match = cmd;
2490 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2491 /* we have an exact match */
2492 count = 1;
2493 break;
2494 }
2495 count++;
2496 }
2497 cmd++;
2498 }
2499
2500 if (count > 1) {
2501 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2502 cmd = wpa_cli_commands;
2503 while (cmd->cmd) {
2504 if (os_strncasecmp(cmd->cmd, argv[0],
2505 os_strlen(argv[0])) == 0) {
2506 printf(" %s", cmd->cmd);
2507 }
2508 cmd++;
2509 }
2510 printf("\n");
2511 ret = 1;
2512 } else if (count == 0) {
2513 printf("Unknown command '%s'\n", argv[0]);
2514 ret = 1;
2515 } else {
2516 ret = match->handler(ctrl, argc - 1, &argv[1]);
2517 }
2518
2519 return ret;
2520 }
2521
2522
2523 static int str_match(const char *a, const char *b)
2524 {
2525 return os_strncmp(a, b, os_strlen(b)) == 0;
2526 }
2527
2528
2529 static int wpa_cli_exec(const char *program, const char *arg1,
2530 const char *arg2)
2531 {
2532 char *cmd;
2533 size_t len;
2534 int res;
2535 int ret = 0;
2536
2537 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2538 cmd = os_malloc(len);
2539 if (cmd == NULL)
2540 return -1;
2541 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2542 if (res < 0 || (size_t) res >= len) {
2543 os_free(cmd);
2544 return -1;
2545 }
2546 cmd[len - 1] = '\0';
2547 #ifndef _WIN32_WCE
2548 if (system(cmd) < 0)
2549 ret = -1;
2550 #endif /* _WIN32_WCE */
2551 os_free(cmd);
2552
2553 return ret;
2554 }
2555
2556
2557 static void wpa_cli_action_process(const char *msg)
2558 {
2559 const char *pos;
2560 char *copy = NULL, *id, *pos2;
2561
2562 pos = msg;
2563 if (*pos == '<') {
2564 /* skip priority */
2565 pos = os_strchr(pos, '>');
2566 if (pos)
2567 pos++;
2568 else
2569 pos = msg;
2570 }
2571
2572 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2573 int new_id = -1;
2574 os_unsetenv("WPA_ID");
2575 os_unsetenv("WPA_ID_STR");
2576 os_unsetenv("WPA_CTRL_DIR");
2577
2578 pos = os_strstr(pos, "[id=");
2579 if (pos)
2580 copy = os_strdup(pos + 4);
2581
2582 if (copy) {
2583 pos2 = id = copy;
2584 while (*pos2 && *pos2 != ' ')
2585 pos2++;
2586 *pos2++ = '\0';
2587 new_id = atoi(id);
2588 os_setenv("WPA_ID", id, 1);
2589 while (*pos2 && *pos2 != '=')
2590 pos2++;
2591 if (*pos2 == '=')
2592 pos2++;
2593 id = pos2;
2594 while (*pos2 && *pos2 != ']')
2595 pos2++;
2596 *pos2 = '\0';
2597 os_setenv("WPA_ID_STR", id, 1);
2598 os_free(copy);
2599 }
2600
2601 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2602
2603 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2604 wpa_cli_connected = 1;
2605 wpa_cli_last_id = new_id;
2606 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2607 }
2608 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2609 if (wpa_cli_connected) {
2610 wpa_cli_connected = 0;
2611 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2612 }
2613 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2614 wpa_cli_exec(action_file, ctrl_ifname, pos);
2615 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2616 wpa_cli_exec(action_file, ctrl_ifname, pos);
2617 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2618 wpa_cli_exec(action_file, ctrl_ifname, pos);
2619 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2620 wpa_cli_exec(action_file, ctrl_ifname, pos);
2621 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2622 wpa_cli_exec(action_file, ctrl_ifname, pos);
2623 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2624 wpa_cli_exec(action_file, ctrl_ifname, pos);
2625 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2626 printf("wpa_supplicant is terminating - stop monitoring\n");
2627 wpa_cli_quit = 1;
2628 }
2629 }
2630
2631
2632 #ifndef CONFIG_ANSI_C_EXTRA
2633 static void wpa_cli_action_cb(char *msg, size_t len)
2634 {
2635 wpa_cli_action_process(msg);
2636 }
2637 #endif /* CONFIG_ANSI_C_EXTRA */
2638
2639
2640 static void wpa_cli_reconnect(void)
2641 {
2642 wpa_cli_close_connection();
2643 wpa_cli_open_connection(ctrl_ifname, 1);
2644 }
2645
2646
2647 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
2648 {
2649 if (ctrl_conn == NULL) {
2650 wpa_cli_reconnect();
2651 return;
2652 }
2653 while (wpa_ctrl_pending(ctrl) > 0) {
2654 char buf[256];
2655 size_t len = sizeof(buf) - 1;
2656 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2657 buf[len] = '\0';
2658 if (action_monitor)
2659 wpa_cli_action_process(buf);
2660 else {
2661 if (wpa_cli_show_event(buf)) {
2662 printf("\r%s\n", buf);
2663 readline_redraw();
2664 }
2665 }
2666 } else {
2667 printf("Could not read pending message.\n");
2668 break;
2669 }
2670 }
2671
2672 if (wpa_ctrl_pending(ctrl) < 0) {
2673 printf("Connection to wpa_supplicant lost - trying to "
2674 "reconnect\n");
2675 wpa_cli_reconnect();
2676 }
2677 }
2678
2679 #define max_args 10
2680
2681 static int tokenize_cmd(char *cmd, char *argv[])
2682 {
2683 char *pos;
2684 int argc = 0;
2685
2686 pos = cmd;
2687 for (;;) {
2688 while (*pos == ' ')
2689 pos++;
2690 if (*pos == '\0')
2691 break;
2692 argv[argc] = pos;
2693 argc++;
2694 if (argc == max_args)
2695 break;
2696 if (*pos == '"') {
2697 char *pos2 = os_strrchr(pos, '"');
2698 if (pos2)
2699 pos = pos2 + 1;
2700 }
2701 while (*pos != '\0' && *pos != ' ')
2702 pos++;
2703 if (*pos == ' ')
2704 *pos++ = '\0';
2705 }
2706
2707 return argc;
2708 }
2709
2710
2711 static void trunc_nl(char *str)
2712 {
2713 char *pos = str;
2714 while (*pos != '\0') {
2715 if (*pos == '\n') {
2716 *pos = '\0';
2717 break;
2718 }
2719 pos++;
2720 }
2721 }
2722
2723
2724 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
2725 {
2726 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2727 printf("Connection to wpa_supplicant lost - trying to "
2728 "reconnect\n");
2729 wpa_cli_close_connection();
2730 }
2731 if (!ctrl_conn)
2732 wpa_cli_reconnect();
2733 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
2734 }
2735
2736
2737 static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
2738 {
2739 eloop_terminate();
2740 }
2741
2742
2743 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
2744 {
2745 wpa_cli_recv_pending(mon_conn, 0);
2746 }
2747
2748
2749 #ifdef CONFIG_READLINE
2750
2751 static char * wpa_cli_cmd_gen(const char *text, int state)
2752 {
2753 static int i, len;
2754 const char *cmd;
2755
2756 if (state == 0) {
2757 i = 0;
2758 len = os_strlen(text);
2759 }
2760
2761 while ((cmd = wpa_cli_commands[i].cmd)) {
2762 i++;
2763 if (os_strncasecmp(cmd, text, len) == 0)
2764 return strdup(cmd);
2765 }
2766
2767 return NULL;
2768 }
2769
2770
2771 static char * wpa_cli_dummy_gen(const char *text, int state)
2772 {
2773 int i;
2774
2775 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2776 const char *cmd = wpa_cli_commands[i].cmd;
2777 size_t len = os_strlen(cmd);
2778 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
2779 rl_line_buffer[len] == ' ') {
2780 printf("\n%s\n", wpa_cli_commands[i].usage);
2781 readline_redraw();
2782 break;
2783 }
2784 }
2785
2786 rl_attempted_completion_over = 1;
2787 return NULL;
2788 }
2789
2790
2791 static char * wpa_cli_status_gen(const char *text, int state)
2792 {
2793 static int i, len;
2794 char *options[] = {
2795 "verbose", NULL
2796 };
2797 char *t;
2798
2799 if (state == 0) {
2800 i = 0;
2801 len = os_strlen(text);
2802 }
2803
2804 while ((t = options[i])) {
2805 i++;
2806 if (os_strncasecmp(t, text, len) == 0)
2807 return strdup(t);
2808 }
2809
2810 rl_attempted_completion_over = 1;
2811 return NULL;
2812 }
2813
2814
2815 static char ** wpa_cli_completion(const char *text, int start, int end)
2816 {
2817 char * (*func)(const char *text, int state);
2818
2819 if (start == 0)
2820 func = wpa_cli_cmd_gen;
2821 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
2822 func = wpa_cli_status_gen;
2823 else
2824 func = wpa_cli_dummy_gen;
2825 return rl_completion_matches(text, func);
2826 }
2827
2828
2829 static void wpa_cli_read_char(int sock, void *eloop_ctx, void *sock_ctx)
2830 {
2831 rl_callback_read_char();
2832 }
2833
2834
2835 static void readline_cmd_handler(char *cmd)
2836 {
2837 int argc;
2838 char *argv[max_args];
2839
2840 if (cmd && *cmd) {
2841 HIST_ENTRY *h;
2842 while (next_history())
2843 ;
2844 h = previous_history();
2845 if (h == NULL || os_strcmp(cmd, h->line) != 0)
2846 add_history(cmd);
2847 next_history();
2848 }
2849 if (cmd == NULL) {
2850 eloop_terminate();
2851 return;
2852 }
2853 trunc_nl(cmd);
2854 argc = tokenize_cmd(cmd, argv);
2855 if (argc)
2856 wpa_request(ctrl_conn, argc, argv);
2857 }
2858
2859
2860 static void wpa_cli_interactive(void)
2861 {
2862 char *home, *hfile = NULL;
2863
2864 printf("\nInteractive mode\n\n");
2865
2866 rl_attempted_completion_function = wpa_cli_completion;
2867 home = getenv("HOME");
2868 if (home) {
2869 const char *fname = ".wpa_cli_history";
2870 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2871 hfile = os_malloc(hfile_len);
2872 if (hfile) {
2873 int res;
2874 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2875 fname);
2876 if (res >= 0 && res < hfile_len) {
2877 hfile[hfile_len - 1] = '\0';
2878 read_history(hfile);
2879 stifle_history(100);
2880 }
2881 }
2882 }
2883
2884 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
2885 eloop_register_read_sock(STDIN_FILENO, wpa_cli_read_char, NULL, NULL);
2886 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
2887
2888 rl_callback_handler_install("> ", readline_cmd_handler);
2889
2890 eloop_run();
2891
2892 rl_callback_handler_remove();
2893
2894 eloop_unregister_read_sock(STDIN_FILENO);
2895 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
2896 wpa_cli_close_connection();
2897
2898 if (hfile) {
2899 /* Save command history, excluding lines that may contain
2900 * passwords. */
2901 HIST_ENTRY *h;
2902 history_set_pos(0);
2903 while ((h = current_history())) {
2904 char *p = h->line;
2905 while (*p == ' ' || *p == '\t')
2906 p++;
2907 if (cmd_has_sensitive_data(p)) {
2908 h = remove_history(where_history());
2909 if (h) {
2910 os_free(h->line);
2911 free(h->data);
2912 os_free(h);
2913 } else
2914 next_history();
2915 } else
2916 next_history();
2917 }
2918 write_history(hfile);
2919 os_free(hfile);
2920 }
2921 }
2922
2923 #else /* CONFIG_READLINE */
2924
2925 #ifdef CONFIG_WPA_CLI_EDIT
2926
2927 static void wpa_cli_clear_line(void)
2928 {
2929 int i;
2930 putchar('\r');
2931 for (i = 0; i < cmdbuf_len + 2; i++)
2932 putchar(' ');
2933 }
2934
2935
2936 static void move_start(void)
2937 {
2938 cmdbuf_pos = 0;
2939 readline_redraw();
2940 }
2941
2942
2943 static void move_end(void)
2944 {
2945 cmdbuf_pos = cmdbuf_len;
2946 readline_redraw();
2947 }
2948
2949
2950 static void move_left(void)
2951 {
2952 if (cmdbuf_pos > 0) {
2953 cmdbuf_pos--;
2954 readline_redraw();
2955 }
2956 }
2957
2958
2959 static void move_right(void)
2960 {
2961 if (cmdbuf_pos < cmdbuf_len) {
2962 cmdbuf_pos++;
2963 readline_redraw();
2964 }
2965 }
2966
2967
2968 static void move_word_left(void)
2969 {
2970 while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] == ' ')
2971 cmdbuf_pos--;
2972 while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] != ' ')
2973 cmdbuf_pos--;
2974 readline_redraw();
2975 }
2976
2977
2978 static void move_word_right(void)
2979 {
2980 while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] == ' ')
2981 cmdbuf_pos++;
2982 while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] != ' ')
2983 cmdbuf_pos++;
2984 readline_redraw();
2985 }
2986
2987
2988 static void delete_left(void)
2989 {
2990 if (cmdbuf_pos == 0)
2991 return;
2992
2993 wpa_cli_clear_line();
2994 os_memmove(cmdbuf + cmdbuf_pos - 1, cmdbuf + cmdbuf_pos,
2995 cmdbuf_len - cmdbuf_pos);
2996 cmdbuf_pos--;
2997 cmdbuf_len--;
2998 readline_redraw();
2999 }
3000
3001
3002 static void delete_current(void)
3003 {
3004 if (cmdbuf_pos == cmdbuf_len)
3005 return;
3006
3007 wpa_cli_clear_line();
3008 os_memmove(cmdbuf + cmdbuf_pos, cmdbuf + cmdbuf_pos + 1,
3009 cmdbuf_len - cmdbuf_pos);
3010 cmdbuf_len--;
3011 readline_redraw();
3012 }
3013
3014
3015 static void delete_word(void)
3016 {
3017 wpa_cli_clear_line();
3018 while (cmdbuf_len > 0 && cmdbuf[cmdbuf_len - 1] == ' ')
3019 cmdbuf_len--;
3020 while (cmdbuf_len > 0 && cmdbuf[cmdbuf_len - 1] != ' ')
3021 cmdbuf_len--;
3022 readline_redraw();
3023 }
3024
3025
3026 static void clear_left(void)
3027 {
3028 if (cmdbuf_pos == 0)
3029 return;
3030
3031 wpa_cli_clear_line();
3032 os_memmove(cmdbuf, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos);
3033 cmdbuf_len -= cmdbuf_pos;
3034 cmdbuf_pos = 0;
3035 readline_redraw();
3036 }
3037
3038
3039 static void clear_right(void)
3040 {
3041 if (cmdbuf_pos == cmdbuf_len)
3042 return;
3043
3044 wpa_cli_clear_line();
3045 cmdbuf_len = cmdbuf_pos;
3046 readline_redraw();
3047 }
3048
3049
3050 static void history_add(const char *str)
3051 {
3052 int prev;
3053
3054 if (str[0] == '\0')
3055 return;
3056
3057 if (history_pos == 0)
3058 prev = CMD_HISTORY_LEN - 1;
3059 else
3060 prev = history_pos - 1;
3061 if (os_strcmp(history_buf[prev], str) == 0)
3062 return;
3063
3064 os_strlcpy(history_buf[history_pos], str, CMD_BUF_LEN);
3065 history_pos++;
3066 if (history_pos == CMD_HISTORY_LEN)
3067 history_pos = 0;
3068 history_current = history_pos;
3069 }
3070
3071
3072 static void history_prev(void)
3073 {
3074 int pos;
3075
3076 if (history_current == (history_pos + 1) % CMD_HISTORY_LEN)
3077 return;
3078
3079 pos = history_current;
3080
3081 if (history_current == history_pos && cmdbuf_len) {
3082 cmdbuf[cmdbuf_len] = '\0';
3083 history_add(cmdbuf);
3084 }
3085
3086 if (pos > 0)
3087 pos--;
3088 else
3089 pos = CMD_HISTORY_LEN - 1;
3090 if (history_buf[pos][0] == '\0')
3091 return;
3092 history_current = pos;
3093
3094 wpa_cli_clear_line();
3095 cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
3096 os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
3097 readline_redraw();
3098 }
3099
3100
3101 static void history_next(void)
3102 {
3103 if (history_current == history_pos)
3104 return;
3105
3106 history_current++;
3107 if (history_current == CMD_HISTORY_LEN)
3108 history_current = 0;
3109
3110 wpa_cli_clear_line();
3111 cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
3112 os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
3113 readline_redraw();
3114 }
3115
3116
3117 static void history_debug_dump(void)
3118 {
3119 int p;
3120 wpa_cli_clear_line();
3121 printf("\r");
3122 p = (history_pos + 1) % CMD_HISTORY_LEN;
3123 for (;;) {
3124 printf("[%d%s%s] %s\n",
3125 p, p == history_current ? "C" : "",
3126 p == history_pos ? "P" : "", history_buf[p]);
3127 if (p == history_pos)
3128 break;
3129 p++;
3130 if (p == CMD_HISTORY_LEN)
3131 p = 0;
3132 }
3133 readline_redraw();
3134 }
3135
3136
3137 static void insert_char(int c)
3138 {
3139 if (c < 32 && c > 255) {
3140 printf("[%d]\n", c);
3141 readline_redraw();
3142 }
3143
3144 if (cmdbuf_len >= (int) sizeof(cmdbuf) - 1)
3145 return;
3146 if (cmdbuf_len == cmdbuf_pos) {
3147 cmdbuf[cmdbuf_pos++] = c;
3148 cmdbuf_len++;
3149 putchar(c);
3150 fflush(stdout);
3151 } else {
3152 os_memmove(cmdbuf + cmdbuf_pos + 1, cmdbuf + cmdbuf_pos,
3153 cmdbuf_len - cmdbuf_pos);
3154 cmdbuf[cmdbuf_pos++] = c;
3155 cmdbuf_len++;
3156 readline_redraw();
3157 }
3158 }
3159
3160
3161 static void process_cmd(void)
3162 {
3163 char *argv[max_args];
3164 int argc;
3165
3166 if (cmdbuf_len == 0) {
3167 printf("\n> ");
3168 fflush(stdout);
3169 return;
3170 }
3171 printf("\n");
3172 cmdbuf[cmdbuf_len] = '\0';
3173 history_add(cmdbuf);
3174 cmdbuf_pos = 0;
3175 cmdbuf_len = 0;
3176 trunc_nl(cmdbuf);
3177 argc = tokenize_cmd(cmdbuf, argv);
3178 if (argc)
3179 wpa_request(ctrl_conn, argc, argv);
3180 printf("> ");
3181 fflush(stdout);
3182 }
3183
3184
3185 static void wpa_cli_read_char(int sock, void *eloop_ctx, void *sock_ctx)
3186 {
3187 int c;
3188 unsigned char buf[1];
3189 int res;
3190 static int esc = -1;
3191 static char esc_buf[6];
3192
3193 res = read(sock, buf, 1);
3194 if (res < 0)
3195 perror("read");
3196 if (res <= 0) {
3197 eloop_terminate();
3198 return;
3199 }
3200 c = buf[0];
3201
3202 if (esc >= 0) {
3203 if (esc == 5) {
3204 printf("{ESC%s}[0]\n", esc_buf);
3205 readline_redraw();
3206 esc = -1;
3207 } else {
3208 esc_buf[esc++] = c;
3209 esc_buf[esc] = '\0';
3210 if (esc == 1)
3211 return;
3212 }
3213 }
3214
3215 if (esc == 2 && esc_buf[0] == '[' && c >= 'A' && c <= 'Z') {
3216 switch (c) {
3217 case 'A': /* up */
3218 history_prev();
3219 break;
3220 case 'B': /* down */
3221 history_next();
3222 break;
3223 case 'C': /* right */
3224 move_right();
3225 break;
3226 case 'D': /* left */
3227 move_left();
3228 break;
3229 case 'F': /* end */
3230 move_end();
3231 break;
3232 case 'H': /* home */
3233 move_start();
3234 break;
3235 default:
3236 printf("{ESC%s}[1]\n", esc_buf);
3237 readline_redraw();
3238 break;
3239 }
3240 esc = -1;
3241 return;
3242 }
3243
3244 if (esc > 1 && esc_buf[0] == '[') {
3245 if ((c >= '0' && c <= '9') || c == ';')
3246 return;
3247
3248 if (esc_buf[1] == '1' && esc_buf[2] == ';' &&
3249 esc_buf[3] == '5') {
3250 switch (esc_buf[4]) {
3251 case 'A': /* Ctrl-Up */
3252 case 'B': /* Ctrl-Down */
3253 break;
3254 case 'C': /* Ctrl-Right */
3255 move_word_right();
3256 break;
3257 case 'D': /* Ctrl-Left */
3258 move_word_left();
3259 break;
3260 default:
3261 printf("{ESC%s}[2]\n", esc_buf);
3262 readline_redraw();
3263 break;
3264 }
3265 esc = -1;
3266 return;
3267 }
3268
3269 switch (c) {
3270 case '~':
3271 switch (atoi(&esc_buf[1])) {
3272 case 2: /* Insert */
3273 break;
3274 case 3: /* Delete */
3275 delete_current();
3276 break;
3277 case 5: /* Page Up */
3278 case 6: /* Page Down */
3279 case 15: /* F5 */
3280 case 17: /* F6 */
3281 case 18: /* F7 */
3282 case 19: /* F8 */
3283 case 20: /* F9 */
3284 case 21: /* F10 */
3285 case 23: /* F11 */
3286 case 24: /* F12 */
3287 break;
3288 default:
3289 printf("{ESC%s}[3]\n", esc_buf);
3290 readline_redraw();
3291 break;
3292 }
3293 break;
3294 default:
3295 printf("{ESC%s}[4]\n", esc_buf);
3296 readline_redraw();
3297 break;
3298 }
3299
3300 esc = -1;
3301 return;
3302 }
3303
3304 if (esc > 1 && esc_buf[0] == 'O') {
3305 switch (esc_buf[1]) {
3306 case 'P': /* F1 */
3307 history_debug_dump();
3308 break;
3309 case 'Q': /* F2 */
3310 case 'R': /* F3 */
3311 case 'S': /* F4 */
3312 break;
3313 default:
3314 printf("{ESC%s}[5]\n", esc_buf);
3315 readline_redraw();
3316 break;
3317 }
3318 esc = -1;
3319 return;
3320 }
3321
3322 if (esc > 1) {
3323 printf("{ESC%s}[6]\n", esc_buf);
3324 readline_redraw();
3325 esc = -1;
3326 return;
3327 }
3328
3329 switch (c) {
3330 case 1: /* ^A */
3331 move_start();
3332 break;
3333 case 4: /* ^D */
3334 if (cmdbuf_len > 0) {
3335 delete_current();
3336 return;
3337 }
3338 printf("\n");
3339 eloop_terminate();
3340 break;
3341 case 5: /* ^E */
3342 move_end();
3343 break;
3344 case 8: /* ^H = BS */
3345 delete_left();
3346 break;
3347 case 9: /* ^I = TAB */
3348 break;
3349 case 10: /* NL */
3350 case 13: /* CR */
3351 process_cmd();
3352 break;
3353 case 11: /* ^K */
3354 clear_right();
3355 break;
3356 case 14: /* ^N */
3357 history_next();
3358 break;
3359 case 16: /* ^P */
3360 history_prev();
3361 break;
3362 case 18: /* ^R */
3363 /* TODO: search history */
3364 break;
3365 case 21: /* ^U */
3366 clear_left();
3367 break;
3368 case 23: /* ^W */
3369 delete_word();
3370 break;
3371 case 27: /* ESC */
3372 esc = 0;
3373 break;
3374 case 127: /* DEL */
3375 delete_left();
3376 break;
3377 default:
3378 insert_char(c);
3379 break;
3380 }
3381 }
3382
3383 #else /* CONFIG_WPA_CLI_EDIT */
3384
3385 static void wpa_cli_read_char(int sock, void *eloop_ctx, void *sock_ctx)
3386 {
3387 char *argv[max_args];
3388 int argc;
3389 int c;
3390 unsigned char buf[1];
3391 int res;
3392
3393 res = read(sock, buf, 1);
3394 if (res < 0)
3395 perror("read");
3396 if (res <= 0) {
3397 eloop_terminate();
3398 return;
3399 }
3400 c = buf[0];
3401
3402 if (c == '\r' || c == '\n') {
3403 cmdbuf[cmdbuf_pos] = '\0';
3404 cmdbuf_pos = 0;
3405 trunc_nl(cmdbuf);
3406 argc = tokenize_cmd(cmdbuf, argv);
3407 if (argc)
3408 wpa_request(ctrl_conn, argc, argv);
3409 printf("> ");
3410 fflush(stdout);
3411 return;
3412 }
3413
3414 if (c >= 32 && c <= 255) {
3415 if (cmdbuf_pos < (int) sizeof(cmdbuf) - 1) {
3416 cmdbuf[cmdbuf_pos++] = c;
3417 }
3418 }
3419 }
3420
3421 #endif /* CONFIG_WPA_CLI_EDIT */
3422
3423
3424 static void wpa_cli_interactive(void)
3425 {
3426 #ifdef CONFIG_WPA_CLI_EDIT
3427 struct termios prevt, newt;
3428 #endif /* CONFIG_WPA_CLI_EDIT */
3429
3430 printf("\nInteractive mode\n\n");
3431 cmdbuf_pos = 0;
3432 cmdbuf_len = 0;
3433
3434 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
3435 eloop_register_read_sock(STDIN_FILENO, wpa_cli_read_char, NULL, NULL);
3436 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3437
3438 #ifdef CONFIG_WPA_CLI_EDIT
3439 os_memset(history_buf, 0, sizeof(history_buf));
3440
3441 tcgetattr(STDIN_FILENO, &prevt);
3442 newt = prevt;
3443 newt.c_lflag &= ~(ICANON | ECHO);
3444 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
3445 #endif /* CONFIG_WPA_CLI_EDIT */
3446
3447 printf("> ");
3448 fflush(stdout);
3449
3450 eloop_run();
3451
3452 eloop_unregister_read_sock(STDIN_FILENO);
3453 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3454 wpa_cli_close_connection();
3455
3456 #ifdef CONFIG_WPA_CLI_EDIT
3457 tcsetattr(STDIN_FILENO, TCSANOW, &prevt);
3458 #endif /* CONFIG_WPA_CLI_EDIT */
3459 }
3460
3461 #endif /* CONFIG_READLINE */
3462
3463
3464 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3465 {
3466 #ifdef CONFIG_ANSI_C_EXTRA
3467 /* TODO: ANSI C version(?) */
3468 printf("Action processing not supported in ANSI C build.\n");
3469 #else /* CONFIG_ANSI_C_EXTRA */
3470 fd_set rfds;
3471 int fd, res;
3472 struct timeval tv;
3473 char buf[256]; /* note: large enough to fit in unsolicited messages */
3474 size_t len;
3475
3476 fd = wpa_ctrl_get_fd(ctrl);
3477
3478 while (!wpa_cli_quit) {
3479 FD_ZERO(&rfds);
3480 FD_SET(fd, &rfds);
3481 tv.tv_sec = ping_interval;
3482 tv.tv_usec = 0;
3483 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3484 if (res < 0 && errno != EINTR) {
3485 perror("select");
3486 break;
3487 }
3488
3489 if (FD_ISSET(fd, &rfds))
3490 wpa_cli_recv_pending(ctrl, 1);
3491 else {
3492 /* verify that connection is still working */
3493 len = sizeof(buf) - 1;
3494 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3495 wpa_cli_action_cb) < 0 ||
3496 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3497 printf("wpa_supplicant did not reply to PING "
3498 "command - exiting\n");
3499 break;
3500 }
3501 }
3502 }
3503 #endif /* CONFIG_ANSI_C_EXTRA */
3504 }
3505
3506
3507 static void wpa_cli_cleanup(void)
3508 {
3509 wpa_cli_close_connection();
3510 if (pid_file)
3511 os_daemonize_terminate(pid_file);
3512
3513 os_program_deinit();
3514 }
3515
3516 static void wpa_cli_terminate(int sig)
3517 {
3518 wpa_cli_cleanup();
3519 exit(0);
3520 }
3521
3522
3523 static char * wpa_cli_get_default_ifname(void)
3524 {
3525 char *ifname = NULL;
3526
3527 #ifdef CONFIG_CTRL_IFACE_UNIX
3528 struct dirent *dent;
3529 DIR *dir = opendir(ctrl_iface_dir);
3530 if (!dir)
3531 return NULL;
3532 while ((dent = readdir(dir))) {
3533 #ifdef _DIRENT_HAVE_D_TYPE
3534 /*
3535 * Skip the file if it is not a socket. Also accept
3536 * DT_UNKNOWN (0) in case the C library or underlying
3537 * file system does not support d_type.
3538 */
3539 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3540 continue;
3541 #endif /* _DIRENT_HAVE_D_TYPE */
3542 if (os_strcmp(dent->d_name, ".") == 0 ||
3543 os_strcmp(dent->d_name, "..") == 0)
3544 continue;
3545 printf("Selected interface '%s'\n", dent->d_name);
3546 ifname = os_strdup(dent->d_name);
3547 break;
3548 }
3549 closedir(dir);
3550 #endif /* CONFIG_CTRL_IFACE_UNIX */
3551
3552 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3553 char buf[2048], *pos;
3554 size_t len;
3555 struct wpa_ctrl *ctrl;
3556 int ret;
3557
3558 ctrl = wpa_ctrl_open(NULL);
3559 if (ctrl == NULL)
3560 return NULL;
3561
3562 len = sizeof(buf) - 1;
3563 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3564 if (ret >= 0) {
3565 buf[len] = '\0';
3566 pos = os_strchr(buf, '\n');
3567 if (pos)
3568 *pos = '\0';
3569 ifname = os_strdup(buf);
3570 }
3571 wpa_ctrl_close(ctrl);
3572 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3573
3574 return ifname;
3575 }
3576
3577
3578 int main(int argc, char *argv[])
3579 {
3580 int warning_displayed = 0;
3581 int c;
3582 int daemonize = 0;
3583 int ret = 0;
3584 const char *global = NULL;
3585
3586 if (os_program_init())
3587 return -1;
3588
3589 for (;;) {
3590 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3591 if (c < 0)
3592 break;
3593 switch (c) {
3594 case 'a':
3595 action_file = optarg;
3596 break;
3597 case 'B':
3598 daemonize = 1;
3599 break;
3600 case 'g':
3601 global = optarg;
3602 break;
3603 case 'G':
3604 ping_interval = atoi(optarg);
3605 break;
3606 case 'h':
3607 usage();
3608 return 0;
3609 case 'v':
3610 printf("%s\n", wpa_cli_version);
3611 return 0;
3612 case 'i':
3613 os_free(ctrl_ifname);
3614 ctrl_ifname = os_strdup(optarg);
3615 break;
3616 case 'p':
3617 ctrl_iface_dir = optarg;
3618 break;
3619 case 'P':
3620 pid_file = optarg;
3621 break;
3622 default:
3623 usage();
3624 return -1;
3625 }
3626 }
3627
3628 interactive = (argc == optind) && (action_file == NULL);
3629
3630 if (interactive)
3631 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3632
3633 if (eloop_init())
3634 return -1;
3635
3636 if (global) {
3637 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3638 ctrl_conn = wpa_ctrl_open(NULL);
3639 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3640 ctrl_conn = wpa_ctrl_open(global);
3641 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3642 if (ctrl_conn == NULL) {
3643 perror("Failed to connect to wpa_supplicant - "
3644 "wpa_ctrl_open");
3645 return -1;
3646 }
3647 }
3648
3649 #ifndef _WIN32_WCE
3650 signal(SIGINT, wpa_cli_terminate);
3651 signal(SIGTERM, wpa_cli_terminate);
3652 #endif /* _WIN32_WCE */
3653
3654 if (ctrl_ifname == NULL)
3655 ctrl_ifname = wpa_cli_get_default_ifname();
3656
3657 if (interactive) {
3658 for (; !global;) {
3659 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3660 if (warning_displayed)
3661 printf("Connection established.\n");
3662 break;
3663 }
3664
3665 if (!warning_displayed) {
3666 printf("Could not connect to wpa_supplicant - "
3667 "re-trying\n");
3668 warning_displayed = 1;
3669 }
3670 os_sleep(1, 0);
3671 continue;
3672 }
3673 } else {
3674 if (!global &&
3675 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3676 perror("Failed to connect to wpa_supplicant - "
3677 "wpa_ctrl_open");
3678 return -1;
3679 }
3680
3681 if (action_file) {
3682 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3683 wpa_cli_attached = 1;
3684 } else {
3685 printf("Warning: Failed to attach to "
3686 "wpa_supplicant.\n");
3687 return -1;
3688 }
3689 }
3690 }
3691
3692 if (daemonize && os_daemonize(pid_file))
3693 return -1;
3694
3695 if (interactive)
3696 wpa_cli_interactive();
3697 else if (action_file)
3698 wpa_cli_action(ctrl_conn);
3699 else
3700 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3701
3702 os_free(ctrl_ifname);
3703 eloop_destroy();
3704 wpa_cli_cleanup();
3705
3706 return ret;
3707 }
3708
3709 #else /* CONFIG_CTRL_IFACE */
3710 int main(int argc, char *argv[])
3711 {
3712 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3713 return -1;
3714 }
3715 #endif /* CONFIG_CTRL_IFACE */