GAS: Report GAS-QUERY-DONE event on initial req TX failure
[mech_eap.git] / wpa_supplicant / wpa_cli.c
index fe30b41..53036ae 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - command line interface for wpa_supplicant daemon
 /*
  * 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.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
 #endif /* ANDROID */
 
 
 #endif /* ANDROID */
 
 
-static const char *wpa_cli_version =
+static const char *const wpa_cli_version =
 "wpa_cli v" VERSION_STR "\n"
 "wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
 
 
 
 
-static const char *wpa_cli_license =
+static const char *const wpa_cli_license =
 "This software may be distributed under the terms of the BSD license.\n"
 "See README for more details.\n";
 
 "This software may be distributed under the terms of the BSD license.\n"
 "See README for more details.\n";
 
-static const char *wpa_cli_full_license =
+static const char *const wpa_cli_full_license =
 "This software may be distributed under the terms of the BSD license.\n"
 "\n"
 "Redistribution and use in source and binary forms, with or without\n"
 "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"
@@ -66,6 +66,12 @@ static const char *wpa_cli_full_license =
 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
 "\n";
 
 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
 "\n";
 
+#define VENDOR_ELEM_FRAME_ID \
+       "  0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
+       "3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
+       "7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \
+       "11: Assoc Req (P2P), 12: Assoc Resp (P2P)"
+
 static struct wpa_ctrl *ctrl_conn;
 static struct wpa_ctrl *mon_conn;
 static int wpa_cli_quit = 0;
 static struct wpa_ctrl *ctrl_conn;
 static struct wpa_ctrl *mon_conn;
 static int wpa_cli_quit = 0;
@@ -76,6 +82,7 @@ static int wpa_cli_last_id = 0;
 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
 #endif /* CONFIG_CTRL_IFACE_DIR */
 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
 #endif /* CONFIG_CTRL_IFACE_DIR */
 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
+static const char *client_socket_dir = NULL;
 static char *ctrl_ifname = NULL;
 static const char *pid_file = NULL;
 static const char *action_file = NULL;
 static char *ctrl_ifname = NULL;
 static const char *pid_file = NULL;
 static const char *action_file = NULL;
@@ -92,6 +99,7 @@ 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(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 print_help(const char *cmd);
@@ -99,13 +107,16 @@ static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
 static void wpa_cli_close_connection(void);
 static char * wpa_cli_get_default_ifname(void);
 static char ** wpa_list_cmd_list(void);
 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"
 
 
 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"
               "[command..]\n"
               "  -h = help (show this usage text)\n"
               "  -v = shown version information\n"
@@ -168,11 +179,12 @@ static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
 
 
 #ifdef CONFIG_P2P
 
 
 #ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
+static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+                                 int separator)
 {
        const char *end;
        char *buf;
 {
        const char *end;
        char *buf;
-       end = os_strchr(txt, ' ');
+       end = os_strchr(txt, separator);
        if (end == NULL)
                end = txt + os_strlen(txt);
        buf = dup_binstr(txt, end - txt);
        if (end == NULL)
                end = txt + os_strlen(txt);
        buf = dup_binstr(txt, end - txt);
@@ -213,14 +225,16 @@ static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
        os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
        return cli_txt_list_add(txt_list, buf);
 }
        os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
        return cli_txt_list_add(txt_list, buf);
 }
+#endif /* CONFIG_P2P */
 
 
 
 
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
+static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+                                int separator)
 {
        const char *end;
        char *buf;
        int ret;
 {
        const char *end;
        char *buf;
        int ret;
-       end = os_strchr(txt, ' ');
+       end = os_strchr(txt, separator);
        if (end == NULL)
                end = txt + os_strlen(txt);
        buf = dup_binstr(txt, end - txt);
        if (end == NULL)
                end = txt + os_strlen(txt);
        buf = dup_binstr(txt, end - txt);
@@ -230,7 +244,6 @@ static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
        os_free(buf);
        return ret;
 }
        os_free(buf);
        return ret;
 }
-#endif /* CONFIG_P2P */
 
 
 static char ** cli_txt_list_array(struct dl_list *txt_list)
 
 
 static char ** cli_txt_list_array(struct dl_list *txt_list)
@@ -326,6 +339,13 @@ static int wpa_cli_open_connection(const char *ifname, int attach)
        }
 #endif /* ANDROID */
 
        }
 #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);
        if (cfile == NULL) {
                flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
                cfile = os_malloc(flen);
@@ -333,20 +353,20 @@ static int wpa_cli_open_connection(const char *ifname, int attach)
                        return -1;
                res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
                                  ifname);
                        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;
                }
        }
 
                        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)
        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);
        else
                mon_conn = NULL;
        os_free(cfile);
@@ -448,13 +468,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);
        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]);
                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;
        }
                        goto fail;
                pos += res;
        }
@@ -498,6 +518,10 @@ static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, 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");
                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");
 }
 
        return wpa_ctrl_command(ctrl, "STATUS");
 }
 
@@ -584,7 +608,7 @@ static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
 
        if (argc == 1) {
                res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[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;
                }
                        printf("Too long SET command.\n");
                        return -1;
                }
@@ -608,34 +632,58 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
                "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
                "no_keep_alive",
                /* global configuration parameters */
                "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
                "no_keep_alive",
                /* global configuration parameters */
-               "eapol_version", "ap_scan", "disable_scan_offload",
-               "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
-               "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
-               "driver_param", "dot11RSNAConfigPMKLifetime",
+#ifdef CONFIG_CTRL_IFACE
+               "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group",
+#endif /* CONFIG_CTRL_IFACE */
+               "eapol_version", "ap_scan", "bgscan",
+#ifdef CONFIG_MESH
+               "user_mpm", "max_peer_links", "mesh_max_inactivity",
+               "dot11RSNASAERetransPeriod",
+#endif /* CONFIG_MESH */
+               "disable_scan_offload", "fast_reauth", "opensc_engine_path",
+               "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
+               "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
+               "dot11RSNAConfigPMKLifetime",
                "dot11RSNAConfigPMKReauthThreshold",
                "dot11RSNAConfigSATimeout",
                "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_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",
                "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);
 
        };
        int i, num_fields = ARRAY_SIZE(fields);
 
@@ -657,6 +705,11 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
        return NULL;
 }
 
        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_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 
 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
@@ -664,6 +717,74 @@ static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
 }
 
 
+static char ** wpa_cli_complete_get(const char *str, int pos)
+{
+       int arg = get_cmd_arg_num(str, pos);
+       const char *fields[] = {
+#ifdef CONFIG_CTRL_IFACE
+               "ctrl_interface", "ctrl_interface_group",
+#endif /* CONFIG_CTRL_IFACE */
+               "eapol_version", "ap_scan",
+#ifdef CONFIG_MESH
+               "user_mpm", "max_peer_links", "mesh_max_inactivity",
+#endif /* CONFIG_MESH */
+               "disable_scan_offload", "fast_reauth", "opensc_engine_path",
+               "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers",
+               "pcsc_reader", "pcsc_pin", "external_sim", "driver_param",
+               "dot11RSNAConfigPMKLifetime",
+               "dot11RSNAConfigPMKReauthThreshold",
+               "dot11RSNAConfigSATimeout",
+#ifndef CONFIG_NO_CONFIG_WRITE
+               "update_config",
+#endif /* CONFIG_NO_CONFIG_WRITE */
+#ifdef CONFIG_WPS
+               "device_name", "manufacturer", "model_name", "model_number",
+               "serial_number", "config_methods", "wps_cred_processing",
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+               "p2p_listen_reg_class", "p2p_listen_channel",
+               "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent",
+               "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss",
+               "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan",
+               "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
+               "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
+               "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
+               "ip_addr_start", "ip_addr_end",
+#endif /* CONFIG_P2P */
+               "bss_max_count", "bss_expiration_age",
+               "bss_expiration_scan_count", "filter_ssids", "filter_rssi",
+               "max_num_sta", "disassoc_low_ack",
+#ifdef CONFIG_HS20
+               "hs20",
+#endif /* CONFIG_HS20 */
+               "interworking", "access_network_type", "pbc_in_m1", "autoscan",
+               "wps_nfc_dev_pw_id", "ext_password_backend",
+               "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
+               "dtim_period", "beacon_int", "ignore_old_scan_res",
+               "scan_cur_freq", "sched_scan_interval",
+               "tdls_external_control", "osu_dir", "wowlan_triggers",
+               "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
+               "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
+               "reassoc_same_bss_optim"
+       };
+       int i, num_fields = ARRAY_SIZE(fields);
+
+       if (arg == 1) {
+               char **res = os_calloc(num_fields + 1, sizeof(char *));
+               if (res == NULL)
+                       return NULL;
+               for (i = 0; i < num_fields; i++) {
+                       res[i] = os_strdup(fields[i]);
+                       if (res[i] == NULL)
+                               return res;
+               }
+               return res;
+       }
+
+       return NULL;
+}
+
+
 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        return wpa_ctrl_command(ctrl, "LOGOFF");
 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        return wpa_ctrl_command(ctrl, "LOGOFF");
@@ -732,7 +853,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]);
                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;
        }
                printf("Too long BSS_FLUSH command.\n");
                return -1;
        }
@@ -867,12 +988,12 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
                res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
                                  argv[0], argv[1]);
        else if (argc == 5 || argc == 6) {
                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';
                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]);
                        if (argv[2][i] == '\0')
                                break;
                        os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
@@ -907,7 +1028,7 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
                return -1;
        }
 
                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;
        }
                printf("Too long WPS_REG command.\n");
                return -1;
        }
@@ -996,12 +1117,12 @@ static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
        int res;
 
        if (argc == 5 || argc == 6) {
        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';
                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]);
                        if (argv[2][i] == '\0')
                                break;
                        os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
@@ -1032,7 +1153,7 @@ static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
                return -1;
        }
 
                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;
        }
                printf("Too long WPS_ER_CONFIG command.\n");
                return -1;
        }
@@ -1084,14 +1205,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]);
        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]);
                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;
                }
                        printf("Too long IDENTITY command.\n");
                        return -1;
                }
@@ -1117,14 +1238,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]);
        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]);
                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;
                }
                        printf("Too long PASSWORD command.\n");
                        return -1;
                }
@@ -1151,14 +1272,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]);
        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]);
                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;
                }
                        printf("Too long NEW_PASSWORD command.\n");
                        return -1;
                }
@@ -1184,14 +1305,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]);
        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]);
                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;
                }
                        printf("Too long PIN command.\n");
                        return -1;
                }
@@ -1216,14 +1337,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]);
        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]);
                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;
                }
                        printf("Too long OTP command.\n");
                        return -1;
                }
@@ -1249,14 +1370,14 @@ static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
                          argv[0], argv[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]);
                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;
                }
                        printf("Too long SIM command.\n");
                        return -1;
                }
@@ -1282,14 +1403,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]);
        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]);
                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;
                }
                        printf("Too long PASSPHRASE command.\n");
                        return -1;
                }
@@ -1355,14 +1476,20 @@ static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
 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[])
 {
 }
 
 
 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;
 }
 
 
 }
 
 
@@ -1423,6 +1550,105 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
 }
 
 
 }
 
 
+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 int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
@@ -1441,6 +1667,31 @@ static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
 }
 
 
 }
 
 
+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_list_creds(struct wpa_ctrl *ctrl, int argc,
                                  char *argv[])
 {
@@ -1519,6 +1770,13 @@ static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
 }
 
 
 }
 
 
+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 int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
@@ -1576,6 +1834,10 @@ 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]);
        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);
 
        if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
                printf("Connected to interface '%s.\n", ctrl_ifname);
@@ -1611,21 +1873,22 @@ static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
                printf("Invalid INTERFACE_ADD command: needs at least one "
                       "argument (interface name)\n"
                       "All arguments: ifname confname driver ctrl_interface "
                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
                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),
         */
        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] : "",
                          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);
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -1664,6 +1927,12 @@ static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
                printf("Not connected to hostapd - command dropped.\n");
                return -1;
        }
                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);
        len = sizeof(buf) - 1;
        ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
                               wpa_cli_msg_cb);
@@ -1751,6 +2020,45 @@ static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
 }
 
 
+#ifdef CONFIG_MESH
+
+static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
+                                         char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
+                                        char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
+                                    char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
+}
+
+#endif /* CONFIG_MESH */
+
+
 #ifdef CONFIG_P2P
 
 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
 #ifdef CONFIG_P2P
 
 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
@@ -1795,6 +2103,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[])
 {
 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
@@ -1853,6 +2175,13 @@ static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
 }
 
 
 }
 
 
+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[])
 {
 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
                                     char *argv[])
 {
@@ -1879,11 +2208,9 @@ static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
 {
        char cmd[4096];
 
 {
        char cmd[4096];
 
-       if (argc != 2 && argc != 4) {
+       if (argc < 2) {
                printf("Invalid P2P_SERV_DISC_REQ command: needs two "
                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;
        }
 
                return -1;
        }
 
@@ -1914,7 +2241,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]);
 
        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);
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -1945,27 +2272,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[])
 {
 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;
        }
 
                       "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);
 }
 
 
 }
 
 
@@ -1989,7 +2314,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]);
                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 -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -2193,6 +2518,27 @@ static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
        return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
 }
 
        return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
 }
 
+
+static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
+                                      char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
+                                      char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
+                                         char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
+}
+
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WIFI_DISPLAY
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WIFI_DISPLAY
@@ -2211,7 +2557,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] : "");
 
        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);
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -2232,7 +2578,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]);
 
        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);
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -2269,6 +2615,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);
 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);
@@ -2379,6 +2732,48 @@ static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
 }
 
 
 }
 
 
+static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
+                                   char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
+                                   char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
+                                   char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
+}
+
+
+static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
+                                              char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
+}
+
+
 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
@@ -2386,6 +2781,13 @@ static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
 }
 
 
 }
 
 
+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_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
@@ -2463,6 +2865,33 @@ static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
 }
 
 
+static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
+                                           char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "ERP_FLUSH");
+}
+
+
+static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
+                                    char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
+                                         char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
+}
+
+
 enum wpa_cli_cmd_flags {
        cli_cmd_flag_none               = 0x00,
        cli_cmd_flag_sensitive          = 0x01
 enum wpa_cli_cmd_flags {
        cli_cmd_flag_none               = 0x00,
        cli_cmd_flag_sensitive          = 0x01
@@ -2476,7 +2905,7 @@ struct wpa_cli_cmd {
        const char *usage;
 };
 
        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" },
        { "status", wpa_cli_cmd_status, NULL,
          cli_cmd_flag_none,
          "[verbose] = get current WPA/EAPOL/EAP status" },
@@ -2514,7 +2943,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
          cli_cmd_flag_none,
          "= set variables (shows list of variables when run without "
          "arguments)" },
          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" },
        { "logon", wpa_cli_cmd_logon, NULL,
          cli_cmd_flag_none,
          "<name> = get information" },
        { "logon", wpa_cli_cmd_logon, NULL,
@@ -2576,29 +3008,33 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "list_networks", wpa_cli_cmd_list_networks, NULL,
          cli_cmd_flag_none,
          "= list configured networks" },
        { "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)" },
          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" },
          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" },
          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" },
          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)" },
          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" },
          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"
        },
          cli_cmd_flag_none,
          "<src network id> <dst network id> <variable> = duplicate network variables"
        },
@@ -2634,13 +3070,16 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "scan_results", wpa_cli_cmd_scan_results, NULL,
          cli_cmd_flag_none,
          "= get latest scan results" },
        { "scan_results", wpa_cli_cmd_scan_results, NULL,
          cli_cmd_flag_none,
          "= get latest scan results" },
+       { "abort_scan", wpa_cli_cmd_abort_scan, NULL,
+         cli_cmd_flag_none,
+         "= request ongoing scan to be aborted" },
        { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
          cli_cmd_flag_none,
          "<<idx> | <bssid>> = get detailed scan result info" },
        { "get_capability", wpa_cli_cmd_get_capability, NULL,
          cli_cmd_flag_none,
          "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
        { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
          cli_cmd_flag_none,
          "<<idx> | <bssid>> = get detailed scan result info" },
        { "get_capability", wpa_cli_cmd_get_capability, NULL,
          cli_cmd_flag_none,
          "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
-         "= get capabilies" },
+         "= get capabilities" },
        { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
          cli_cmd_flag_none,
          "= force wpa_supplicant to re-read its configuration file" },
        { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
          cli_cmd_flag_none,
          "= force wpa_supplicant to re-read its configuration file" },
@@ -2650,8 +3089,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "interface_add", wpa_cli_cmd_interface_add, NULL,
          cli_cmd_flag_none,
          "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
        { "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" },
        { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
          cli_cmd_flag_none,
          "<ifname> = removes the interface" },
@@ -2780,12 +3221,35 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
          cli_cmd_flag_none,
          "<addr> = roam to the specified BSS" },
        { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
          cli_cmd_flag_none,
          "<addr> = roam to the specified BSS" },
+#ifdef CONFIG_MESH
+       { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
+         cli_cmd_flag_none,
+         "[ifname] = Create a new mesh interface" },
+       { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
+         cli_cmd_flag_none,
+         "<network id> = join a mesh network (disable others)" },
+       { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
+         cli_cmd_flag_none,
+         "<ifname> = Remove mesh group interface" },
+       { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
+         cli_cmd_flag_none,
+         "<addr> = Remove a mesh peer" },
+       { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
+         cli_cmd_flag_none,
+         "<addr> [duration=<seconds>] = Add a mesh peer" },
+#endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
        { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
          cli_cmd_flag_none,
          "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
        { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
          "= stop P2P Devices search" },
 #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" },
        { "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" },
@@ -2796,6 +3260,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
          "<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)" },
          "<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" },
        { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
          wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
          "<addr> <method> = request provisioning discovery" },
@@ -2822,8 +3289,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,
          "= 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" },
          "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_service_del", wpa_cli_cmd_p2p_service_del, NULL,
          cli_cmd_flag_none,
          "<bonjour|upnp> <query|version> [|service] = remove a local "
@@ -2860,6 +3331,18 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "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" },
        { "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,
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_WIFI_DISPLAY
        { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
@@ -2881,6 +3364,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_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" },
        { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
          cli_cmd_flag_none,
          "<addr> <info id>[,<info id>]... = request ANQP information" },
@@ -2920,9 +3406,34 @@ 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>" },
        { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
          cli_cmd_flag_none,
          "<addr> = tear down TDLS with <addr>" },
+       { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
+         cli_cmd_flag_none,
+         "<addr> = TDLS link status with <addr>" },
+       { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
+         cli_cmd_flag_none,
+         "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
+         "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
+         "= add WMM-AC traffic stream" },
+       { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
+         cli_cmd_flag_none,
+         "<tsid> = delete WMM-AC traffic stream" },
+       { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
+         cli_cmd_flag_none,
+         "= show status for Wireless Multi-Media Admission-Control" },
+       { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
+         cli_cmd_flag_none,
+         "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
+         "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
+         "with TDLS peer" },
+       { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
+         cli_cmd_flag_none,
+         "<addr> = disable channel switching with TDLS peer <addr>" },
        { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
          cli_cmd_flag_none,
          "= get signal parameters" },
        { "signal_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" },
        { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
          cli_cmd_flag_none,
          "= get TX/RX packet counters" },
@@ -2937,7 +3448,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "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,
        { "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" },
 #endif /* CONFIG_WNM */
        { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
          "<params..> = Sent unprocessed command" },
@@ -2952,6 +3463,20 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
          "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
        },
        { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
          "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
        },
+       { "neighbor_rep_request",
+         wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
+         "[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)"
+       },
+       { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
+         "= flush ERP keys" },
+       { "mac_rand_scan",
+         wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
+         "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
+         "mask=mac-address-mask] = scan MAC randomization"
+       },
+       { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
+         cli_cmd_flag_none,
+         "<interface type> = retrieve preferred freq list for the specified interface type" },
        { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
        { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
@@ -2959,7 +3484,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 /*
  * Prints command usage, lines are padded with the specified string.
  */
 /*
  * Prints command usage, lines are padded with the specified string.
  */
-static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
+static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
 {
        char c;
        size_t n;
 {
        char c;
        size_t n;
@@ -3097,7 +3622,7 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
 
 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 
 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;
 
        int count;
        int ret = 0;
 
@@ -3163,6 +3688,10 @@ static int wpa_cli_exec(const char *program, const char *arg1,
        size_t len;
        int res;
 
        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)
        len = os_strlen(arg1) + os_strlen(arg2) + 2;
        arg = os_malloc(len);
        if (arg == NULL)
@@ -3182,6 +3711,9 @@ static void wpa_cli_action_process(const char *msg)
        const char *ifname = ctrl_ifname;
        char ifname_buf[100];
 
        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 = msg;
        if (os_strncmp(pos, "IFNAME=", 7) == 0) {
                const char *end;
@@ -3245,6 +3777,18 @@ static void wpa_cli_action_process(const char *msg)
                        wpa_cli_connected = 0;
                        wpa_cli_exec(action_file, ifname, "DISCONNECTED");
                }
                        wpa_cli_connected = 0;
                        wpa_cli_exec(action_file, ifname, "DISCONNECTED");
                }
+       } else if (str_match(pos, AP_EVENT_ENABLED)) {
+               wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } else if (str_match(pos, AP_EVENT_DISABLED)) {
+               wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } else if (str_match(pos, MESH_GROUP_STARTED)) {
+               wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } else if (str_match(pos, MESH_GROUP_REMOVED)) {
+               wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } else if (str_match(pos, MESH_PEER_CONNECTED)) {
+               wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } 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)) {
        } 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)) {
@@ -3351,7 +3895,7 @@ static void cli_event(const char *str)
                s = os_strchr(start, ' ');
                if (s == NULL)
                        return;
                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;
        }
 
                return;
        }
 
@@ -3359,7 +3903,7 @@ static void cli_event(const char *str)
                s = os_strchr(start, ' ');
                if (s == NULL)
                        return;
                s = os_strchr(start, ' ');
                if (s == NULL)
                        return;
-               cli_txt_list_del_word(&p2p_groups, s + 1);
+               cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
                return;
        }
 #endif /* CONFIG_P2P */
                return;
        }
 #endif /* CONFIG_P2P */
@@ -3518,7 +4062,11 @@ static void start_edit(void)
        ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
 
        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");
        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;
        if (home) {
                const char *fname = ".wpa_cli_history";
                int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
@@ -3594,13 +4142,45 @@ static void update_ifnames(struct wpa_ctrl *ctrl)
                        break;
                *end = '\0';
                ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
                        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;
        }
 }
 
 
                        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)
 static void try_connection(void *eloop_ctx, void *timeout_ctx)
 {
        if (ctrl_conn)
@@ -3609,10 +4189,11 @@ static void try_connection(void *eloop_ctx, void *timeout_ctx)
        if (ctrl_ifname == NULL)
                ctrl_ifname = wpa_cli_get_default_ifname();
 
        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: "
                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);
                        warning_displayed = 1;
                }
                eloop_register_timeout(1, 0, try_connection, NULL, NULL);
@@ -3620,6 +4201,7 @@ static void try_connection(void *eloop_ctx, void *timeout_ctx)
        }
 
        update_bssid_list(ctrl_conn);
        }
 
        update_bssid_list(ctrl_conn);
+       update_networks(ctrl_conn);
 
        if (warning_displayed)
                printf("Connection established.\n");
 
        if (warning_displayed)
                printf("Connection established.\n");
@@ -3641,6 +4223,7 @@ static void wpa_cli_interactive(void)
        cli_txt_list_flush(&p2p_groups);
        cli_txt_list_flush(&bsses);
        cli_txt_list_flush(&ifnames);
        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);
        if (edit_started)
                edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
        os_free(hfile);
@@ -3649,45 +4232,49 @@ static void wpa_cli_interactive(void)
 }
 
 
 }
 
 
+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 */
 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);
 
        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 */
 }
 
 #endif /* CONFIG_ANSI_C_EXTRA */
 }
 
@@ -3712,18 +4299,17 @@ static char * wpa_cli_get_default_ifname(void)
 {
        char *ifname = NULL;
 
 {
        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 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))) {
                return NULL;
        }
        while ((dent = readdir(dir))) {
@@ -3767,6 +4353,7 @@ static char * wpa_cli_get_default_ifname(void)
        }
        wpa_ctrl_close(ctrl);
 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
        }
        wpa_ctrl_close(ctrl);
 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+#endif /* ANDROID */
 
        return ifname;
 }
 
        return ifname;
 }
@@ -3783,7 +4370,7 @@ int main(int argc, char *argv[])
                return -1;
 
        for (;;) {
                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) {
                if (c < 0)
                        break;
                switch (c) {
@@ -3815,6 +4402,9 @@ int main(int argc, char *argv[])
                case 'P':
                        pid_file = optarg;
                        break;
                case 'P':
                        pid_file = optarg;
                        break;
+               case 's':
+                       client_socket_dir = optarg;
+                       break;
                default:
                        usage();
                        return -1;
                default:
                        usage();
                        return -1;
@@ -3873,7 +4463,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",
                    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;
                }
 
                        return -1;
                }
 
@@ -3887,7 +4478,7 @@ int main(int argc, char *argv[])
                        }
                }
 
                        }
                }
 
-               if (daemonize && os_daemonize(pid_file))
+               if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
                        return -1;
 
                if (action_file)
                        return -1;
 
                if (action_file)