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