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