aboutsummaryrefslogtreecommitdiff
path: root/wpa_supplicant/wpa_cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'wpa_supplicant/wpa_cli.c')
-rw-r--r--wpa_supplicant/wpa_cli.c944
1 files changed, 755 insertions, 189 deletions
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 0c6ef5e8ad12..5a0af0dc9bba 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -28,7 +28,7 @@
static const char *wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
static const char *wpa_cli_license =
@@ -70,7 +70,7 @@ 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"
@@ -81,6 +81,7 @@ 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;
@@ -90,6 +91,7 @@ struct cli_txt_entry {
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 void print_help(const char *cmd);
@@ -173,11 +175,9 @@ static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
end = os_strchr(txt, ' ');
if (end == NULL)
end = txt + os_strlen(txt);
- buf = os_malloc(end - txt + 1);
+ buf = dup_binstr(txt, end - txt);
if (buf == NULL)
return;
- os_memcpy(buf, txt, end - txt);
- buf[end - txt] = '\0';
cli_txt_list_del(txt_list, buf);
os_free(buf);
}
@@ -223,11 +223,9 @@ static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
end = os_strchr(txt, ' ');
if (end == NULL)
end = txt + os_strlen(txt);
- buf = os_malloc(end - txt + 1);
+ buf = dup_binstr(txt, end - txt);
if (buf == NULL)
return -1;
- os_memcpy(buf, txt, end - txt);
- buf[end - txt] = '\0';
ret = cli_txt_list_add(txt_list, buf);
os_free(buf);
return ret;
@@ -335,7 +333,7 @@ static int wpa_cli_open_connection(const char *ifname, int attach)
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;
}
@@ -400,7 +398,7 @@ static void wpa_cli_msg_cb(char *msg, size_t len)
static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
{
- char buf[2048];
+ char buf[4096];
size_t len;
int ret;
@@ -408,6 +406,12 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
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);
@@ -444,13 +448,13 @@ static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
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;
}
@@ -467,7 +471,7 @@ fail:
static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
int argc, char *argv[])
{
- char buf[256];
+ char buf[4096];
if (argc < min_args) {
printf("Invalid %s command - at least %d argument%s "
"required.\n", cmd, min_args,
@@ -492,6 +496,8 @@ static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
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");
return wpa_ctrl_command(ctrl, "STATUS");
}
@@ -526,6 +532,13 @@ static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+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);
@@ -564,52 +577,90 @@ static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
-static void wpa_cli_show_variables(void)
-{
- printf("set variables:\n"
- " EAPOL::heldPeriod (EAPOL state machine held period, "
- "in seconds)\n"
- " EAPOL::authPeriod (EAPOL state machine authentication "
- "period, in seconds)\n"
- " EAPOL::startPeriod (EAPOL state machine start period, in "
- "seconds)\n"
- " EAPOL::maxStart (EAPOL state machine maximum start "
- "attempts)\n");
- printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
- "seconds)\n"
- " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
- " threshold\n\tpercentage)\n"
- " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
- "security\n\tassociation in seconds)\n");
-}
-
-
static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
int res;
- if (argc == 0) {
- wpa_cli_show_variables();
- return 0;
+ if (argc == 1) {
+ res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long SET command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
}
- if (argc != 1 && argc != 2) {
- printf("Invalid SET command: needs two arguments (variable "
- "name and value)\n");
- return -1;
- }
+ return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
+}
- if (argc == 1)
- res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
- else
- res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
- argv[0], argv[1]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
- printf("Too long SET command.\n");
- return -1;
+
+static char ** wpa_cli_complete_set(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ /* runtime values */
+ "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
+ "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
+ "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
+ "wps_fragment_size", "wps_version_number", "ampdu",
+ "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
+ "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", "openssl_ciphers",
+ "pcsc_reader", "pcsc_pin",
+ "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",
+ "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_no_go_freq",
+ "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
+ "p2p_go_vht",
+ "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_go_max_inactivity", "auto_interworking", "okc", "pmf",
+ "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
+ "ignore_old_scan_res", "freq_list", "external_sim",
+ "tdls_external_control", "p2p_search_delay"
+ };
+ 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 wpa_ctrl_command(ctrl, cmd);
+
+ if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
+ return cli_txt_list_array(&bsses);
+
+ return NULL;
+}
+
+static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DUMP");
}
@@ -638,6 +689,12 @@ static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
}
+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[])
{
@@ -681,7 +738,7 @@ static int wpa_cli_cmd_bss_flush(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;
}
@@ -744,6 +801,13 @@ static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -791,55 +855,10 @@ static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
}
-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,
+static int wpa_cli_cmd_nfc_report_handover(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;
+ return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
}
#endif /* CONFIG_WPS_NFC */
@@ -894,7 +913,7 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
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;
}
@@ -1019,7 +1038,7 @@ static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
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;
}
@@ -1071,14 +1090,14 @@ static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
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;
}
@@ -1104,14 +1123,14 @@ static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
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;
}
@@ -1138,14 +1157,14 @@ static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
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;
}
@@ -1171,14 +1190,14 @@ static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
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;
}
@@ -1203,14 +1222,14 @@ static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
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;
}
@@ -1221,6 +1240,38 @@ static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+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[])
{
@@ -1237,14 +1288,14 @@ static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
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;
}
@@ -1378,6 +1429,24 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
}
+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 int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1410,6 +1479,18 @@ static int wpa_cli_cmd_set_cred(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[])
{
@@ -1433,7 +1514,7 @@ static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- return wpa_ctrl_command(ctrl, "SCAN");
+ return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
}
@@ -1501,8 +1582,12 @@ static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *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",
@@ -1550,7 +1635,7 @@ static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
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))
+ if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
@@ -1640,6 +1725,13 @@ static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
{
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 */
@@ -1655,10 +1747,12 @@ static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+#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[])
@@ -1667,6 +1761,31 @@ 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);
+}
+
+#endif /* CONFIG_MESH */
+
+
#ifdef CONFIG_P2P
static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
@@ -1711,6 +1830,20 @@ static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
}
+static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ 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[])
{
@@ -1795,11 +1928,9 @@ static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
{
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;
}
@@ -1830,7 +1961,7 @@ static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
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);
@@ -1861,27 +1992,25 @@ static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
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);
}
@@ -1905,7 +2034,7 @@ static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
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);
@@ -2008,6 +2137,50 @@ static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+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");
@@ -2058,6 +2231,13 @@ static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
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);
+}
+
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
@@ -2076,7 +2256,7 @@ static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
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);
@@ -2097,7 +2277,7 @@ static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
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);
@@ -2134,6 +2314,13 @@ static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
}
+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);
@@ -2182,6 +2369,37 @@ static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
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 */
@@ -2213,6 +2431,41 @@ static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
}
+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[])
{
@@ -2254,6 +2507,12 @@ static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
}
+
+static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
+}
+
#endif /* CONFIG_WNM */
@@ -2265,6 +2524,52 @@ static int wpa_cli_cmd_raw(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);
+}
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
@@ -2312,10 +2617,13 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "quit", wpa_cli_cmd_quit, NULL,
cli_cmd_flag_none,
"= exit wpa_cli" },
- { "set", wpa_cli_cmd_set, NULL,
+ { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
cli_cmd_flag_none,
"= set variables (shows list of variables when run without "
"arguments)" },
+ { "dump", wpa_cli_cmd_dump, NULL,
+ cli_cmd_flag_none,
+ "= dump config variables" },
{ "get", wpa_cli_cmd_get, NULL,
cli_cmd_flag_none,
"<name> = get information" },
@@ -2328,9 +2636,15 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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" },
@@ -2354,6 +2668,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
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" },
@@ -2391,6 +2708,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "get_network", wpa_cli_cmd_get_network, NULL,
cli_cmd_flag_none,
"<network id> <variable> = get network variables" },
+ { "dup_network", wpa_cli_cmd_dup_network, NULL,
+ 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" },
@@ -2403,6 +2724,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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" },
@@ -2425,7 +2749,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
"<<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> "
+ "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
"= get capabilies" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
cli_cmd_flag_none,
@@ -2481,6 +2805,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
cli_cmd_flag_none,
"[BSSID] = start Wi-Fi Protected Setup: NFC" },
+ { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
+ cli_cmd_flag_none,
+ "<WPS|NDEF> = build configuration token" },
{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
cli_cmd_flag_none,
"<WPS|NDEF> = create password token" },
@@ -2493,12 +2820,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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,
+ { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, 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" },
+ "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
+ "NFC handover" },
#endif /* CONFIG_WPS_NFC */
{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
cli_cmd_flag_sensitive,
@@ -2548,22 +2873,46 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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" },
+#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" },
@@ -2600,8 +2949,12 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
"= 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 "
@@ -2618,7 +2971,8 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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" },
@@ -2634,6 +2988,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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" },
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
@@ -2655,6 +3012,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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" },
@@ -2673,6 +3033,14 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "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,
@@ -2686,6 +3054,25 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
cli_cmd_flag_none,
"<addr> = tear down TDLS 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" },
@@ -2702,9 +3089,34 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
#ifdef CONFIG_WNM
{ "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" },
#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>] = Trigger request to AP for neighboring AP report "
+ "(with optional given SSID, default: current SSID)"
+ },
+ { "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"
+ },
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
@@ -2763,9 +3175,12 @@ static char ** wpa_list_cmd_list(void)
{
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;
@@ -2775,6 +3190,22 @@ static char ** wpa_list_cmd_list(void)
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;
}
@@ -2806,6 +3237,14 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
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();
@@ -2827,6 +3266,16 @@ static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
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) {
@@ -2875,28 +3324,19 @@ static int str_match(const char *a, const char *b)
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);
+ 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;
}
@@ -2904,15 +3344,29 @@ static void wpa_cli_action_process(const char *msg)
{
const char *pos;
char *copy = NULL, *id, *pos2;
+ const char *ifname = ctrl_ifname;
+ char ifname_buf[100];
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)) {
@@ -2946,34 +3400,48 @@ static void wpa_cli_action_process(const char *msg)
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, MESH_GROUP_STARTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+ } else if (str_match(pos, MESH_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+ } else if (str_match(pos, MESH_PEER_CONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+ } 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, ctrl_ifname, pos);
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
- wpa_cli_exec(action_file, ctrl_ifname, pos);
+ 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;
@@ -3105,7 +3573,7 @@ static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
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';
@@ -3169,10 +3637,18 @@ static int tokenize_cmd(char *cmd, char *argv[])
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();
@@ -3235,24 +3711,94 @@ static void start_edit(void)
}
+static void update_bssid_list(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "BSS RANGE=ALL MASK=0x2";
+ char *pos, *end;
+
+ 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) {
+ pos = os_strstr(pos, "bssid=");
+ if (pos == NULL)
+ break;
+ pos += 6;
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ cli_txt_list_add(&bsses, pos);
+ pos = end + 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 try_connection(void *eloop_ctx, void *timeout_ctx)
{
+ if (ctrl_conn)
+ goto done;
+
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
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);
return;
}
+ update_bssid_list(ctrl_conn);
+
if (warning_displayed)
printf("Connection established.\n");
+done:
start_edit();
}
@@ -3268,6 +3814,7 @@ static void wpa_cli_interactive(void)
cli_txt_list_flush(&p2p_peers);
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
+ cli_txt_list_flush(&ifnames);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile);
@@ -3374,7 +3921,7 @@ static char * wpa_cli_get_default_ifname(void)
#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;
@@ -3468,6 +4015,24 @@ int main(int argc, char *argv[])
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);
@@ -3482,7 +4047,8 @@ int main(int argc, char *argv[])
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;
}