/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2013, 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.
#include <dirent.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
+#include "common/cli.h"
#include "common/wpa_ctrl.h"
#include "utils/common.h"
#include "utils/eloop.h"
#endif /* ANDROID */
-static const char *wpa_cli_version =
+static const char *const wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
-
-
-static const char *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 =
-"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"
-"modification, are permitted provided that the following conditions are\n"
-"met:\n"
-"\n"
-"1. Redistributions of source code must retain the above copyright\n"
-" notice, this list of conditions and the following disclaimer.\n"
-"\n"
-"2. Redistributions in binary form must reproduce the above copyright\n"
-" notice, this list of conditions and the following disclaimer in the\n"
-" documentation and/or other materials provided with the distribution.\n"
-"\n"
-"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
-" names of its contributors may be used to endorse or promote products\n"
-" derived from this software without specific prior written permission.\n"
-"\n"
-"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
-"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
-"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
-"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
-"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
-"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
-"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
-"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
-"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
-"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
-"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
-"\n";
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
+
+#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;
#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 interactive = 0;
static char *ifname_prefix = NULL;
-struct cli_txt_entry {
- struct dl_list list;
- char *txt;
-};
-
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"
}
-static void cli_txt_list_free(struct cli_txt_entry *e)
-{
- dl_list_del(&e->list);
- os_free(e->txt);
- os_free(e);
-}
-
-
-static void cli_txt_list_flush(struct dl_list *list)
-{
- struct cli_txt_entry *e;
- while ((e = dl_list_first(list, struct cli_txt_entry, list)))
- cli_txt_list_free(e);
-}
-
-
-static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
- const char *txt)
-{
- struct cli_txt_entry *e;
- dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
- if (os_strcmp(e->txt, txt) == 0)
- return e;
- }
- return NULL;
-}
-
-
-static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
-{
- struct cli_txt_entry *e;
- e = cli_txt_list_get(txt_list, txt);
- if (e)
- cli_txt_list_free(e);
-}
-
-
-static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
-{
- u8 addr[ETH_ALEN];
- char buf[18];
- if (hwaddr_aton(txt, addr) < 0)
- return;
- os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
- cli_txt_list_del(txt_list, buf);
-}
-
-
-#ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
-{
- const char *end;
- char *buf;
- end = os_strchr(txt, ' ');
- if (end == NULL)
- end = txt + os_strlen(txt);
- buf = dup_binstr(txt, end - txt);
- if (buf == NULL)
- return;
- cli_txt_list_del(txt_list, buf);
- os_free(buf);
-}
-#endif /* CONFIG_P2P */
-
-
-static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
-{
- struct cli_txt_entry *e;
- e = cli_txt_list_get(txt_list, txt);
- if (e)
- return 0;
- e = os_zalloc(sizeof(*e));
- if (e == NULL)
- return -1;
- e->txt = os_strdup(txt);
- if (e->txt == NULL) {
- os_free(e);
- return -1;
- }
- dl_list_add(txt_list, &e->list);
- return 0;
-}
-
-
-#ifdef CONFIG_P2P
-static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
-{
- u8 addr[ETH_ALEN];
- char buf[18];
- if (hwaddr_aton(txt, addr) < 0)
- return -1;
- os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
- return cli_txt_list_add(txt_list, buf);
-}
-
-
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
-{
- const char *end;
- char *buf;
- int ret;
- end = os_strchr(txt, ' ');
- if (end == NULL)
- end = txt + os_strlen(txt);
- buf = dup_binstr(txt, end - txt);
- if (buf == NULL)
- return -1;
- ret = cli_txt_list_add(txt_list, buf);
- os_free(buf);
- return ret;
-}
-#endif /* CONFIG_P2P */
-
-
-static char ** cli_txt_list_array(struct dl_list *txt_list)
-{
- unsigned int i, count = dl_list_len(txt_list);
- char **res;
- struct cli_txt_entry *e;
-
- res = os_calloc(count + 1, sizeof(char *));
- if (res == NULL)
- return NULL;
-
- i = 0;
- dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
- res[i] = os_strdup(e->txt);
- if (res[i] == NULL)
- break;
- i++;
- }
-
- return res;
-}
-
-
-static int get_cmd_arg_num(const char *str, int pos)
-{
- int arg = 0, i;
-
- for (i = 0; i <= pos; i++) {
- if (str[i] != ' ') {
- arg++;
- while (i <= pos && str[i] != ' ')
- i++;
- }
- }
-
- if (arg > 0)
- arg--;
- return arg;
-}
-
-
-static int str_starts(const char *src, const char *match)
-{
- return os_strncmp(src, match, os_strlen(match)) == 0;
-}
-
-
static int wpa_cli_show_event(const char *event)
{
const char *start;
}
#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);
}
-static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
- char *argv[])
-{
- int i, res;
- char *pos, *end;
-
- pos = buf;
- end = buf + buflen;
-
- res = os_snprintf(pos, end - pos, "%s", cmd);
- if (res < 0 || res >= end - pos)
- 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)
- goto fail;
- pos += res;
- }
-
- buf[buflen - 1] = '\0';
- return 0;
-
-fail:
- printf("Too long command\n");
- return -1;
-}
-
-
static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
int argc, char *argv[])
{
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_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
+ printf("%s\n\n%s\n", wpa_cli_version, cli_full_license);
return 0;
}
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", "openssl_ciphers",
- "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_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_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", "external_sim",
- "tdls_external_control", "p2p_search_delay"
+ "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 = ARRAY_SIZE(fields);
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");
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;
}
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;
}
pos = cmd;
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
argv[0], argv[1]);
- if (ret < 0 || ret >= end - pos) {
+ 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 (ret < 0 || ret >= end - pos) {
+ if (os_snprintf_error(end - pos, ret)) {
printf("Too long SIM command.\n");
return -1;
}
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[])
{
}
+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_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);
}
+static char ** wpa_cli_complete_get_capability(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ "eap", "pairwise", "group", "group_mgmt", "key_mgmt",
+ "proto", "auth_alg", "modes", "channels", "freq",
+#ifdef CONFIG_TDLS
+ "tdls",
+#endif /* CONFIG_TDLS */
+#ifdef CONFIG_ERP
+ "erp",
+#endif /* CONFIG_ERP */
+#ifdef CONFIG_FIPS
+ "fips",
+#endif /* CONFIG_FIPS */
+#ifdef CONFIG_ACS
+ "acs",
+#endif /* CONFIG_ACS */
+ };
+ int i, num_fields = ARRAY_SIZE(fields);
+ char **res = NULL;
+
+ if (arg == 1) {
+ 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;
+ }
+ }
+ if (arg == 2) {
+ res = os_calloc(1 + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ res[0] = os_strdup("strict");
+ }
+ return res;
+}
+
+
static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
{
printf("Available interfaces:\n");
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) == 0) {
printf("Connected to interface '%s.\n", ctrl_ifname);
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);
#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_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 */
}
+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[])
{
}
+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;
+ }
- if (argc != 3 && argc != 4) {
- printf("Invalid P2P_SERVICE_ADD command: needs three or four "
+ return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
+}
+
+
+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);
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);
}
+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[])
{
}
+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[])
{
}
+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" },
{ "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, NULL,
+ { "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"
},
{ "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,
+ { "get_capability", wpa_cli_cmd_get_capability,
+ wpa_cli_complete_get_capability, 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" },
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,
"[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_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" },
{ "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=#] "
{ "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" },
},
{ "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)"
+ "[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;
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;
}
-static int str_match(const char *a, const char *b)
-{
- return os_strncmp(a, b, os_strlen(b)) == 0;
-}
-
-
static int wpa_cli_exec(const char *program, const char *arg1,
const char *arg2)
{
size_t len;
int res;
+ /* 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)
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;
pos = prev;
}
- if (str_match(pos, WPA_EVENT_CONNECTED)) {
+ if (str_starts(pos, WPA_EVENT_CONNECTED)) {
int new_id = -1;
os_unsetenv("WPA_ID");
os_unsetenv("WPA_ID_STR");
wpa_cli_last_id = new_id;
wpa_cli_exec(action_file, ifname, "CONNECTED");
}
- } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
+ } else if (str_starts(pos, WPA_EVENT_DISCONNECTED)) {
if (wpa_cli_connected) {
wpa_cli_connected = 0;
wpa_cli_exec(action_file, ifname, "DISCONNECTED");
}
- } else if (str_match(pos, MESH_GROUP_STARTED)) {
+ } else if (str_starts(pos, AP_EVENT_ENABLED)) {
+ wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_starts(pos, AP_EVENT_DISABLED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_GROUP_REMOVED)) {
+ } else if (str_starts(pos, MESH_GROUP_STARTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_PEER_CONNECTED)) {
+ } else if (str_starts(pos, MESH_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
+ } else if (str_starts(pos, MESH_PEER_CONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+ } else if (str_starts(pos, MESH_PEER_DISCONNECTED)) {
+ wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_starts(pos, P2P_EVENT_GROUP_STARTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+ } else if (str_starts(pos, P2P_EVENT_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+ } else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+ } else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
+ } else if (str_starts(pos, P2P_EVENT_GO_NEG_FAILURE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
+ } else if (str_starts(pos, WPS_EVENT_SUCCESS)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPS_EVENT_FAIL)) {
+ } else if (str_starts(pos, WPS_EVENT_FAIL)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, AP_STA_CONNECTED)) {
+ } else if (str_starts(pos, AP_STA_CONNECTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, AP_STA_DISCONNECTED)) {
+ } else if (str_starts(pos, AP_STA_DISCONNECTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
+ } else if (str_starts(pos, ESS_DISASSOC_IMMINENT)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
+ } else if (str_starts(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
+ } else if (str_starts(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
+ } else if (str_starts(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 */
pos = msg;
}
- if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
+ if (str_starts(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
edit_clear_line();
printf("\rConnection to wpa_supplicant lost - trying to "
"reconnect\n");
}
}
-#define max_args 10
-
-static int tokenize_cmd(char *cmd, char *argv[])
-{
- char *pos;
- int argc = 0;
-
- pos = cmd;
- for (;;) {
- while (*pos == ' ')
- pos++;
- if (*pos == '\0')
- break;
- argv[argc] = pos;
- argc++;
- if (argc == max_args)
- break;
- if (*pos == '"') {
- char *pos2 = os_strrchr(pos, '"');
- if (pos2)
- pos = pos2 + 1;
- }
- while (*pos != '\0' && *pos != ' ')
- pos++;
- if (*pos == ' ')
- *pos++ = '\0';
- }
-
- return argc;
-}
-
static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
{
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;
break;
*end = '\0';
ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
- if (ret > 0 && ret < (int) sizeof(txt))
+ 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_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))) {
}
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;
interactive = (argc == optind) && (action_file == NULL);
if (interactive)
- printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
+ printf("%s\n\n%s\n\n", wpa_cli_version, cli_license);
if (eloop_init())
return -1;
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)