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