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