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