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