X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=wpa_supplicant%2Fwpa_cli.c;h=00fb0dccae9935861140b493a347d9571253aac1;hb=HEAD;hp=6cd9c6890768e71b6b35a80cbd2bb86c72fcace3;hpb=cbf78558838a5abd61473fcd45b8fdaf6108b22f;p=libeap.git diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 6cd9c68..00fb0dc 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -127,14 +127,66 @@ static void usage(void) } +static void readline_redraw() +{ +#ifdef CONFIG_READLINE + rl_on_new_line(); + rl_redisplay(); +#endif /* CONFIG_READLINE */ +} + + +static int str_starts(const char *src, const char *match) +{ + return os_strncmp(src, match, os_strlen(match)) == 0; +} + + +static int wpa_cli_show_event(const char *event) +{ + const char *start; + + start = os_strchr(event, '>'); + if (start == NULL) + return 1; + + start++; + /* + * Skip BSS added/removed events since they can be relatively frequent + * and are likely of not much use for an interactive user. + */ + if (str_starts(start, WPA_EVENT_BSS_ADDED) || + str_starts(start, WPA_EVENT_BSS_REMOVED)) + return 0; + + return 1; +} + + #ifdef CONFIG_WPA_CLI_FORK +static int in_query = 0; + +static void wpa_cli_monitor_sig(int sig) +{ + if (sig == SIGUSR1) + in_query = 1; + else if (sig == SIGUSR2) + in_query = 0; +} + + static void wpa_cli_monitor(void) { char buf[256]; size_t len = sizeof(buf) - 1; struct timeval tv; fd_set rfds; + int ppid; + + signal(SIGUSR1, wpa_cli_monitor_sig); + signal(SIGUSR2, wpa_cli_monitor_sig); + ppid = getppid(); while (mon_conn) { int s = wpa_ctrl_get_fd(mon_conn); tv.tv_sec = 5; @@ -142,6 +194,8 @@ static void wpa_cli_monitor(void) FD_ZERO(&rfds); FD_SET(s, &rfds); if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) { + if (errno == EINTR) + continue; perror("select"); break; } @@ -155,7 +209,12 @@ static void wpa_cli_monitor(void) break; } buf[len] = '\0'; - printf("%s\n", buf); + if (wpa_cli_show_event(buf)) { + if (in_query) + printf("\r"); + printf("%s\n", buf); + kill(ppid, SIGUSR1); + } } } } @@ -237,6 +296,15 @@ static void wpa_cli_close_connection(void) if (ctrl_conn == NULL) return; +#ifdef CONFIG_WPA_CLI_FORK + if (mon_pid) { + int status; + kill(mon_pid, SIGPIPE); + wait(&status); + mon_pid = 0; + } +#endif /* CONFIG_WPA_CLI_FORK */ + if (wpa_cli_attached) { wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); wpa_cli_attached = 0; @@ -247,14 +315,6 @@ static void wpa_cli_close_connection(void) wpa_ctrl_close(mon_conn); mon_conn = NULL; } -#ifdef CONFIG_WPA_CLI_FORK - if (mon_pid) { - int status; - kill(mon_pid, SIGPIPE); - wait(&status); - mon_pid = 0; - } -#endif /* CONFIG_WPA_CLI_FORK */ } @@ -311,6 +371,19 @@ static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256]; + int ret; + if (argc == 0) + return -1; + ret = os_snprintf(cmd, sizeof(cmd), "NOTE %s", argv[0]); + if (ret < 0 || (size_t) ret >= sizeof(cmd)) + return -1; + return wpa_ctrl_command(ctrl, cmd); +} + + static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "MIB"); @@ -542,6 +615,39 @@ static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc != 1 && argc != 2) { + printf("Invalid WPS_CHECK_PIN command: needs one argument:\n" + "- PIN to be verified\n"); + return -1; + } + + if (argc == 2) + res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s", + argv[0], argv[1]); + else + res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s", + argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long WPS_CHECK_PIN command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "WPS_CANCEL"); +} + + #ifdef CONFIG_WPS_OOB static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -583,7 +689,7 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc == 2) res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]); - else if (argc == 6) { + else if (argc == 5 || argc == 6) { char ssid_hex[2 * 32 + 1]; char key_hex[2 * 64 + 1]; int i; @@ -596,10 +702,13 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) } key_hex[0] = '\0'; - for (i = 0; i < 64; i++) { - if (argv[5][i] == '\0') - break; - os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]); + if (argc == 6) { + for (i = 0; i < 64; i++) { + if (argv[5][i] == '\0') + break; + os_snprintf(&key_hex[i * 2], 3, "%02x", + argv[5][i]); + } } res = os_snprintf(cmd, sizeof(cmd), @@ -632,8 +741,12 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc, char *argv[]) { + char cmd[100]; + if (argc > 0) { + os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]); + return wpa_ctrl_command(ctrl, cmd); + } return wpa_ctrl_command(ctrl, "WPS_ER_START"); - } @@ -651,15 +764,21 @@ static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc, char cmd[256]; int res; - if (argc != 2) { - printf("Invalid WPS_ER_PIN command: need two arguments:\n" + if (argc < 2) { + printf("Invalid WPS_ER_PIN command: need at least two " + "arguments:\n" "- UUID: use 'any' to select any\n" - "- PIN: Enrollee PIN\n"); + "- PIN: Enrollee PIN\n" + "optional: - Enrollee MAC address\n"); return -1; } - res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s", - argv[0], argv[1]); + if (argc > 2) + res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s", + argv[0], argv[1], argv[2]); + else + res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s", + argv[0], argv[1]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long WPS_ER_PIN command.\n"); return -1; @@ -713,6 +832,57 @@ static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc == 5 || argc == 6) { + char ssid_hex[2 * 32 + 1]; + char key_hex[2 * 64 + 1]; + int i; + + ssid_hex[0] = '\0'; + for (i = 0; i < 32; i++) { + if (argv[2][i] == '\0') + break; + os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); + } + + key_hex[0] = '\0'; + if (argc == 6) { + for (i = 0; i < 64; i++) { + if (argv[5][i] == '\0') + break; + os_snprintf(&key_hex[i * 2], 3, "%02x", + argv[5][i]); + } + } + + res = os_snprintf(cmd, sizeof(cmd), + "WPS_ER_CONFIG %s %s %s %s %s %s", + argv[0], argv[1], ssid_hex, argv[3], argv[4], + key_hex); + } else { + printf("Invalid WPS_ER_CONFIG command: need six arguments:\n" + "- AP UUID\n" + "- AP PIN\n" + "- new SSID\n" + "- new auth (OPEN, WPAPSK, WPA2PSK)\n" + "- new encr (NONE, WEP, TKIP, CCMP)\n" + "- new key\n"); + return -1; + } + + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long WPS_ER_CONFIG command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; @@ -1347,7 +1517,7 @@ static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) "address, is required.\n"); return -1; } - snprintf(buf, sizeof(buf), "STA %s", argv[0]); + os_snprintf(buf, sizeof(buf), "STA %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } @@ -1395,7 +1565,7 @@ static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr))) return 0; do { - snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); + os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0); return -1; @@ -1403,134 +1573,698 @@ static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) #endif /* CONFIG_AP */ -enum wpa_cli_cmd_flags { - cli_cmd_flag_none = 0x00, - cli_cmd_flag_sensitive = 0x01 -}; +static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "SUSPEND"); +} -struct wpa_cli_cmd { - const char *cmd; - int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); - enum wpa_cli_cmd_flags flags; - const char *usage; -}; -static struct wpa_cli_cmd wpa_cli_commands[] = { - { "status", wpa_cli_cmd_status, - cli_cmd_flag_none, - "[verbose] = get current WPA/EAPOL/EAP status" }, - { "ping", wpa_cli_cmd_ping, - cli_cmd_flag_none, - "= pings wpa_supplicant" }, - { "mib", wpa_cli_cmd_mib, - cli_cmd_flag_none, - "= get MIB variables (dot1x, dot11)" }, - { "help", wpa_cli_cmd_help, - cli_cmd_flag_none, - "= show this usage help" }, - { "interface", wpa_cli_cmd_interface, - cli_cmd_flag_none, - "[ifname] = show interfaces/select interface" }, - { "level", wpa_cli_cmd_level, - cli_cmd_flag_none, - " = change debug level" }, - { "license", wpa_cli_cmd_license, - cli_cmd_flag_none, - "= show full wpa_cli license" }, - { "quit", wpa_cli_cmd_quit, - cli_cmd_flag_none, - "= exit wpa_cli" }, - { "set", wpa_cli_cmd_set, - cli_cmd_flag_none, - "= set variables (shows list of variables when run without " - "arguments)" }, - { "logon", wpa_cli_cmd_logon, - cli_cmd_flag_none, - "= IEEE 802.1X EAPOL state machine logon" }, - { "logoff", wpa_cli_cmd_logoff, - cli_cmd_flag_none, - "= IEEE 802.1X EAPOL state machine logoff" }, - { "pmksa", wpa_cli_cmd_pmksa, - cli_cmd_flag_none, - "= show PMKSA cache" }, - { "reassociate", wpa_cli_cmd_reassociate, - cli_cmd_flag_none, - "= force reassociation" }, - { "preauthenticate", wpa_cli_cmd_preauthenticate, - cli_cmd_flag_none, - " = force preauthentication" }, - { "identity", wpa_cli_cmd_identity, - cli_cmd_flag_none, - " = configure identity for an SSID" }, - { "password", wpa_cli_cmd_password, - cli_cmd_flag_sensitive, - " = configure password for an SSID" }, - { "new_password", wpa_cli_cmd_new_password, - cli_cmd_flag_sensitive, - " = change password for an SSID" }, - { "pin", wpa_cli_cmd_pin, - cli_cmd_flag_sensitive, - " = configure pin for an SSID" }, - { "otp", wpa_cli_cmd_otp, - cli_cmd_flag_sensitive, - " = configure one-time-password for an SSID" - }, - { "passphrase", wpa_cli_cmd_passphrase, - cli_cmd_flag_sensitive, - " = configure private key passphrase\n" - " for an SSID" }, - { "bssid", wpa_cli_cmd_bssid, - cli_cmd_flag_none, - " = set preferred BSSID for an SSID" }, - { "list_networks", wpa_cli_cmd_list_networks, - cli_cmd_flag_none, - "= list configured networks" }, - { "select_network", wpa_cli_cmd_select_network, - cli_cmd_flag_none, - " = select a network (disable others)" }, - { "enable_network", wpa_cli_cmd_enable_network, - cli_cmd_flag_none, - " = enable a network" }, - { "disable_network", wpa_cli_cmd_disable_network, - cli_cmd_flag_none, - " = disable a network" }, - { "add_network", wpa_cli_cmd_add_network, - cli_cmd_flag_none, - "= add a network" }, - { "remove_network", wpa_cli_cmd_remove_network, - cli_cmd_flag_none, - " = remove a network" }, - { "set_network", wpa_cli_cmd_set_network, - cli_cmd_flag_sensitive, - " = set network variables (shows\n" - " list of variables when run without arguments)" }, - { "get_network", wpa_cli_cmd_get_network, - cli_cmd_flag_none, - " = get network variables" }, - { "save_config", wpa_cli_cmd_save_config, - cli_cmd_flag_none, - "= save the current configuration" }, - { "disconnect", wpa_cli_cmd_disconnect, - cli_cmd_flag_none, - "= disconnect and wait for reassociate/reconnect command before\n" - " connecting" }, - { "reconnect", wpa_cli_cmd_reconnect, - cli_cmd_flag_none, - "= like reassociate, but only takes effect if already disconnected" - }, - { "scan", wpa_cli_cmd_scan, - cli_cmd_flag_none, - "= request new BSS scan" }, - { "scan_results", wpa_cli_cmd_scan_results, - cli_cmd_flag_none, - "= get latest scan results" }, - { "bss", wpa_cli_cmd_bss, - cli_cmd_flag_none, - "< | > = get detailed scan result info" }, - { "get_capability", wpa_cli_cmd_get_capability, - cli_cmd_flag_none, - " = get capabilies" }, - { "reconfigure", wpa_cli_cmd_reconfigure, +static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RESUME"); +} + + +static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DROP_SA"); +} + + +static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 1) { + printf("Invalid ROAM command: needs one argument " + "(target AP's BSSID)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long ROAM command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +#ifdef CONFIG_P2P + +static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc == 0) + return wpa_ctrl_command(ctrl, "P2P_FIND"); + + if (argc > 1) + res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s", + argv[0], argv[1]); + else + res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_STOP_FIND"); +} + + +static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[128]; + int res; + + if (argc < 2) { + printf("Invalid P2P_CONNECT command: needs at least two " + "arguments (address and pbc/PIN)\n"); + return -1; + } + + if (argc > 4) + res = os_snprintf(cmd, sizeof(cmd), + "P2P_CONNECT %s %s %s %s %s", + argv[0], argv[1], argv[2], argv[3], + argv[4]); + else if (argc > 3) + res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + else if (argc > 2) + res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s", + argv[0], argv[1], argv[2]); + else + res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[128]; + int res; + + if (argc == 0) + return wpa_ctrl_command(ctrl, "P2P_LISTEN"); + + res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 1) { + printf("Invalid P2P_GROUP_REMOVE command: needs one argument " + "(interface name)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[128]; + int res; + + if (argc == 0) + return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD"); + + res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 2) { + printf("Invalid P2P_PROV_DISC command: needs two arguments " + "(address and config method\n" + "(display, keypad, or pbc)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE"); +} + + +static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[4096]; + int res; + + if (argc != 2 && argc != 4) { + printf("Invalid P2P_SERV_DISC_REQ command: needs two " + "arguments (address and TLVs) or four arguments " + "(address, \"upnp\", version, search target " + "(SSDP ST:)\n"); + return -1; + } + + if (argc == 4) + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERV_DISC_REQ %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + else + res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 1) { + printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one " + "argument (pending request identifier)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s", + argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[4096]; + int res; + + if (argc != 4) { + printf("Invalid P2P_SERV_DISC_RESP command: needs four " + "arguments (freq, address, dialog token, and TLVs)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE"); +} + + +static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 1) { + printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one " + "argument (external processing: 0/1)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s", + argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH"); +} + + +static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[4096]; + int res; + + if (argc != 3 && argc != 4) { + printf("Invalid P2P_SERVICE_ADD command: needs three or four " + "arguments\n"); + return -1; + } + + if (argc == 4) + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERVICE_ADD %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + else + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERVICE_ADD %s %s %s", + argv[0], argv[1], argv[2]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[4096]; + int res; + + if (argc != 2 && argc != 3) { + printf("Invalid P2P_SERVICE_DEL command: needs two or three " + "arguments\n"); + return -1; + } + + if (argc == 3) + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERVICE_DEL %s %s %s", + argv[0], argv[1], argv[2]); + else + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERVICE_DEL %s %s", + argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 1) { + printf("Invalid P2P_REJECT command: needs one argument " + "(peer address)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc < 1) { + printf("Invalid P2P_INVITE command: needs at least one " + "argument\n"); + return -1; + } + + if (argc > 2) + res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s", + argv[0], argv[1], argv[2]); + else if (argc > 1) + res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s", + argv[0], argv[1]); + else + res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char buf[64]; + if (argc != 1) { + printf("Invalid 'p2p_peer' command - exactly one argument, " + "P2P peer device address, is required.\n"); + return -1; + } + os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]); + return wpa_ctrl_command(ctrl, buf); +} + + +static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd, + char *addr, size_t addr_len, + int discovered) +{ + char buf[4096], *pos; + size_t len; + int ret; + + if (ctrl_conn == NULL) + return -1; + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + printf("'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + printf("'%s' command failed.\n", cmd); + return -1; + } + + buf[len] = '\0'; + if (memcmp(buf, "FAIL", 4) == 0) + return -1; + + pos = buf; + while (*pos != '\0' && *pos != '\n') + pos++; + *pos++ = '\0'; + os_strlcpy(addr, buf, addr_len); + if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL) + printf("%s\n", addr); + return 0; +} + + +static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char addr[32], cmd[64]; + int discovered; + + discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0; + + if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST", + addr, sizeof(addr), discovered)) + return 0; + do { + os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr); + } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr), + discovered) == 0); + + return -1; +} + + +static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[100]; + int res; + + if (argc != 2) { + printf("Invalid P2P_SET command: needs two arguments (field, " + "value)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_FLUSH"); +} + + +static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[100]; + int res; + + if (argc != 0 && argc != 2 && argc != 4) { + printf("Invalid P2P_PRESENCE_REQ command: needs two arguments " + "(preferred duration, interval; in microsecods).\n" + "Optional second pair can be used to provide " + "acceptable values.\n"); + return -1; + } + + if (argc == 4) + res = os_snprintf(cmd, sizeof(cmd), + "P2P_PRESENCE_REQ %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + else if (argc == 2) + res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s", + argv[0], argv[1]); + else + res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ"); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[100]; + int res; + + if (argc != 0 && argc != 2) { + printf("Invalid P2P_EXT_LISTEN command: needs two arguments " + "(availability period, availability interval; in " + "millisecods).\n" + "Extended Listen Timing can be cancelled with this " + "command when used without parameters.\n"); + return -1; + } + + if (argc == 2) + res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s", + argv[0], argv[1]); + else + res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN"); + if (res < 0 || (size_t) res >= sizeof(cmd)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + +#endif /* CONFIG_P2P */ + + +static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc != 1) { + printf("Invalid STA_AUTOCONNECT command: needs one argument " + "(0/1 = disable/enable automatic reconnection)\n"); + return -1; + } + res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long STA_AUTOCONNECT command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +enum wpa_cli_cmd_flags { + cli_cmd_flag_none = 0x00, + cli_cmd_flag_sensitive = 0x01 +}; + +struct wpa_cli_cmd { + const char *cmd; + int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); + enum wpa_cli_cmd_flags flags; + const char *usage; +}; + +static struct wpa_cli_cmd wpa_cli_commands[] = { + { "status", wpa_cli_cmd_status, + cli_cmd_flag_none, + "[verbose] = get current WPA/EAPOL/EAP status" }, + { "ping", wpa_cli_cmd_ping, + cli_cmd_flag_none, + "= pings wpa_supplicant" }, + { "note", wpa_cli_cmd_note, + cli_cmd_flag_none, + " = add a note to wpa_supplicant debug log" }, + { "mib", wpa_cli_cmd_mib, + cli_cmd_flag_none, + "= get MIB variables (dot1x, dot11)" }, + { "help", wpa_cli_cmd_help, + cli_cmd_flag_none, + "= show this usage help" }, + { "interface", wpa_cli_cmd_interface, + cli_cmd_flag_none, + "[ifname] = show interfaces/select interface" }, + { "level", wpa_cli_cmd_level, + cli_cmd_flag_none, + " = change debug level" }, + { "license", wpa_cli_cmd_license, + cli_cmd_flag_none, + "= show full wpa_cli license" }, + { "quit", wpa_cli_cmd_quit, + cli_cmd_flag_none, + "= exit wpa_cli" }, + { "set", wpa_cli_cmd_set, + cli_cmd_flag_none, + "= set variables (shows list of variables when run without " + "arguments)" }, + { "logon", wpa_cli_cmd_logon, + cli_cmd_flag_none, + "= IEEE 802.1X EAPOL state machine logon" }, + { "logoff", wpa_cli_cmd_logoff, + cli_cmd_flag_none, + "= IEEE 802.1X EAPOL state machine logoff" }, + { "pmksa", wpa_cli_cmd_pmksa, + cli_cmd_flag_none, + "= show PMKSA cache" }, + { "reassociate", wpa_cli_cmd_reassociate, + cli_cmd_flag_none, + "= force reassociation" }, + { "preauthenticate", wpa_cli_cmd_preauthenticate, + cli_cmd_flag_none, + " = force preauthentication" }, + { "identity", wpa_cli_cmd_identity, + cli_cmd_flag_none, + " = configure identity for an SSID" }, + { "password", wpa_cli_cmd_password, + cli_cmd_flag_sensitive, + " = configure password for an SSID" }, + { "new_password", wpa_cli_cmd_new_password, + cli_cmd_flag_sensitive, + " = change password for an SSID" }, + { "pin", wpa_cli_cmd_pin, + cli_cmd_flag_sensitive, + " = configure pin for an SSID" }, + { "otp", wpa_cli_cmd_otp, + cli_cmd_flag_sensitive, + " = configure one-time-password for an SSID" + }, + { "passphrase", wpa_cli_cmd_passphrase, + cli_cmd_flag_sensitive, + " = configure private key passphrase\n" + " for an SSID" }, + { "bssid", wpa_cli_cmd_bssid, + cli_cmd_flag_none, + " = set preferred BSSID for an SSID" }, + { "list_networks", wpa_cli_cmd_list_networks, + cli_cmd_flag_none, + "= list configured networks" }, + { "select_network", wpa_cli_cmd_select_network, + cli_cmd_flag_none, + " = select a network (disable others)" }, + { "enable_network", wpa_cli_cmd_enable_network, + cli_cmd_flag_none, + " = enable a network" }, + { "disable_network", wpa_cli_cmd_disable_network, + cli_cmd_flag_none, + " = disable a network" }, + { "add_network", wpa_cli_cmd_add_network, + cli_cmd_flag_none, + "= add a network" }, + { "remove_network", wpa_cli_cmd_remove_network, + cli_cmd_flag_none, + " = remove a network" }, + { "set_network", wpa_cli_cmd_set_network, + cli_cmd_flag_sensitive, + " = set network variables (shows\n" + " list of variables when run without arguments)" }, + { "get_network", wpa_cli_cmd_get_network, + cli_cmd_flag_none, + " = get network variables" }, + { "save_config", wpa_cli_cmd_save_config, + cli_cmd_flag_none, + "= save the current configuration" }, + { "disconnect", wpa_cli_cmd_disconnect, + cli_cmd_flag_none, + "= disconnect and wait for reassociate/reconnect command before\n" + " connecting" }, + { "reconnect", wpa_cli_cmd_reconnect, + cli_cmd_flag_none, + "= like reassociate, but only takes effect if already disconnected" + }, + { "scan", wpa_cli_cmd_scan, + cli_cmd_flag_none, + "= request new BSS scan" }, + { "scan_results", wpa_cli_cmd_scan_results, + cli_cmd_flag_none, + "= get latest scan results" }, + { "bss", wpa_cli_cmd_bss, + cli_cmd_flag_none, + "< | > = get detailed scan result info" }, + { "get_capability", wpa_cli_cmd_get_capability, + cli_cmd_flag_none, + " = get capabilies" }, + { "reconfigure", wpa_cli_cmd_reconfigure, cli_cmd_flag_none, "= force wpa_supplicant to re-read its configuration file" }, { "terminate", wpa_cli_cmd_terminate, @@ -1563,6 +2297,11 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { cli_cmd_flag_sensitive, " [PIN] = start WPS PIN method (returns PIN, if not " "hardcoded)" }, + { "wps_check_pin", wpa_cli_cmd_wps_check_pin, + cli_cmd_flag_sensitive, + " = verify PIN checksum" }, + { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none, + "Cancels the pending WPS operation" }, #ifdef CONFIG_WPS_OOB { "wps_oob", wpa_cli_cmd_wps_oob, cli_cmd_flag_sensitive, @@ -1573,7 +2312,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { " = start WPS Registrar to configure an AP" }, { "wps_er_start", wpa_cli_cmd_wps_er_start, cli_cmd_flag_none, - "= start Wi-Fi Protected Setup External Registrar" }, + "[IP address] = start Wi-Fi Protected Setup External Registrar" }, { "wps_er_stop", wpa_cli_cmd_wps_er_stop, cli_cmd_flag_none, "= stop Wi-Fi Protected Setup External Registrar" }, @@ -1586,6 +2325,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "wps_er_learn", wpa_cli_cmd_wps_er_learn, cli_cmd_flag_sensitive, " = learn AP configuration" }, + { "wps_er_config", wpa_cli_cmd_wps_er_config, + cli_cmd_flag_sensitive, + " = configure AP" }, { "ibss_rsn", wpa_cli_cmd_ibss_rsn, cli_cmd_flag_none, " = request RSN authentication with in IBSS" }, @@ -1597,6 +2339,82 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { cli_cmd_flag_none, "= get information about all associated stations (AP)" }, #endif /* CONFIG_AP */ + { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none, + "= notification of suspend/hibernate" }, + { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none, + "= notification of resume/thaw" }, + { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none, + "= drop SA without deauth/disassoc (test command)" }, + { "roam", wpa_cli_cmd_roam, + cli_cmd_flag_none, + " = roam to the specified BSS" }, +#ifdef CONFIG_P2P + { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none, + "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" }, + { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none, + "= stop P2P Devices search" }, + { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none, + " <\"pbc\"|PIN> = connect to a P2P Devices" }, + { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none, + "[timeout] = listen for P2P Devices for up-to timeout seconds" }, + { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none, + " = remote P2P group interface (terminate group if GO)" }, + { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none, + "= add a new P2P group (local end as GO)" }, + { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none, + " = request provisioning discovery" }, + { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, + cli_cmd_flag_none, + "= get the passphrase for a group (GO only)" }, + { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req, + cli_cmd_flag_none, + " = schedule service discovery request" }, + { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req, + cli_cmd_flag_none, + " = cancel pending service discovery request" }, + { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, + cli_cmd_flag_none, + " = service discovery response" }, + { "p2p_service_update", wpa_cli_cmd_p2p_service_update, + cli_cmd_flag_none, + "= indicate change in local services" }, + { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, + cli_cmd_flag_none, + " = set external processing of service discovery" }, + { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, + cli_cmd_flag_none, + "= remove all stored service entries" }, + { "p2p_service_add", wpa_cli_cmd_p2p_service_add, + cli_cmd_flag_none, + " = add a local " + "service" }, + { "p2p_service_del", wpa_cli_cmd_p2p_service_del, + cli_cmd_flag_none, + " [|service] = remove a local " + "service" }, + { "p2p_reject", wpa_cli_cmd_p2p_reject, + cli_cmd_flag_none, + " = reject connection attempts from a specific peer" }, + { "p2p_invite", wpa_cli_cmd_p2p_invite, + cli_cmd_flag_none, + " [peer=addr] = invite peer" }, + { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none, + "[discovered] = list known (optionally, only fully discovered) P2P " + "peers" }, + { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none, + "
= show information about known P2P peer" }, + { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none, + " = set a P2P parameter" }, + { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none, + "= flush P2P state" }, + { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none, + "[ ] [ ] = request GO " + "presence" }, + { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none, + "[ ] = set extended listen timing" }, +#endif /* CONFIG_P2P */ + { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none, + "<0/1> = disable/enable automatic reconnection" }, { NULL, NULL, cli_cmd_flag_none, NULL } }; @@ -1786,6 +2604,18 @@ static void wpa_cli_action_process(const char *msg) wpa_cli_connected = 0; wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); } + } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); + } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); + } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); + } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); + } else if (str_match(pos, WPS_EVENT_SUCCESS)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); + } else if (str_match(pos, WPS_EVENT_FAIL)) { + wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, WPA_EVENT_TERMINATING)) { printf("wpa_supplicant is terminating - stop monitoring\n"); wpa_cli_quit = 1; @@ -1824,10 +2654,13 @@ static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, if (action_monitor) wpa_cli_action_process(buf); else { - if (in_read && first) - printf("\n"); - first = 0; - printf("%s\n", buf); + if (wpa_cli_show_event(buf)) { + if (in_read && first) + printf("\r"); + first = 0; + printf("%s\n", buf); + readline_redraw(); + } } } else { printf("Could not read pending message.\n"); @@ -1866,14 +2699,59 @@ static char * wpa_cli_cmd_gen(const char *text, int state) static char * wpa_cli_dummy_gen(const char *text, int state) { + int i; + + for (i = 0; wpa_cli_commands[i].cmd; i++) { + const char *cmd = wpa_cli_commands[i].cmd; + size_t len = os_strlen(cmd); + if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 && + rl_line_buffer[len] == ' ') { + printf("\n%s\n", wpa_cli_commands[i].usage); + readline_redraw(); + break; + } + } + + rl_attempted_completion_over = 1; + return NULL; +} + + +static char * wpa_cli_status_gen(const char *text, int state) +{ + static int i, len; + char *options[] = { + "verbose", NULL + }; + char *t; + + if (state == 0) { + i = 0; + len = os_strlen(text); + } + + while ((t = options[i])) { + i++; + if (os_strncasecmp(t, text, len) == 0) + return strdup(t); + } + + rl_attempted_completion_over = 1; return NULL; } static char ** wpa_cli_completion(const char *text, int start, int end) { - return rl_completion_matches(text, start == 0 ? - wpa_cli_cmd_gen : wpa_cli_dummy_gen); + char * (*func)(const char *text, int state); + + if (start == 0) + func = wpa_cli_cmd_gen; + else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0) + func = wpa_cli_status_gen; + else + func = wpa_cli_dummy_gen; + return rl_completion_matches(text, func); } #endif /* CONFIG_READLINE */ @@ -1914,6 +2792,10 @@ static void wpa_cli_interactive(void) #ifndef CONFIG_NATIVE_WINDOWS alarm(ping_interval); #endif /* CONFIG_NATIVE_WINDOWS */ +#ifdef CONFIG_WPA_CLI_FORK + if (mon_pid) + kill(mon_pid, SIGUSR1); +#endif /* CONFIG_WPA_CLI_FORK */ #ifdef CONFIG_READLINE cmd = readline("> "); if (cmd && *cmd) { @@ -1969,6 +2851,10 @@ static void wpa_cli_interactive(void) if (cmd != cmdbuf) free(cmd); +#ifdef CONFIG_WPA_CLI_FORK + if (mon_pid) + kill(mon_pid, SIGUSR2); +#endif /* CONFIG_WPA_CLI_FORK */ } while (!wpa_cli_quit); #ifdef CONFIG_READLINE @@ -2058,6 +2944,14 @@ static void wpa_cli_terminate(int sig) } +#ifdef CONFIG_WPA_CLI_FORK +static void wpa_cli_usr1(int sig) +{ + readline_redraw(); +} +#endif /* CONFIG_WPA_CLI_FORK */ + + #ifndef CONFIG_NATIVE_WINDOWS static void wpa_cli_alarm(int sig) { @@ -2205,6 +3099,9 @@ int main(int argc, char *argv[]) #ifndef CONFIG_NATIVE_WINDOWS signal(SIGALRM, wpa_cli_alarm); #endif /* CONFIG_NATIVE_WINDOWS */ +#ifdef CONFIG_WPA_CLI_FORK + signal(SIGUSR1, wpa_cli_usr1); +#endif /* CONFIG_WPA_CLI_FORK */ if (ctrl_ifname == NULL) ctrl_ifname = wpa_cli_get_default_ifname();