/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#endif /* ANDROID */
-static const char *wpa_cli_version =
+static const char *const wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
-static const char *wpa_cli_license =
+static const char *const wpa_cli_license =
"This software may be distributed under the terms of the BSD license.\n"
"See README for more details.\n";
-static const char *wpa_cli_full_license =
+static const char *const wpa_cli_full_license =
"This software may be distributed under the terms of the BSD license.\n"
"\n"
"Redistribution and use in source and binary forms, with or without\n"
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
"\n";
+#define VENDOR_ELEM_FRAME_ID \
+ " 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
+ "3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
+ "7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \
+ "11: Assoc Req (P2P), 12: Assoc Resp (P2P)"
+
static struct wpa_ctrl *ctrl_conn;
static struct wpa_ctrl *mon_conn;
static int wpa_cli_quit = 0;
static int wpa_cli_attached = 0;
-static int wpa_cli_connected = 0;
+static int wpa_cli_connected = -1;
static int wpa_cli_last_id = 0;
#ifndef CONFIG_CTRL_IFACE_DIR
#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
#endif /* CONFIG_CTRL_IFACE_DIR */
static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
+static const char *client_socket_dir = NULL;
static char *ctrl_ifname = NULL;
static const char *pid_file = NULL;
static const char *action_file = NULL;
static int ping_interval = 5;
static int interactive = 0;
+static char *ifname_prefix = NULL;
struct cli_txt_entry {
struct dl_list list;
static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
static void print_help(const char *cmd);
static void wpa_cli_close_connection(void);
static char * wpa_cli_get_default_ifname(void);
static char ** wpa_list_cmd_list(void);
+static void update_networks(struct wpa_ctrl *ctrl);
static void usage(void)
{
printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
"[-a<action file>] \\\n"
- " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
+ " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
+ "\\\n"
+ " [-s<wpa_client_socket_file_path>] "
"[command..]\n"
" -h = help (show this usage text)\n"
" -v = shown version information\n"
#ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
+static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator)
{
const char *end;
char *buf;
- end = os_strchr(txt, ' ');
+ end = os_strchr(txt, separator);
if (end == NULL)
end = txt + os_strlen(txt);
buf = dup_binstr(txt, end - txt);
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
return cli_txt_list_add(txt_list, buf);
}
+#endif /* CONFIG_P2P */
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
+static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator)
{
const char *end;
char *buf;
int ret;
- end = os_strchr(txt, ' ');
+ end = os_strchr(txt, separator);
if (end == NULL)
end = txt + os_strlen(txt);
buf = dup_binstr(txt, end - txt);
os_free(buf);
return ret;
}
-#endif /* CONFIG_P2P */
static char ** cli_txt_list_array(struct dl_list *txt_list)
}
#endif /* ANDROID */
+ if (client_socket_dir && client_socket_dir[0] &&
+ access(client_socket_dir, F_OK) < 0) {
+ perror(client_socket_dir);
+ os_free(cfile);
+ return -1;
+ }
+
if (cfile == NULL) {
flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
cfile = os_malloc(flen);
return -1;
res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
ifname);
- if (res < 0 || res >= flen) {
+ if (os_snprintf_error(flen, res)) {
os_free(cfile);
return -1;
}
}
- ctrl_conn = wpa_ctrl_open(cfile);
+ ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
if (ctrl_conn == NULL) {
os_free(cfile);
return -1;
}
if (attach && interactive)
- mon_conn = wpa_ctrl_open(cfile);
+ mon_conn = wpa_ctrl_open2(cfile, client_socket_dir);
else
mon_conn = NULL;
os_free(cfile);
printf("Not connected to wpa_supplicant - command dropped.\n");
return -1;
}
+ if (ifname_prefix) {
+ os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
+ ifname_prefix, cmd);
+ buf[sizeof(buf) - 1] = '\0';
+ cmd = buf;
+ }
len = sizeof(buf) - 1;
ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
wpa_cli_msg_cb);
end = buf + buflen;
res = os_snprintf(pos, end - pos, "%s", cmd);
- if (res < 0 || res >= end - pos)
+ if (os_snprintf_error(end - pos, res))
goto fail;
pos += res;
for (i = 0; i < argc; i++) {
res = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (res < 0 || res >= end - pos)
+ if (os_snprintf_error(end - pos, res))
goto fail;
pos += res;
}
return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
return wpa_ctrl_command(ctrl, "STATUS-WPS");
+ if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
+ return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
+#ifdef ANDROID
+ if (argc > 0 && os_strcmp(argv[0], "no_events") == 0)
+ return wpa_ctrl_command(ctrl, "STATUS-NO_EVENTS");
+#endif /* ANDROID */
return wpa_ctrl_command(ctrl, "STATUS");
}
}
+static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
+}
+
+
static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
print_help(argc > 0 ? argv[0] : NULL);
if (argc == 1) {
res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long SET command.\n");
return -1;
}
"uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
"no_keep_alive",
/* global configuration parameters */
- "eapol_version", "ap_scan", "disable_scan_offload",
- "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
- "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
- "driver_param", "dot11RSNAConfigPMKLifetime",
+#ifdef CONFIG_CTRL_IFACE
+ "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
+#endif /* CONFIG_CTRL_IFACE */
+ "eapol_version", "ap_scan", "bgscan",
+#ifdef CONFIG_MESH
+ "user_mpm", "max_peer_links", "mesh_max_inactivity",
+ "dot11RSNASAERetransPeriod",
+#endif /* CONFIG_MESH */
+ "disable_scan_offload", "fast_reauth", "opensc_engine_path",
+ "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
+ "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
+ "dot11RSNAConfigPMKLifetime",
"dot11RSNAConfigPMKReauthThreshold",
"dot11RSNAConfigSATimeout",
- "update_config", "load_dynamic_eap", "uuid", "device_name",
- "manufacturer", "model_name", "model_number", "serial_number",
- "device_type", "os_version", "config_methods",
- "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
+#ifndef CONFIG_NO_CONFIG_WRITE
+ "update_config",
+#endif /* CONFIG_NO_CONFIG_WRITE */
+ "load_dynamic_eap",
+#ifdef CONFIG_WPS
+ "uuid", "device_name", "manufacturer", "model_name",
+ "model_number", "serial_number", "device_type", "os_version",
+ "config_methods", "wps_cred_processing", "wps_vendor_ext_m1",
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+ "sec_device_type",
"p2p_listen_reg_class", "p2p_listen_channel",
- "p2p_oper_reg_class", "p2p_oper_channel",
- "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
- "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
- "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
- "p2p_ignore_shared_freq", "country", "bss_max_count",
- "bss_expiration_age", "bss_expiration_scan_count",
- "filter_ssids", "filter_rssi", "max_num_sta",
- "disassoc_low_ack", "hs20", "interworking", "hessid",
- "access_network_type", "pbc_in_m1", "autoscan",
- "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
- "wps_nfc_dev_pw", "ext_password_backend",
+ "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
+ "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
+ "p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan",
+ "p2p_no_go_freq", "p2p_add_cli_chan",
+ "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
+ "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
+ "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
+ "ip_addr_start", "ip_addr_end",
+#endif /* CONFIG_P2P */
+ "country", "bss_max_count", "bss_expiration_age",
+ "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
+ "max_num_sta", "disassoc_low_ack",
+#ifdef CONFIG_HS20
+ "hs20",
+#endif /* CONFIG_HS20 */
+ "interworking", "hessid", "access_network_type", "pbc_in_m1",
+ "autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey",
+ "wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
- "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
- "ignore_old_scan_res", "freq_list"
+ "sae_groups", "dtim_period", "beacon_int",
+ "ap_vendor_elements", "ignore_old_scan_res", "freq_list",
+ "scan_cur_freq", "sched_scan_interval",
+ "tdls_external_control", "osu_dir", "wowlan_triggers",
+ "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
+ "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
+ "reassoc_same_bss_optim", "wps_priority"
};
- int i, num_fields = sizeof(fields) / sizeof(fields[0]);
+ int i, num_fields = ARRAY_SIZE(fields);
if (arg == 1) {
char **res = os_calloc(num_fields + 1, sizeof(char *));
return NULL;
}
+static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DUMP");
+}
+
+
+static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
}
+static char ** wpa_cli_complete_get(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+#ifdef CONFIG_CTRL_IFACE
+ "ctrl_interface", "ctrl_interface_group",
+#endif /* CONFIG_CTRL_IFACE */
+ "eapol_version", "ap_scan",
+#ifdef CONFIG_MESH
+ "user_mpm", "max_peer_links", "mesh_max_inactivity",
+#endif /* CONFIG_MESH */
+ "disable_scan_offload", "fast_reauth", "opensc_engine_path",
+ "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
+ "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
+ "dot11RSNAConfigPMKLifetime",
+ "dot11RSNAConfigPMKReauthThreshold",
+ "dot11RSNAConfigSATimeout",
+#ifndef CONFIG_NO_CONFIG_WRITE
+ "update_config",
+#endif /* CONFIG_NO_CONFIG_WRITE */
+#ifdef CONFIG_WPS
+ "device_name", "manufacturer", "model_name", "model_number",
+ "serial_number", "config_methods", "wps_cred_processing",
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+ "p2p_listen_reg_class", "p2p_listen_channel",
+ "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
+ "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
+ "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
+ "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
+ "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
+ "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
+ "ip_addr_start", "ip_addr_end",
+#endif /* CONFIG_P2P */
+ "bss_max_count", "bss_expiration_age",
+ "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
+ "max_num_sta", "disassoc_low_ack",
+#ifdef CONFIG_HS20
+ "hs20",
+#endif /* CONFIG_HS20 */
+ "interworking", "access_network_type", "pbc_in_m1", "autoscan",
+ "wps_nfc_dev_pw_id", "ext_password_backend",
+ "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
+ "dtim_period", "beacon_int", "ignore_old_scan_res",
+ "scan_cur_freq", "sched_scan_interval",
+ "tdls_external_control", "osu_dir", "wowlan_triggers",
+ "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
+ "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
+ "reassoc_same_bss_optim"
+ };
+ int i, num_fields = ARRAY_SIZE(fields);
+
+ if (arg == 1) {
+ char **res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(fields[i]);
+ if (res[i] == NULL)
+ return res;
+ }
+ return res;
+ }
+
+ return NULL;
+}
+
+
static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "LOGOFF");
}
+static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "REATTACH");
+}
+
+
static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
else
res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long BSS_FLUSH command.\n");
return -1;
}
}
-static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
-{
- int ret;
- char *buf;
- size_t buflen;
-
- if (argc != 1) {
- printf("Invalid 'nfc_rx_handover_req' command - one argument "
- "is required.\n");
- return -1;
- }
-
- buflen = 21 + os_strlen(argv[0]);
- buf = os_malloc(buflen);
- if (buf == NULL)
- return -1;
- os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
-
- ret = wpa_ctrl_command(ctrl, buf);
- os_free(buf);
-
- return ret;
-}
-
-
-static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
-{
- int ret;
- char *buf;
- size_t buflen;
-
- if (argc != 1) {
- printf("Invalid 'nfc_rx_handover_sel' command - one argument "
- "is required.\n");
- return -1;
- }
-
- buflen = 21 + os_strlen(argv[0]);
- buf = os_malloc(buflen);
- if (buf == NULL)
- return -1;
- os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
-
- ret = wpa_ctrl_command(ctrl, buf);
- os_free(buf);
-
- return ret;
-}
-
-
static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
argv[0], argv[1]);
else if (argc == 5 || argc == 6) {
- char ssid_hex[2 * 32 + 1];
+ char ssid_hex[2 * SSID_MAX_LEN + 1];
char key_hex[2 * 64 + 1];
int i;
ssid_hex[0] = '\0';
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < SSID_MAX_LEN; i++) {
if (argv[2][i] == '\0')
break;
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
return -1;
}
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long WPS_REG command.\n");
return -1;
}
int res;
if (argc == 5 || argc == 6) {
- char ssid_hex[2 * 32 + 1];
+ char ssid_hex[2 * SSID_MAX_LEN + 1];
char key_hex[2 * 64 + 1];
int i;
ssid_hex[0] = '\0';
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < SSID_MAX_LEN; i++) {
if (argv[2][i] == '\0')
break;
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
return -1;
}
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long WPS_ER_CONFIG command.\n");
return -1;
}
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long IDENTITY command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long IDENTITY command.\n");
return -1;
}
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long PASSWORD command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long PASSWORD command.\n");
return -1;
}
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long NEW_PASSWORD command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long NEW_PASSWORD command.\n");
return -1;
}
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long PIN command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long PIN command.\n");
return -1;
}
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long OTP command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long OTP command.\n");
return -1;
}
}
+static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ char cmd[256], *pos, *end;
+ int i, ret;
+
+ if (argc < 2) {
+ printf("Invalid SIM command: needs two arguments "
+ "(network id and SIM operation response)\n");
+ return -1;
+ }
+
+ end = cmd + sizeof(cmd);
+ pos = cmd;
+ ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
+ argv[0], argv[1]);
+ if (os_snprintf_error(end - pos, ret)) {
+ printf("Too long SIM command.\n");
+ return -1;
+ }
+ pos += ret;
+ for (i = 2; i < argc; i++) {
+ ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+ if (os_snprintf_error(end - pos, ret)) {
+ printf("Too long SIM command.\n");
+ return -1;
+ }
+ pos += ret;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long PASSPHRASE command.\n");
return -1;
}
pos += ret;
for (i = 2; i < argc; i++) {
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long PASSPHRASE command.\n");
return -1;
}
static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_ctrl_command(ctrl, "ADD_NETWORK");
+ int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
+ if (interactive)
+ update_networks(ctrl);
+ return res;
}
static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
+ int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
+ if (interactive)
+ update_networks(ctrl);
+ return res;
}
}
+static const char *network_fields[] = {
+ "ssid", "scan_ssid", "bssid", "bssid_blacklist",
+ "bssid_whitelist", "psk", "proto", "key_mgmt",
+ "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
+ "freq_list", "max_oper_chwidth",
+#ifdef IEEE8021X_EAPOL
+ "eap", "identity", "anonymous_identity", "password", "ca_cert",
+ "ca_path", "client_cert", "private_key", "private_key_passwd",
+ "dh_file", "subject_match", "altsubject_match",
+ "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
+ "client_cert2", "private_key2", "private_key2_passwd",
+ "dh_file2", "subject_match2", "altsubject_match2",
+ "domain_suffix_match2", "domain_match2", "phase1", "phase2",
+ "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
+ "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
+ "engine", "engine2", "eapol_flags", "sim_num",
+ "openssl_ciphers", "erp",
+#endif /* IEEE8021X_EAPOL */
+ "wep_key0", "wep_key1", "wep_key2", "wep_key3",
+ "wep_tx_keyidx", "priority",
+#ifdef IEEE8021X_EAPOL
+ "eap_workaround", "pac_file", "fragment_size", "ocsp",
+#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_MESH
+ "mode", "no_auto_peer",
+#else /* CONFIG_MESH */
+ "mode",
+#endif /* CONFIG_MESH */
+ "proactive_key_caching", "disabled", "id_str",
+#ifdef CONFIG_IEEE80211W
+ "ieee80211w",
+#endif /* CONFIG_IEEE80211W */
+ "peerkey", "mixed_cell", "frequency", "fixed_freq",
+#ifdef CONFIG_MESH
+ "mesh_basic_rates", "dot11MeshMaxRetries",
+ "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
+ "dot11MeshHoldingTimeout",
+#endif /* CONFIG_MESH */
+ "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
+#ifdef CONFIG_P2P
+ "go_p2p_dev_addr", "p2p_client_list", "psk_list",
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_HT_OVERRIDES
+ "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
+ "ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
+ "ampdu_density", "ht_mcs",
+#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
+ "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
+ "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
+ "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
+ "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
+ "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
+#endif /* CONFIG_VHT_OVERRIDES */
+ "ap_max_inactivity", "dtim_period", "beacon_int",
+#ifdef CONFIG_MACSEC
+ "macsec_policy",
+#endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+ "update_identifier",
+#endif /* CONFIG_HS20 */
+ "mac_addr", "pbss", "wps_disabled"
+};
+
+
+static char ** wpa_cli_complete_network(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(network_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&networks);
+ break;
+ case 2:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(network_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
+}
+
+
+static char ** wpa_cli_complete_network_id(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ if (arg == 1)
+ return cli_txt_list_array(&networks);
+ return NULL;
+}
+
+
+static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ if (argc == 0) {
+ wpa_cli_show_network_variables();
+ return 0;
+ }
+
+ if (argc < 3) {
+ printf("Invalid DUP_NETWORK command: needs three arguments\n"
+ "(src netid, dest netid, and variable name)\n");
+ return -1;
+ }
+
+ return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
+}
+
+
+static char ** wpa_cli_complete_dup_network(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(network_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ case 2:
+ res = cli_txt_list_array(&networks);
+ break;
+ case 3:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(network_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
+}
+
+
static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
}
+static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ if (argc != 2) {
+ printf("Invalid GET_CRED command: needs two arguments\n"
+ "(cred id, variable name)\n");
+ return -1;
+ }
+
+ return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
+}
+
+
static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
}
+static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "ABORT_SCAN");
+}
+
+
static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
wpa_cli_close_connection();
os_free(ctrl_ifname);
ctrl_ifname = os_strdup(argv[0]);
+ if (!ctrl_ifname) {
+ printf("Failed to allocate memory\n");
+ return 0;
+ }
- if (wpa_cli_open_connection(ctrl_ifname, 1)) {
+ if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
printf("Connected to interface '%s.\n", ctrl_ifname);
} else {
printf("Could not connect to interface '%s' - re-trying\n",
printf("Invalid INTERFACE_ADD command: needs at least one "
"argument (interface name)\n"
"All arguments: ifname confname driver ctrl_interface "
- "driver_param bridge_name\n");
+ "driver_param bridge_name [create]\n");
return -1;
}
/*
* INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
- * <driver_param>TAB<bridge_name>
+ * <driver_param>TAB<bridge_name>[TAB<create>[TAB<type>]]
*/
res = os_snprintf(cmd, sizeof(cmd),
- "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
+ "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
argv[0],
argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
- argc > 5 ? argv[5] : "");
- if (res < 0 || (size_t) res >= sizeof(cmd))
+ argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "",
+ argc > 7 ? argv[7] : "");
+ if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
printf("Not connected to hostapd - command dropped.\n");
return -1;
}
+ if (ifname_prefix) {
+ os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
+ ifname_prefix, cmd);
+ buf[sizeof(buf) - 1] = '\0';
+ cmd = buf;
+ }
len = sizeof(buf) - 1;
ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
wpa_cli_msg_cb);
{
return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
}
+
+static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
+}
+
#endif /* CONFIG_AP */
}
+#ifdef CONFIG_TESTING_OPTIONS
static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "DROP_SA");
}
+#endif /* CONFIG_TESTING_OPTIONS */
static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+#ifdef CONFIG_MESH
+
+static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
+}
+
+#endif /* CONFIG_MESH */
+
+
#ifdef CONFIG_P2P
static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
-static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
+static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
{
- return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
+ return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
}
-static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
+static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
{
- int arg = get_cmd_arg_num(str, pos);
- char **res = NULL;
+ return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
+}
+
+
+static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
switch (arg) {
case 1:
}
+static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
{
char cmd[4096];
- if (argc != 2 && argc != 4) {
+ if (argc < 2) {
printf("Invalid P2P_SERV_DISC_REQ command: needs two "
- "arguments (address and TLVs) or four arguments "
- "(address, \"upnp\", version, search target "
- "(SSDP ST:)\n");
+ "or more arguments (address 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))
+ if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- char cmd[4096];
- int res;
+ if (argc < 3) {
+ printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
+ return -1;
+ }
+
+ return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
+}
- if (argc != 3 && argc != 4) {
- printf("Invalid P2P_SERVICE_ADD command: needs three or four "
+
+static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ if (argc < 5 || argc > 6) {
+ printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
"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);
+ return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
}
res = os_snprintf(cmd, sizeof(cmd),
"P2P_SERVICE_DEL %s %s",
argv[0], argv[1]);
- if (res < 0 || (size_t) res >= sizeof(cmd))
+ if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
}
+static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ "discoverability",
+ "managed",
+ "listen_channel",
+ "ssid_postfix",
+ "noa",
+ "ps",
+ "oppps",
+ "ctwindow",
+ "disabled",
+ "conc_pref",
+ "force_long_sd",
+ "peer_filter",
+ "cross_connect",
+ "go_apsd",
+ "client_apsd",
+ "disallow_freq",
+ "disc_int",
+ "per_sta_psk",
+ };
+ int i, num_fields = ARRAY_SIZE(fields);
+
+ if (arg == 1) {
+ char **res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(fields[i]);
+ if (res[i] == NULL)
+ return res;
+ }
+ return res;
+ }
+
+ if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
+ return cli_txt_list_array(&p2p_peers);
+
+ return NULL;
+}
+
+
static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "P2P_FLUSH");
return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
}
+
+static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
+}
+
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
argv[0], argc > 1 ? argv[1] : "");
- if (res < 0 || (size_t) res >= sizeof(cmd))
+ if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd))
+ if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
}
+static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
return wpa_ctrl_command(ctrl, cmd);
}
+
+static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[512];
+
+ if (argc < 2) {
+ printf("Command needs two arguments (dst mac addr and "
+ "icon name)\n");
+ return -1;
+ }
+
+ if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
+ return -1;
+
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "FETCH_OSU");
+}
+
+
+static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
+}
+
#endif /* CONFIG_HS20 */
}
+static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
+}
+
+
+static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
}
+static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv);
+}
+
+
static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
}
+#ifdef ANDROID
+static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
+}
+#endif /* ANDROID */
+
+
+static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "FLUSH");
}
+static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "ERP_FLUSH");
+}
+
+
+static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv);
+}
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
const char *usage;
};
-static struct wpa_cli_cmd wpa_cli_commands[] = {
+static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "status", wpa_cli_cmd_status, NULL,
cli_cmd_flag_none,
"[verbose] = get current WPA/EAPOL/EAP status" },
cli_cmd_flag_none,
"= set variables (shows list of variables when run without "
"arguments)" },
- { "get", wpa_cli_cmd_get, NULL,
+ { "dump", wpa_cli_cmd_dump, NULL,
+ cli_cmd_flag_none,
+ "= dump config variables" },
+ { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
cli_cmd_flag_none,
"<name> = get information" },
+ { "driver_flags", wpa_cli_cmd_driver_flags, NULL,
+ cli_cmd_flag_none,
+ "= list driver flags" },
{ "logon", wpa_cli_cmd_logon, NULL,
cli_cmd_flag_none,
"= IEEE 802.1X EAPOL state machine logon" },
{ "pmksa", wpa_cli_cmd_pmksa, NULL,
cli_cmd_flag_none,
"= show PMKSA cache" },
+ { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
+ cli_cmd_flag_none,
+ "= flush PMKSA cache entries" },
{ "reassociate", wpa_cli_cmd_reassociate, NULL,
cli_cmd_flag_none,
"= force reassociation" },
+ { "reattach", wpa_cli_cmd_reattach, NULL,
+ cli_cmd_flag_none,
+ "= force reassociation back to the same BSS" },
{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<BSSID> = force preauthentication" },
cli_cmd_flag_sensitive,
"<network id> <passphrase> = configure private key passphrase\n"
" for an SSID" },
+ { "sim", wpa_cli_cmd_sim, NULL,
+ cli_cmd_flag_sensitive,
+ "<network id> <pin> = report SIM operation result" },
{ "bssid", wpa_cli_cmd_bssid, NULL,
cli_cmd_flag_none,
"<network id> <BSSID> = set preferred BSSID for an SSID" },
{ "list_networks", wpa_cli_cmd_list_networks, NULL,
cli_cmd_flag_none,
"= list configured networks" },
- { "select_network", wpa_cli_cmd_select_network, NULL,
+ { "select_network", wpa_cli_cmd_select_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = select a network (disable others)" },
- { "enable_network", wpa_cli_cmd_enable_network, NULL,
+ { "enable_network", wpa_cli_cmd_enable_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = enable a network" },
- { "disable_network", wpa_cli_cmd_disable_network, NULL,
+ { "disable_network", wpa_cli_cmd_disable_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = disable a network" },
{ "add_network", wpa_cli_cmd_add_network, NULL,
cli_cmd_flag_none,
"= add a network" },
- { "remove_network", wpa_cli_cmd_remove_network, NULL,
+ { "remove_network", wpa_cli_cmd_remove_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = remove a network" },
- { "set_network", wpa_cli_cmd_set_network, NULL,
+ { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
cli_cmd_flag_sensitive,
"<network id> <variable> <value> = set network variables (shows\n"
" list of variables when run without arguments)" },
- { "get_network", wpa_cli_cmd_get_network, NULL,
+ { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
cli_cmd_flag_none,
"<network id> <variable> = get network variables" },
+ { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
+ cli_cmd_flag_none,
+ "<src network id> <dst network id> <variable> = duplicate network variables"
+ },
{ "list_creds", wpa_cli_cmd_list_creds, NULL,
cli_cmd_flag_none,
"= list configured credentials" },
{ "set_cred", wpa_cli_cmd_set_cred, NULL,
cli_cmd_flag_sensitive,
"<cred id> <variable> <value> = set credential variables" },
+ { "get_cred", wpa_cli_cmd_get_cred, NULL,
+ cli_cmd_flag_none,
+ "<cred id> <variable> = get credential variables" },
{ "save_config", wpa_cli_cmd_save_config, NULL,
cli_cmd_flag_none,
"= save the current configuration" },
{ "scan_results", wpa_cli_cmd_scan_results, NULL,
cli_cmd_flag_none,
"= get latest scan results" },
+ { "abort_scan", wpa_cli_cmd_abort_scan, NULL,
+ cli_cmd_flag_none,
+ "= request ongoing scan to be aborted" },
{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<<idx> | <bssid>> = get detailed scan result info" },
{ "get_capability", wpa_cli_cmd_get_capability, NULL,
cli_cmd_flag_none,
"<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
- "= get capabilies" },
+ "= get capabilities" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
cli_cmd_flag_none,
"= force wpa_supplicant to re-read its configuration file" },
{ "interface_add", wpa_cli_cmd_interface_add, NULL,
cli_cmd_flag_none,
"<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
- " <bridge_name> = adds new interface, all parameters but <ifname>\n"
- " are optional" },
+ " <bridge_name> <create> <type> = adds new interface, all "
+ "parameters but\n"
+ " <ifname> are optional. Supported types are station ('sta') and "
+ "AP ('ap')" },
{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
cli_cmd_flag_none,
"<ifname> = removes the interface" },
{ "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
cli_cmd_flag_none,
"<NDEF> <WPS> = create NFC handover select" },
- { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
- cli_cmd_flag_none,
- "<hexdump of payload> = report received NFC handover request" },
- { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
- cli_cmd_flag_none,
- "<hexdump of payload> = report received NFC handover select" },
{ "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
cli_cmd_flag_none,
"<role> <type> <hexdump of req> <hexdump of sel> = report completed "
{ "disassociate", wpa_cli_cmd_disassociate, NULL,
cli_cmd_flag_none,
"<addr> = disassociate a station" },
+ { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
+ cli_cmd_flag_none,
+ "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
+ " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
+ " = CSA parameters" },
#endif /* CONFIG_AP */
{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
"= notification of suspend/hibernate" },
{ "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
"= notification of resume/thaw" },
+#ifdef CONFIG_TESTING_OPTIONS
{ "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
"= drop SA without deauth/disassoc (test command)" },
+#endif /* CONFIG_TESTING_OPTIONS */
{ "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<addr> = roam to the specified BSS" },
+#ifdef CONFIG_MESH
+ { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
+ cli_cmd_flag_none,
+ "[ifname] = Create a new mesh interface" },
+ { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
+ cli_cmd_flag_none,
+ "<network id> = join a mesh network (disable others)" },
+ { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
+ cli_cmd_flag_none,
+ "<ifname> = Remove mesh group interface" },
+ { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
+ cli_cmd_flag_none,
+ "<addr> = Remove a mesh peer" },
+ { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
+ cli_cmd_flag_none,
+ "<addr> [duration=<seconds>] = Add a mesh peer" },
+#endif /* CONFIG_MESH */
#ifdef CONFIG_P2P
{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_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, NULL, cli_cmd_flag_none,
"= stop P2P Devices search" },
+ { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
+ cli_cmd_flag_none,
+ "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
+ { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
+ cli_cmd_flag_none,
+ "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
{ "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
cli_cmd_flag_none,
"<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
"<ifname> = remove P2P group interface (terminate group if GO)" },
{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
"[ht40] = add a new P2P group (local end as GO)" },
+ { "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL,
+ cli_cmd_flag_none,
+ "<dev_addr> = Get peer interface address on local GO using peer Device Address" },
{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
"<addr> <method> = request provisioning discovery" },
"= remove all stored service entries" },
{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
cli_cmd_flag_none,
- "<bonjour|upnp> <query|version> <response|service> = add a local "
+ "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
"service" },
+ { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
+ cli_cmd_flag_none,
+ "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
+ "local ASP service" },
{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
cli_cmd_flag_none,
"<bonjour|upnp> <query|version> [|service] = remove a local "
{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
cli_cmd_flag_none,
"<address> = show information about known P2P peer" },
- { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
+ { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
+ cli_cmd_flag_none,
"<field> <value> = set a P2P parameter" },
{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
"= flush P2P state" },
{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
cli_cmd_flag_none,
"[<period> <interval>] = set extended listen timing" },
+ { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
+ wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
+ "<address|iface=address> = remove a peer from all groups" },
+ { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
+ cli_cmd_flag_none,
+ "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
+ VENDOR_ELEM_FRAME_ID },
+ { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
+ cli_cmd_flag_none,
+ "<frame id> = get vendor specific IE(s) to frame(s)\n"
+ VENDOR_ELEM_FRAME_ID },
+ { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
+ cli_cmd_flag_none,
+ "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
+ VENDOR_ELEM_FRAME_ID },
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
{ "interworking_connect", wpa_cli_cmd_interworking_connect,
wpa_cli_complete_bss, cli_cmd_flag_none,
"<BSSID> = connect using Interworking credentials" },
+ { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
+ wpa_cli_complete_bss, cli_cmd_flag_none,
+ "<BSSID> = connect using Interworking credentials" },
{ "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<addr> <info id>[,<info id>]... = request ANQP information" },
{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
wpa_cli_complete_bss, cli_cmd_flag_none,
"<addr> <home realm> = get HS20 nai home realm list" },
+ { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
+ wpa_cli_complete_bss, cli_cmd_flag_none,
+ "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
+ { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
+ "= fetch OSU provider information from all APs" },
+ { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
+ cli_cmd_flag_none,
+ "= cancel fetch_osu command" },
#endif /* CONFIG_HS20 */
{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
cli_cmd_flag_none,
{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
cli_cmd_flag_none,
"<addr> = tear down TDLS with <addr>" },
+ { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
+ cli_cmd_flag_none,
+ "<addr> = TDLS link status with <addr>" },
+ { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
+ cli_cmd_flag_none,
+ "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
+ "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
+ "= add WMM-AC traffic stream" },
+ { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
+ cli_cmd_flag_none,
+ "<tsid> = delete WMM-AC traffic stream" },
+ { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
+ cli_cmd_flag_none,
+ "= show status for Wireless Multi-Media Admission-Control" },
+ { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
+ cli_cmd_flag_none,
+ "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
+ "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
+ "with TDLS peer" },
+ { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
+ cli_cmd_flag_none,
+ "<addr> = disable channel switching with TDLS peer <addr>" },
{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
cli_cmd_flag_none,
"= get signal parameters" },
+ { "signal_monitor", wpa_cli_cmd_signal_monitor, NULL,
+ cli_cmd_flag_none,
+ "= set signal monitor parameters" },
{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
cli_cmd_flag_none,
"= get TX/RX packet counters" },
{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
"<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
- "<query reason> = Send BSS Transition Management Query" },
+ "<query reason> [list] = Send BSS Transition Management Query" },
#endif /* CONFIG_WNM */
{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
"<params..> = Sent unprocessed command" },
{ "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
"= flush wpa_supplicant state" },
+#ifdef ANDROID
+ { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
+ "<command> = driver private commands" },
+#endif /* ANDROID */
+ { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
+ "= radio_work <show/add/done>" },
+ { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
+ "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
+ },
+ { "neighbor_rep_request",
+ wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
+ "[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)"
+ },
+ { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
+ "= flush ERP keys" },
+ { "mac_rand_scan",
+ wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
+ "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
+ "mask=mac-address-mask] = scan MAC randomization"
+ },
+ { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
+ cli_cmd_flag_none,
+ "<interface type> = retrieve preferred freq list for the specified interface type" },
+ { "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL,
+ cli_cmd_flag_none,
+ "<freq> <period> <interval> <count> = start P2P listen offload" },
+ { "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
+ cli_cmd_flag_none,
+ "= stop P2P listen offload" },
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
/*
* Prints command usage, lines are padded with the specified string.
*/
-static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
+static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
{
char c;
size_t n;
{
char **res;
int i, count;
+ struct cli_txt_entry *e;
- count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
- res = os_calloc(count, sizeof(char *));
+ count = ARRAY_SIZE(wpa_cli_commands);
+ count += dl_list_len(&p2p_groups);
+ count += dl_list_len(&ifnames);
+ res = os_calloc(count + 1, sizeof(char *));
if (res == NULL)
return NULL;
break;
}
+ dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
+ size_t len = 8 + os_strlen(e->txt);
+ res[i] = os_malloc(len);
+ if (res[i] == NULL)
+ break;
+ os_snprintf(res[i], len, "ifname=%s", e->txt);
+ i++;
+ }
+
+ dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
+ res[i] = os_strdup(e->txt);
+ if (res[i] == NULL)
+ break;
+ i++;
+ }
+
return res;
}
const char *end;
char *cmd;
+ if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
+ end = os_strchr(str, ' ');
+ if (end && pos > end - str) {
+ pos -= end - str + 1;
+ str = end + 1;
+ }
+ }
+
end = os_strchr(str, ' ');
if (end == NULL || str + pos < end)
return wpa_list_cmd_list();
static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- struct wpa_cli_cmd *cmd, *match = NULL;
+ const struct wpa_cli_cmd *cmd, *match = NULL;
int count;
int ret = 0;
+ if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
+ ifname_prefix = argv[0] + 7;
+ argv = &argv[1];
+ argc--;
+ } else
+ ifname_prefix = NULL;
+
+ if (argc == 0)
+ return -1;
+
count = 0;
cmd = wpa_cli_commands;
while (cmd->cmd) {
static int wpa_cli_exec(const char *program, const char *arg1,
const char *arg2)
{
- char *cmd;
+ char *arg;
size_t len;
int res;
- int ret = 0;
- len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
- cmd = os_malloc(len);
- if (cmd == NULL)
- return -1;
- res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
- if (res < 0 || (size_t) res >= len) {
- os_free(cmd);
+ /* If no interface is specified, set the global */
+ if (!arg1)
+ arg1 = "global";
+
+ len = os_strlen(arg1) + os_strlen(arg2) + 2;
+ arg = os_malloc(len);
+ if (arg == NULL)
return -1;
- }
- cmd[len - 1] = '\0';
-#ifndef _WIN32_WCE
- if (system(cmd) < 0)
- ret = -1;
-#endif /* _WIN32_WCE */
- os_free(cmd);
+ os_snprintf(arg, len, "%s %s", arg1, arg2);
+ res = os_exec(program, arg, 1);
+ os_free(arg);
- return ret;
+ return res;
}
{
const char *pos;
char *copy = NULL, *id, *pos2;
+ const char *ifname = ctrl_ifname;
+ char ifname_buf[100];
+
+ if (eloop_terminated())
+ return;
pos = msg;
+ if (os_strncmp(pos, "IFNAME=", 7) == 0) {
+ const char *end;
+ end = os_strchr(pos + 7, ' ');
+ if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
+ pos += 7;
+ os_memcpy(ifname_buf, pos, end - pos);
+ ifname_buf[end - pos] = '\0';
+ ifname = ifname_buf;
+ pos = end + 1;
+ }
+ }
if (*pos == '<') {
+ const char *prev = pos;
/* skip priority */
pos = os_strchr(pos, '>');
if (pos)
pos++;
else
- pos = msg;
+ pos = prev;
}
if (str_match(pos, WPA_EVENT_CONNECTED)) {
os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
- if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
+ if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
wpa_cli_connected = 1;
wpa_cli_last_id = new_id;
- wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
+ wpa_cli_exec(action_file, ifname, "CONNECTED");
}
} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
if (wpa_cli_connected) {
wpa_cli_connected = 0;
- wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
+ wpa_cli_exec(action_file, ifname, "DISCONNECTED");
}
- } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+ } else if (str_match(pos, AP_EVENT_ENABLED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+ } else if (str_match(pos, AP_EVENT_DISABLED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+ } else if (str_match(pos, MESH_GROUP_STARTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+ } else if (str_match(pos, MESH_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
+ } else if (str_match(pos, MESH_PEER_CONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
+ } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_match(pos, WPS_EVENT_FAIL)) {
- wpa_cli_exec(action_file, ctrl_ifname, pos);
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_match(pos, AP_STA_CONNECTED)) {
- wpa_cli_exec(action_file, ctrl_ifname, pos);
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_match(pos, AP_STA_DISCONNECTED)) {
- wpa_cli_exec(action_file, ctrl_ifname, pos);
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
+ wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
wpa_cli_quit = 1;
s = os_strchr(start, ' ');
if (s == NULL)
return;
- cli_txt_list_add_word(&p2p_groups, s + 1);
+ cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
return;
}
s = os_strchr(start, ' ');
if (s == NULL)
return;
- cli_txt_list_del_word(&p2p_groups, s + 1);
+ cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
return;
}
#endif /* CONFIG_P2P */
return;
}
while (wpa_ctrl_pending(ctrl) > 0) {
- char buf[256];
+ char buf[4096];
size_t len = sizeof(buf) - 1;
if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
buf[len] = '\0';
static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
{
- if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
- printf("Connection to wpa_supplicant lost - trying to "
- "reconnect\n");
- wpa_cli_close_connection();
+ if (ctrl_conn) {
+ int res;
+ char *prefix = ifname_prefix;
+
+ ifname_prefix = NULL;
+ res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
+ ifname_prefix = prefix;
+ if (res) {
+ printf("Connection to wpa_supplicant lost - trying to "
+ "reconnect\n");
+ wpa_cli_close_connection();
+ }
}
if (!ctrl_conn)
wpa_cli_reconnect();
ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+#ifdef CONFIG_WPA_CLI_HISTORY_DIR
+ home = CONFIG_WPA_CLI_HISTORY_DIR;
+#else /* CONFIG_WPA_CLI_HISTORY_DIR */
home = getenv("HOME");
+#endif /* CONFIG_WPA_CLI_HISTORY_DIR */
if (home) {
const char *fname = ".wpa_cli_history";
int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
}
+static void update_ifnames(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "INTERFACES";
+ char *pos, *end;
+ char txt[200];
+
+ cli_txt_list_flush(&ifnames);
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
+ if (!os_snprintf_error(sizeof(txt), ret))
+ cli_txt_list_add(&ifnames, txt);
+ pos = end + 1;
+ }
+}
+
+
+static void update_networks(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "LIST_NETWORKS";
+ char *pos, *end;
+ int header = 1;
+
+ cli_txt_list_flush(&networks);
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ if (!header)
+ cli_txt_list_add_word(&networks, pos, '\t');
+ header = 0;
+ pos = end + 1;
+ }
+}
+
+
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_conn)
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
- if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
+ if (wpa_cli_open_connection(ctrl_ifname, 1)) {
if (!warning_displayed) {
printf("Could not connect to wpa_supplicant: "
- "%s - re-trying\n", ctrl_ifname);
+ "%s - re-trying\n",
+ ctrl_ifname ? ctrl_ifname : "(nil)");
warning_displayed = 1;
}
eloop_register_timeout(1, 0, try_connection, NULL, NULL);
}
update_bssid_list(ctrl_conn);
+ update_networks(ctrl_conn);
if (warning_displayed)
printf("Connection established.\n");
cli_txt_list_flush(&p2p_peers);
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
+ cli_txt_list_flush(&ifnames);
+ cli_txt_list_flush(&networks);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile);
}
+static void wpa_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_ctrl *ctrl = eloop_ctx;
+ char buf[256];
+ size_t len;
+
+ /* verify that connection is still working */
+ len = sizeof(buf) - 1;
+ if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
+ wpa_cli_action_cb) < 0 ||
+ len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
+ printf("wpa_supplicant did not reply to PING command - exiting\n");
+ eloop_terminate();
+ return;
+ }
+ eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
+ ctrl, NULL);
+}
+
+
+static void wpa_cli_action_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct wpa_ctrl *ctrl = eloop_ctx;
+
+ wpa_cli_recv_pending(ctrl, 1);
+}
+
+
static void wpa_cli_action(struct wpa_ctrl *ctrl)
{
#ifdef CONFIG_ANSI_C_EXTRA
/* TODO: ANSI C version(?) */
printf("Action processing not supported in ANSI C build.\n");
#else /* CONFIG_ANSI_C_EXTRA */
- fd_set rfds;
- int fd, res;
- struct timeval tv;
- char buf[256]; /* note: large enough to fit in unsolicited messages */
- size_t len;
+ int fd;
fd = wpa_ctrl_get_fd(ctrl);
-
- while (!wpa_cli_quit) {
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- tv.tv_sec = ping_interval;
- tv.tv_usec = 0;
- res = select(fd + 1, &rfds, NULL, NULL, &tv);
- if (res < 0 && errno != EINTR) {
- perror("select");
- break;
- }
-
- if (FD_ISSET(fd, &rfds))
- wpa_cli_recv_pending(ctrl, 1);
- else {
- /* verify that connection is still working */
- len = sizeof(buf) - 1;
- if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
- wpa_cli_action_cb) < 0 ||
- len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
- printf("wpa_supplicant did not reply to PING "
- "command - exiting\n");
- break;
- }
- }
- }
+ eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
+ ctrl, NULL);
+ eloop_register_read_sock(fd, wpa_cli_action_receive, ctrl, NULL);
+ eloop_run();
+ eloop_cancel_timeout(wpa_cli_action_ping, ctrl, NULL);
+ eloop_unregister_read_sock(fd);
#endif /* CONFIG_ANSI_C_EXTRA */
}
{
char *ifname = NULL;
+#ifdef ANDROID
+ char ifprop[PROPERTY_VALUE_MAX];
+ if (property_get("wifi.interface", ifprop, NULL) != 0) {
+ ifname = os_strdup(ifprop);
+ printf("Using interface '%s'\n", ifname ? ifname : "N/A");
+ }
+#else /* ANDROID */
#ifdef CONFIG_CTRL_IFACE_UNIX
struct dirent *dent;
DIR *dir = opendir(ctrl_iface_dir);
if (!dir) {
-#ifdef ANDROID
- char ifprop[PROPERTY_VALUE_MAX];
- if (property_get("wifi.interface", ifprop, NULL) != 0) {
- ifname = os_strdup(ifprop);
- printf("Using interface '%s'\n", ifname);
- return ifname;
- }
-#endif /* ANDROID */
return NULL;
}
while ((dent = readdir(dir))) {
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
- char buf[2048], *pos;
+ char buf[4096], *pos;
size_t len;
struct wpa_ctrl *ctrl;
int ret;
}
wpa_ctrl_close(ctrl);
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+#endif /* ANDROID */
return ifname;
}
return -1;
for (;;) {
- c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
+ c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
if (c < 0)
break;
switch (c) {
case 'P':
pid_file = optarg;
break;
+ case 's':
+ client_socket_dir = optarg;
+ break;
default:
usage();
return -1;
global, strerror(errno));
return -1;
}
+
+ if (interactive) {
+ update_ifnames(ctrl_conn);
+ mon_conn = wpa_ctrl_open(global);
+ if (mon_conn) {
+ if (wpa_ctrl_attach(mon_conn) == 0) {
+ wpa_cli_attached = 1;
+ eloop_register_read_sock(
+ wpa_ctrl_get_fd(mon_conn),
+ wpa_cli_mon_receive,
+ NULL, NULL);
+ } else {
+ printf("Failed to open monitor "
+ "connection through global "
+ "control interface\n");
+ }
+ }
+ }
}
eloop_register_signal_terminate(wpa_cli_terminate, NULL);
wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
fprintf(stderr, "Failed to connect to non-global "
"ctrl_ifname: %s error: %s\n",
- ctrl_ifname, strerror(errno));
+ ctrl_ifname ? ctrl_ifname : "(nil)",
+ strerror(errno));
return -1;
}
}
}
- if (daemonize && os_daemonize(pid_file))
+ if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
return -1;
if (action_file)