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