]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
Interworking: Add ANQP query requests
[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
afc064fe
JM
2222#ifdef CONFIG_INTERWORKING
2223static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2224 char *argv[])
2225{
2226 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2227}
2228
2229
2230static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2231 char *argv[])
2232{
2233 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2234}
2235
2236
2237static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2238{
2239 char cmd[100];
2240 int res;
2241
2242 if (argc != 2) {
2243 printf("Invalid ANQP_GET command: needs two arguments "
2244 "(addr and info id list)\n");
2245 return -1;
2246 }
2247
2248 res = os_snprintf(cmd, sizeof(cmd), "ANQP_GET %s %s",
2249 argv[0], argv[1]);
2250 if (res < 0 || (size_t) res >= sizeof(cmd))
2251 return -1;
2252 cmd[sizeof(cmd) - 1] = '\0';
2253 return wpa_ctrl_command(ctrl, cmd);
2254}
2255#endif /* CONFIG_INTERWORKING */
2256
2257
0d0a8ca1
AC
2258static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
2261 char cmd[256];
2262 int res;
2263
2264 if (argc != 1) {
2265 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2266 "(0/1 = disable/enable automatic reconnection)\n");
2267 return -1;
2268 }
2269 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2270 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2271 printf("Too long STA_AUTOCONNECT command.\n");
2272 return -1;
2273 }
2274 return wpa_ctrl_command(ctrl, cmd);
2275}
2276
2277
281ff0aa
GP
2278static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2279 char *argv[])
2280{
2281 char cmd[256];
2282 int res;
2283
2284 if (argc != 1) {
2285 printf("Invalid TDLS_DISCOVER command: needs one argument "
2286 "(Peer STA MAC address)\n");
2287 return -1;
2288 }
2289
2290 res = os_snprintf(cmd, sizeof(cmd), "TDLS_DISCOVER %s", argv[0]);
2291 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2292 printf("Too long TDLS_DISCOVER command.\n");
2293 return -1;
2294 }
2295 return wpa_ctrl_command(ctrl, cmd);
2296}
2297
2298
2299static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2300 char *argv[])
2301{
2302 char cmd[256];
2303 int res;
2304
2305 if (argc != 1) {
2306 printf("Invalid TDLS_SETUP command: needs one argument "
2307 "(Peer STA MAC address)\n");
2308 return -1;
2309 }
2310
2311 res = os_snprintf(cmd, sizeof(cmd), "TDLS_SETUP %s", argv[0]);
2312 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2313 printf("Too long TDLS_SETUP command.\n");
2314 return -1;
2315 }
2316 return wpa_ctrl_command(ctrl, cmd);
2317}
2318
2319
2320static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2321 char *argv[])
2322{
2323 char cmd[256];
2324 int res;
2325
2326 if (argc != 1) {
2327 printf("Invalid TDLS_TEARDOWN command: needs one argument "
2328 "(Peer STA MAC address)\n");
2329 return -1;
2330 }
2331
2332 res = os_snprintf(cmd, sizeof(cmd), "TDLS_TEARDOWN %s", argv[0]);
2333 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2334 printf("Too long TDLS_TEARDOWN command.\n");
2335 return -1;
2336 }
2337 return wpa_ctrl_command(ctrl, cmd);
2338}
2339
2340
60b24b0d
DS
2341static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2342 char *argv[])
2343{
2344 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2345}
2346
2347
40fd868c
ER
2348enum wpa_cli_cmd_flags {
2349 cli_cmd_flag_none = 0x00,
2350 cli_cmd_flag_sensitive = 0x01
2351};
2352
6fc6879b
JM
2353struct wpa_cli_cmd {
2354 const char *cmd;
2355 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 2356 enum wpa_cli_cmd_flags flags;
dfa141b1 2357 const char *usage;
6fc6879b
JM
2358};
2359
2360static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 2361 { "status", wpa_cli_cmd_status,
dfa141b1
ER
2362 cli_cmd_flag_none,
2363 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 2364 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
2365 cli_cmd_flag_none,
2366 "= pings wpa_supplicant" },
ac6912b5
BG
2367 { "relog", wpa_cli_cmd_relog,
2368 cli_cmd_flag_none,
2369 "= re-open log-file (allow rolling logs)" },
77895cd9
JM
2370 { "note", wpa_cli_cmd_note,
2371 cli_cmd_flag_none,
2372 "<text> = add a note to wpa_supplicant debug log" },
40fd868c 2373 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
2374 cli_cmd_flag_none,
2375 "= get MIB variables (dot1x, dot11)" },
40fd868c 2376 { "help", wpa_cli_cmd_help,
dfa141b1
ER
2377 cli_cmd_flag_none,
2378 "= show this usage help" },
40fd868c 2379 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
2380 cli_cmd_flag_none,
2381 "[ifname] = show interfaces/select interface" },
40fd868c 2382 { "level", wpa_cli_cmd_level,
dfa141b1
ER
2383 cli_cmd_flag_none,
2384 "<debug level> = change debug level" },
40fd868c 2385 { "license", wpa_cli_cmd_license,
dfa141b1
ER
2386 cli_cmd_flag_none,
2387 "= show full wpa_cli license" },
40fd868c 2388 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
2389 cli_cmd_flag_none,
2390 "= exit wpa_cli" },
40fd868c 2391 { "set", wpa_cli_cmd_set,
dfa141b1
ER
2392 cli_cmd_flag_none,
2393 "= set variables (shows list of variables when run without "
2394 "arguments)" },
acec8d32
JM
2395 { "get", wpa_cli_cmd_get,
2396 cli_cmd_flag_none,
2397 "<name> = get information" },
40fd868c 2398 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
2399 cli_cmd_flag_none,
2400 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 2401 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
2402 cli_cmd_flag_none,
2403 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 2404 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
2405 cli_cmd_flag_none,
2406 "= show PMKSA cache" },
40fd868c 2407 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
2408 cli_cmd_flag_none,
2409 "= force reassociation" },
40fd868c 2410 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
2411 cli_cmd_flag_none,
2412 "<BSSID> = force preauthentication" },
40fd868c 2413 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
2414 cli_cmd_flag_none,
2415 "<network id> <identity> = configure identity for an SSID" },
40fd868c 2416 { "password", wpa_cli_cmd_password,
dfa141b1
ER
2417 cli_cmd_flag_sensitive,
2418 "<network id> <password> = configure password for an SSID" },
40fd868c 2419 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
2420 cli_cmd_flag_sensitive,
2421 "<network id> <password> = change password for an SSID" },
40fd868c 2422 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
2423 cli_cmd_flag_sensitive,
2424 "<network id> <pin> = configure pin for an SSID" },
40fd868c 2425 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
2426 cli_cmd_flag_sensitive,
2427 "<network id> <password> = configure one-time-password for an SSID"
2428 },
40fd868c 2429 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
2430 cli_cmd_flag_sensitive,
2431 "<network id> <passphrase> = configure private key passphrase\n"
2432 " for an SSID" },
40fd868c 2433 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
2434 cli_cmd_flag_none,
2435 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 2436 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
2437 cli_cmd_flag_none,
2438 "= list configured networks" },
40fd868c 2439 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
2440 cli_cmd_flag_none,
2441 "<network id> = select a network (disable others)" },
40fd868c 2442 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
2443 cli_cmd_flag_none,
2444 "<network id> = enable a network" },
40fd868c 2445 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
2446 cli_cmd_flag_none,
2447 "<network id> = disable a network" },
40fd868c 2448 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
2449 cli_cmd_flag_none,
2450 "= add a network" },
40fd868c 2451 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
2452 cli_cmd_flag_none,
2453 "<network id> = remove a network" },
40fd868c 2454 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
2455 cli_cmd_flag_sensitive,
2456 "<network id> <variable> <value> = set network variables (shows\n"
2457 " list of variables when run without arguments)" },
40fd868c 2458 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
2459 cli_cmd_flag_none,
2460 "<network id> <variable> = get network variables" },
40fd868c 2461 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
2462 cli_cmd_flag_none,
2463 "= save the current configuration" },
40fd868c 2464 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
2465 cli_cmd_flag_none,
2466 "= disconnect and wait for reassociate/reconnect command before\n"
2467 " connecting" },
40fd868c 2468 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
2469 cli_cmd_flag_none,
2470 "= like reassociate, but only takes effect if already disconnected"
2471 },
40fd868c 2472 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
2473 cli_cmd_flag_none,
2474 "= request new BSS scan" },
40fd868c 2475 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
2476 cli_cmd_flag_none,
2477 "= get latest scan results" },
40fd868c 2478 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
2479 cli_cmd_flag_none,
2480 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 2481 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
2482 cli_cmd_flag_none,
2483 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 2484 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
2485 cli_cmd_flag_none,
2486 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 2487 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
2488 cli_cmd_flag_none,
2489 "= terminate wpa_supplicant" },
40fd868c 2490 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
2491 cli_cmd_flag_none,
2492 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2493 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2494 " are optional" },
40fd868c 2495 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
2496 cli_cmd_flag_none,
2497 "<ifname> = removes the interface" },
40fd868c 2498 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
2499 cli_cmd_flag_none,
2500 "= list available interfaces" },
40fd868c 2501 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
2502 cli_cmd_flag_none,
2503 "<value> = set ap_scan parameter" },
67b9bd08
DS
2504 { "scan_interval", wpa_cli_cmd_scan_interval,
2505 cli_cmd_flag_none,
2506 "<value> = set scan_interval parameter (in seconds)" },
78633c37
SL
2507 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
2508 cli_cmd_flag_none,
2509 "<value> = set BSS expiration age parameter" },
2510 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
2511 cli_cmd_flag_none,
2512 "<value> = set BSS expiration scan count parameter" },
40fd868c 2513 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
2514 cli_cmd_flag_none,
2515 "<addr> = request STK negotiation with <addr>" },
40fd868c 2516 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
2517 cli_cmd_flag_none,
2518 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 2519 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
2520 cli_cmd_flag_none,
2521 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 2522 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
2523 cli_cmd_flag_sensitive,
2524 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2525 "hardcoded)" },
3981cb3c
JM
2526 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2527 cli_cmd_flag_sensitive,
2528 "<PIN> = verify PIN checksum" },
2f9929ff
AC
2529 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2530 "Cancels the pending WPS operation" },
116f7bb0 2531#ifdef CONFIG_WPS_OOB
46bdb83a
MH
2532 { "wps_oob", wpa_cli_cmd_wps_oob,
2533 cli_cmd_flag_sensitive,
e1ee6b60 2534 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 2535#endif /* CONFIG_WPS_OOB */
40fd868c 2536 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
2537 cli_cmd_flag_sensitive,
2538 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
70d84f11
JM
2539 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
2540 cli_cmd_flag_sensitive,
2541 "[params..] = enable/disable AP PIN" },
e9bcfebf
JM
2542 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2543 cli_cmd_flag_none,
08486685 2544 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
e9bcfebf
JM
2545 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2546 cli_cmd_flag_none,
2547 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
2548 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2549 cli_cmd_flag_sensitive,
2550 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
2551 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2552 cli_cmd_flag_none,
2553 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
2554 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2555 cli_cmd_flag_sensitive,
2556 "<UUID> <PIN> = learn AP configuration" },
ef10f473
JM
2557 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2558 cli_cmd_flag_none,
2559 "<UUID> <network id> = set AP configuration for enrolling" },
7d6640a6
JM
2560 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2561 cli_cmd_flag_sensitive,
2562 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
11ef8d35
JM
2563 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2564 cli_cmd_flag_none,
2565 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
2566#ifdef CONFIG_AP
2567 { "sta", wpa_cli_cmd_sta,
2568 cli_cmd_flag_none,
2569 "<addr> = get information about an associated station (AP)" },
2570 { "all_sta", wpa_cli_cmd_all_sta,
2571 cli_cmd_flag_none,
2572 "= get information about all associated stations (AP)" },
2573#endif /* CONFIG_AP */
207ef3fb
JM
2574 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2575 "= notification of suspend/hibernate" },
2576 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2577 "= notification of resume/thaw" },
32d5295f
JM
2578 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2579 "= drop SA without deauth/disassoc (test command)" },
86d4f806
JM
2580 { "roam", wpa_cli_cmd_roam,
2581 cli_cmd_flag_none,
2582 "<addr> = roam to the specified BSS" },
57faa1ce
JM
2583#ifdef CONFIG_P2P
2584 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2585 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2586 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2587 "= stop P2P Devices search" },
2588 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2589 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2590 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2591 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2592 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
4d2ea6a6 2593 "<ifname> = remove P2P group interface (terminate group if GO)" },
57faa1ce
JM
2594 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2595 "= add a new P2P group (local end as GO)" },
2596 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2597 "<addr> <method> = request provisioning discovery" },
2598 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2599 cli_cmd_flag_none,
2600 "= get the passphrase for a group (GO only)" },
2601 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2602 cli_cmd_flag_none,
2603 "<addr> <TLVs> = schedule service discovery request" },
2604 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2605 cli_cmd_flag_none,
2606 "<id> = cancel pending service discovery request" },
2607 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2608 cli_cmd_flag_none,
2609 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2610 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2611 cli_cmd_flag_none,
2612 "= indicate change in local services" },
2613 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2614 cli_cmd_flag_none,
2615 "<external> = set external processing of service discovery" },
2616 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2617 cli_cmd_flag_none,
2618 "= remove all stored service entries" },
2619 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2620 cli_cmd_flag_none,
2621 "<bonjour|upnp> <query|version> <response|service> = add a local "
2622 "service" },
2623 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2624 cli_cmd_flag_none,
2625 "<bonjour|upnp> <query|version> [|service] = remove a local "
2626 "service" },
2627 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2628 cli_cmd_flag_none,
2629 "<addr> = reject connection attempts from a specific peer" },
2630 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2631 cli_cmd_flag_none,
2632 "<cmd> [peer=addr] = invite peer" },
2633 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2634 "[discovered] = list known (optionally, only fully discovered) P2P "
2635 "peers" },
2636 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2637 "<address> = show information about known P2P peer" },
2638 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2639 "<field> <value> = set a P2P parameter" },
2640 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2641 "= flush P2P state" },
59eba7a2
JM
2642 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
2643 "= cancel P2P group formation" },
9d562b79
SS
2644 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
2645 "<address> = unauthorize a peer" },
57faa1ce
JM
2646 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2647 "[<duration> <interval>] [<duration> <interval>] = request GO "
2648 "presence" },
2649 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2650 "[<period> <interval>] = set extended listen timing" },
2651#endif /* CONFIG_P2P */
afc064fe
JM
2652
2653#ifdef CONFIG_INTERWORKING
2654 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
2655 "= fetch ANQP information for all APs" },
2656 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
2657 "= stop fetch_anqp operation" },
2658 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
2659 "<addr> <info id>[,<info id>]... = request ANQP information" },
2660#endif /* CONFIG_INTERWORKING */
0d0a8ca1
AC
2661 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2662 "<0/1> = disable/enable automatic reconnection" },
281ff0aa
GP
2663 { "tdls_discover", wpa_cli_cmd_tdls_discover,
2664 cli_cmd_flag_none,
2665 "<addr> = request TDLS discovery with <addr>" },
2666 { "tdls_setup", wpa_cli_cmd_tdls_setup,
2667 cli_cmd_flag_none,
2668 "<addr> = request TDLS setup with <addr>" },
2669 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
2670 cli_cmd_flag_none,
2671 "<addr> = tear down TDLS with <addr>" },
60b24b0d
DS
2672 { "signal_poll", wpa_cli_cmd_signal_poll,
2673 cli_cmd_flag_none,
2674 "= get signal parameters" },
dfa141b1 2675 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
2676};
2677
2678
dfa141b1
ER
2679/*
2680 * Prints command usage, lines are padded with the specified string.
2681 */
2682static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2683{
2684 char c;
2685 size_t n;
2686
2687 printf("%s%s ", pad, cmd->cmd);
2688 for (n = 0; (c = cmd->usage[n]); n++) {
2689 printf("%c", c);
2690 if (c == '\n')
2691 printf("%s", pad);
2692 }
2693 printf("\n");
2694}
2695
2696
2697static void print_help(void)
2698{
2699 int n;
2700 printf("commands:\n");
2701 for (n = 0; wpa_cli_commands[n].cmd; n++)
2702 print_cmd_help(&wpa_cli_commands[n], " ");
2703}
2704
2705
e8ecb5fb 2706static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
40fd868c
ER
2707{
2708 const char *c, *delim;
2709 int n;
2710 size_t len;
2711
2712 delim = os_strchr(cmd, ' ');
2713 if (delim)
2714 len = delim - cmd;
2715 else
2716 len = os_strlen(cmd);
2717
2718 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2719 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2720 return (wpa_cli_commands[n].flags &
2721 cli_cmd_flag_sensitive);
2722 }
2723 return 0;
2724}
e8ecb5fb
JM
2725
2726
2727static char ** wpa_list_cmd_list(void)
2728{
2729 char **res;
2730 int i, count;
2731
2732 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
2733 res = os_zalloc(count * sizeof(char *));
2734 if (res == NULL)
2735 return NULL;
2736
2737 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2738 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2739 if (res[i] == NULL)
2740 break;
2741 }
2742
2743 return res;
2744}
2745
2746
2747static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2748 int pos)
2749{
2750 int i;
2751
2752 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2753 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
2754 edit_clear_line();
2755 printf("\r%s\n", wpa_cli_commands[i].usage);
2756 edit_redraw();
2757 break;
2758 }
2759 }
2760
2761 return NULL;
2762}
2763
2764
2765static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2766{
2767 char **res;
2768 const char *end;
2769 char *cmd;
2770
2771 end = os_strchr(str, ' ');
2772 if (end == NULL || str + pos < end)
2773 return wpa_list_cmd_list();
2774
2775 cmd = os_malloc(pos + 1);
2776 if (cmd == NULL)
2777 return NULL;
2778 os_memcpy(cmd, str, pos);
2779 cmd[end - str] = '\0';
2780 res = wpa_cli_cmd_completion(cmd, str, pos);
2781 os_free(cmd);
2782 return res;
2783}
40fd868c
ER
2784
2785
6fc6879b
JM
2786static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2787{
2788 struct wpa_cli_cmd *cmd, *match = NULL;
2789 int count;
2790 int ret = 0;
2791
2792 count = 0;
2793 cmd = wpa_cli_commands;
2794 while (cmd->cmd) {
2795 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2796 {
2797 match = cmd;
2798 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2799 /* we have an exact match */
2800 count = 1;
2801 break;
2802 }
2803 count++;
2804 }
2805 cmd++;
2806 }
2807
2808 if (count > 1) {
2809 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2810 cmd = wpa_cli_commands;
2811 while (cmd->cmd) {
2812 if (os_strncasecmp(cmd->cmd, argv[0],
2813 os_strlen(argv[0])) == 0) {
2814 printf(" %s", cmd->cmd);
2815 }
2816 cmd++;
2817 }
2818 printf("\n");
2819 ret = 1;
2820 } else if (count == 0) {
2821 printf("Unknown command '%s'\n", argv[0]);
2822 ret = 1;
2823 } else {
2824 ret = match->handler(ctrl, argc - 1, &argv[1]);
2825 }
2826
2827 return ret;
2828}
2829
2830
2831static int str_match(const char *a, const char *b)
2832{
2833 return os_strncmp(a, b, os_strlen(b)) == 0;
2834}
2835
2836
2837static int wpa_cli_exec(const char *program, const char *arg1,
2838 const char *arg2)
2839{
2840 char *cmd;
2841 size_t len;
2842 int res;
308a4ec8 2843 int ret = 0;
6fc6879b
JM
2844
2845 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2846 cmd = os_malloc(len);
2847 if (cmd == NULL)
2848 return -1;
2849 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2850 if (res < 0 || (size_t) res >= len) {
2851 os_free(cmd);
2852 return -1;
2853 }
2854 cmd[len - 1] = '\0';
2855#ifndef _WIN32_WCE
308a4ec8
JM
2856 if (system(cmd) < 0)
2857 ret = -1;
6fc6879b
JM
2858#endif /* _WIN32_WCE */
2859 os_free(cmd);
2860
308a4ec8 2861 return ret;
6fc6879b
JM
2862}
2863
2864
2865static void wpa_cli_action_process(const char *msg)
2866{
2867 const char *pos;
2868 char *copy = NULL, *id, *pos2;
2869
2870 pos = msg;
2871 if (*pos == '<') {
2872 /* skip priority */
2873 pos = os_strchr(pos, '>');
2874 if (pos)
2875 pos++;
2876 else
2877 pos = msg;
2878 }
2879
2880 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2881 int new_id = -1;
2882 os_unsetenv("WPA_ID");
2883 os_unsetenv("WPA_ID_STR");
2884 os_unsetenv("WPA_CTRL_DIR");
2885
2886 pos = os_strstr(pos, "[id=");
2887 if (pos)
2888 copy = os_strdup(pos + 4);
2889
2890 if (copy) {
2891 pos2 = id = copy;
2892 while (*pos2 && *pos2 != ' ')
2893 pos2++;
2894 *pos2++ = '\0';
2895 new_id = atoi(id);
2896 os_setenv("WPA_ID", id, 1);
2897 while (*pos2 && *pos2 != '=')
2898 pos2++;
2899 if (*pos2 == '=')
2900 pos2++;
2901 id = pos2;
2902 while (*pos2 && *pos2 != ']')
2903 pos2++;
2904 *pos2 = '\0';
2905 os_setenv("WPA_ID_STR", id, 1);
2906 os_free(copy);
2907 }
2908
2909 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2910
2911 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2912 wpa_cli_connected = 1;
2913 wpa_cli_last_id = new_id;
2914 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2915 }
2916 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2917 if (wpa_cli_connected) {
2918 wpa_cli_connected = 0;
2919 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2920 }
42f0101b
JM
2921 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2922 wpa_cli_exec(action_file, ctrl_ifname, pos);
2923 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2924 wpa_cli_exec(action_file, ctrl_ifname, pos);
72044390
JM
2925 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2926 wpa_cli_exec(action_file, ctrl_ifname, pos);
2927 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2928 wpa_cli_exec(action_file, ctrl_ifname, pos);
876103dc
AC
2929 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2930 wpa_cli_exec(action_file, ctrl_ifname, pos);
2931 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2932 wpa_cli_exec(action_file, ctrl_ifname, pos);
6fc6879b
JM
2933 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2934 printf("wpa_supplicant is terminating - stop monitoring\n");
2935 wpa_cli_quit = 1;
2936 }
2937}
2938
2939
2940#ifndef CONFIG_ANSI_C_EXTRA
2941static void wpa_cli_action_cb(char *msg, size_t len)
2942{
2943 wpa_cli_action_process(msg);
2944}
2945#endif /* CONFIG_ANSI_C_EXTRA */
2946
2947
2948static void wpa_cli_reconnect(void)
2949{
2950 wpa_cli_close_connection();
4a3ade4e 2951 wpa_cli_open_connection(ctrl_ifname, 1);
6fc6879b
JM
2952}
2953
2954
cd101567 2955static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
6fc6879b 2956{
6fc6879b
JM
2957 if (ctrl_conn == NULL) {
2958 wpa_cli_reconnect();
2959 return;
2960 }
2961 while (wpa_ctrl_pending(ctrl) > 0) {
2962 char buf[256];
2963 size_t len = sizeof(buf) - 1;
2964 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2965 buf[len] = '\0';
2966 if (action_monitor)
2967 wpa_cli_action_process(buf);
2968 else {
f3f0f648 2969 if (wpa_cli_show_event(buf)) {
82a855bd 2970 edit_clear_line();
cd101567 2971 printf("\r%s\n", buf);
bdc45634 2972 edit_redraw();
f3f0f648 2973 }
6fc6879b
JM
2974 }
2975 } else {
2976 printf("Could not read pending message.\n");
2977 break;
2978 }
2979 }
2980
2981 if (wpa_ctrl_pending(ctrl) < 0) {
2982 printf("Connection to wpa_supplicant lost - trying to "
2983 "reconnect\n");
2984 wpa_cli_reconnect();
2985 }
2986}
2987
6f1c6549
JM
2988#define max_args 10
2989
2990static int tokenize_cmd(char *cmd, char *argv[])
2991{
2992 char *pos;
2993 int argc = 0;
2994
2995 pos = cmd;
2996 for (;;) {
2997 while (*pos == ' ')
2998 pos++;
2999 if (*pos == '\0')
3000 break;
3001 argv[argc] = pos;
3002 argc++;
3003 if (argc == max_args)
3004 break;
3005 if (*pos == '"') {
3006 char *pos2 = os_strrchr(pos, '"');
3007 if (pos2)
3008 pos = pos2 + 1;
3009 }
3010 while (*pos != '\0' && *pos != ' ')
3011 pos++;
3012 if (*pos == ' ')
3013 *pos++ = '\0';
3014 }
3015
3016 return argc;
3017}
3018
3019
cd101567
JM
3020static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3021{
3022 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3023 printf("Connection to wpa_supplicant lost - trying to "
3024 "reconnect\n");
3025 wpa_cli_close_connection();
3026 }
3027 if (!ctrl_conn)
3028 wpa_cli_reconnect();
3029 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3030}
3031
3032
3033static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3034{
3035 eloop_terminate();
3036}
3037
3038
3039static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3040{
3041 wpa_cli_recv_pending(mon_conn, 0);
3042}
3043
3044
82a855bd 3045static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
aee680e8
JM
3046{
3047 char *argv[max_args];
3048 int argc;
82a855bd 3049 argc = tokenize_cmd(cmd, argv);
aee680e8
JM
3050 if (argc)
3051 wpa_request(ctrl_conn, argc, argv);
aee680e8
JM
3052}
3053
3054
82a855bd 3055static void wpa_cli_edit_eof_cb(void *ctx)
6f1c6549 3056{
82a855bd 3057 eloop_terminate();
cd101567
JM
3058}
3059
3060
3061static void wpa_cli_interactive(void)
3062{
8953e968 3063 char *home, *hfile = NULL;
aee680e8 3064
cd101567 3065 printf("\nInteractive mode\n\n");
cd101567 3066
8953e968
JM
3067 home = getenv("HOME");
3068 if (home) {
3069 const char *fname = ".wpa_cli_history";
3070 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3071 hfile = os_malloc(hfile_len);
3072 if (hfile)
3073 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3074 }
3075
cd101567 3076 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
8953e968
JM
3077 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3078 wpa_cli_edit_completion_cb, NULL, hfile);
cd101567
JM
3079 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3080
cd101567
JM
3081 eloop_run();
3082
8953e968
JM
3083 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3084 os_free(hfile);
cd101567
JM
3085 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3086 wpa_cli_close_connection();
6f1c6549
JM
3087}
3088
6fc6879b
JM
3089
3090static void wpa_cli_action(struct wpa_ctrl *ctrl)
3091{
3092#ifdef CONFIG_ANSI_C_EXTRA
3093 /* TODO: ANSI C version(?) */
3094 printf("Action processing not supported in ANSI C build.\n");
3095#else /* CONFIG_ANSI_C_EXTRA */
3096 fd_set rfds;
3097 int fd, res;
3098 struct timeval tv;
3099 char buf[256]; /* note: large enough to fit in unsolicited messages */
3100 size_t len;
3101
3102 fd = wpa_ctrl_get_fd(ctrl);
3103
3104 while (!wpa_cli_quit) {
3105 FD_ZERO(&rfds);
3106 FD_SET(fd, &rfds);
1cc84c1c 3107 tv.tv_sec = ping_interval;
6fc6879b
JM
3108 tv.tv_usec = 0;
3109 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3110 if (res < 0 && errno != EINTR) {
3111 perror("select");
3112 break;
3113 }
3114
3115 if (FD_ISSET(fd, &rfds))
cd101567 3116 wpa_cli_recv_pending(ctrl, 1);
6fc6879b
JM
3117 else {
3118 /* verify that connection is still working */
3119 len = sizeof(buf) - 1;
3120 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3121 wpa_cli_action_cb) < 0 ||
3122 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3123 printf("wpa_supplicant did not reply to PING "
3124 "command - exiting\n");
3125 break;
3126 }
3127 }
3128 }
3129#endif /* CONFIG_ANSI_C_EXTRA */
3130}
3131
3132
3133static void wpa_cli_cleanup(void)
3134{
3135 wpa_cli_close_connection();
3136 if (pid_file)
3137 os_daemonize_terminate(pid_file);
3138
3139 os_program_deinit();
3140}
3141
3142static void wpa_cli_terminate(int sig)
3143{
3144 wpa_cli_cleanup();
3145 exit(0);
3146}
3147
3148
6fc6879b
JM
3149static char * wpa_cli_get_default_ifname(void)
3150{
3151 char *ifname = NULL;
3152
3153#ifdef CONFIG_CTRL_IFACE_UNIX
3154 struct dirent *dent;
3155 DIR *dir = opendir(ctrl_iface_dir);
b1001e4c
DS
3156 if (!dir) {
3157#ifdef ANDROID
3158 char ifprop[PROPERTY_VALUE_MAX];
3159 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3160 ifname = os_strdup(ifprop);
3161 printf("Using interface '%s'\n", ifname);
3162 return ifname;
3163 }
3164#endif /* ANDROID */
6fc6879b 3165 return NULL;
b1001e4c 3166 }
6fc6879b
JM
3167 while ((dent = readdir(dir))) {
3168#ifdef _DIRENT_HAVE_D_TYPE
3169 /*
3170 * Skip the file if it is not a socket. Also accept
3171 * DT_UNKNOWN (0) in case the C library or underlying
3172 * file system does not support d_type.
3173 */
3174 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3175 continue;
3176#endif /* _DIRENT_HAVE_D_TYPE */
3177 if (os_strcmp(dent->d_name, ".") == 0 ||
3178 os_strcmp(dent->d_name, "..") == 0)
3179 continue;
3180 printf("Selected interface '%s'\n", dent->d_name);
3181 ifname = os_strdup(dent->d_name);
3182 break;
3183 }
3184 closedir(dir);
3185#endif /* CONFIG_CTRL_IFACE_UNIX */
3186
3187#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3188 char buf[2048], *pos;
3189 size_t len;
3190 struct wpa_ctrl *ctrl;
3191 int ret;
3192
3193 ctrl = wpa_ctrl_open(NULL);
3194 if (ctrl == NULL)
3195 return NULL;
3196
3197 len = sizeof(buf) - 1;
3198 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3199 if (ret >= 0) {
3200 buf[len] = '\0';
3201 pos = os_strchr(buf, '\n');
3202 if (pos)
3203 *pos = '\0';
3204 ifname = os_strdup(buf);
3205 }
3206 wpa_ctrl_close(ctrl);
3207#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3208
3209 return ifname;
3210}
3211
3212
3213int main(int argc, char *argv[])
3214{
6fc6879b
JM
3215 int warning_displayed = 0;
3216 int c;
3217 int daemonize = 0;
3218 int ret = 0;
3219 const char *global = NULL;
3220
3221 if (os_program_init())
3222 return -1;
3223
3224 for (;;) {
1cc84c1c 3225 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
3226 if (c < 0)
3227 break;
3228 switch (c) {
3229 case 'a':
3230 action_file = optarg;
3231 break;
3232 case 'B':
3233 daemonize = 1;
3234 break;
3235 case 'g':
3236 global = optarg;
3237 break;
1cc84c1c
JM
3238 case 'G':
3239 ping_interval = atoi(optarg);
3240 break;
6fc6879b
JM
3241 case 'h':
3242 usage();
3243 return 0;
3244 case 'v':
3245 printf("%s\n", wpa_cli_version);
3246 return 0;
3247 case 'i':
3248 os_free(ctrl_ifname);
3249 ctrl_ifname = os_strdup(optarg);
3250 break;
3251 case 'p':
3252 ctrl_iface_dir = optarg;
3253 break;
3254 case 'P':
3255 pid_file = optarg;
3256 break;
3257 default:
3258 usage();
3259 return -1;
3260 }
3261 }
3262
3263 interactive = (argc == optind) && (action_file == NULL);
3264
3265 if (interactive)
3266 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3267
cd101567
JM
3268 if (eloop_init())
3269 return -1;
3270
6fc6879b
JM
3271 if (global) {
3272#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3273 ctrl_conn = wpa_ctrl_open(NULL);
3274#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3275 ctrl_conn = wpa_ctrl_open(global);
3276#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3277 if (ctrl_conn == NULL) {
3278 perror("Failed to connect to wpa_supplicant - "
3279 "wpa_ctrl_open");
3280 return -1;
3281 }
3282 }
3283
6fc6879b
JM
3284#ifndef _WIN32_WCE
3285 signal(SIGINT, wpa_cli_terminate);
3286 signal(SIGTERM, wpa_cli_terminate);
3287#endif /* _WIN32_WCE */
6fc6879b 3288
4a3ade4e
JM
3289 if (ctrl_ifname == NULL)
3290 ctrl_ifname = wpa_cli_get_default_ifname();
3291
3292 if (interactive) {
3293 for (; !global;) {
3294 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3295 if (warning_displayed)
3296 printf("Connection established.\n");
3297 break;
3298 }
3299
3300 if (!warning_displayed) {
3301 printf("Could not connect to wpa_supplicant - "
3302 "re-trying\n");
3303 warning_displayed = 1;
3304 }
3305 os_sleep(1, 0);
3306 continue;
3307 }
3308 } else {
3309 if (!global &&
3310 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3311 perror("Failed to connect to wpa_supplicant - "
3312 "wpa_ctrl_open");
3313 return -1;
3314 }
3315
3316 if (action_file) {
3317 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3318 wpa_cli_attached = 1;
3319 } else {
3320 printf("Warning: Failed to attach to "
3321 "wpa_supplicant.\n");
6fc6879b 3322 return -1;
4a3ade4e 3323 }
6fc6879b
JM
3324 }
3325 }
3326
3327 if (daemonize && os_daemonize(pid_file))
3328 return -1;
3329
3330 if (interactive)
3331 wpa_cli_interactive();
3332 else if (action_file)
3333 wpa_cli_action(ctrl_conn);
3334 else
3335 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3336
3337 os_free(ctrl_ifname);
cd101567 3338 eloop_destroy();
6fc6879b
JM
3339 wpa_cli_cleanup();
3340
3341 return ret;
3342}
3343
3344#else /* CONFIG_CTRL_IFACE */
3345int main(int argc, char *argv[])
3346{
3347 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3348 return -1;
3349}
3350#endif /* CONFIG_CTRL_IFACE */