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