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