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