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