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