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