wpa_cli: Add MAC address randomization in scan
[mech_eap.git] / wpa_supplicant / wpa_cli.c
index 77c5295..d2face0 100644 (file)
@@ -333,7 +333,7 @@ static int wpa_cli_open_connection(const char *ifname, int attach)
                        return -1;
                res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
                                  ifname);
-               if (res < 0 || res >= flen) {
+               if (os_snprintf_error(flen, res)) {
                        os_free(cfile);
                        return -1;
                }
@@ -448,13 +448,13 @@ static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
        end = buf + buflen;
 
        res = os_snprintf(pos, end - pos, "%s", cmd);
-       if (res < 0 || res >= end - pos)
+       if (os_snprintf_error(end - pos, res))
                goto fail;
        pos += res;
 
        for (i = 0; i < argc; i++) {
                res = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (res < 0 || res >= end - pos)
+               if (os_snprintf_error(end - pos, res))
                        goto fail;
                pos += res;
        }
@@ -532,6 +532,13 @@ static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
+static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+                                  char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
+}
+
+
 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        print_help(argc > 0 ? argv[0] : NULL);
@@ -577,7 +584,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 (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+               if (os_snprintf_error(sizeof(cmd), res)) {
                        printf("Too long SET command.\n");
                        return -1;
                }
@@ -603,7 +610,8 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
                /* 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",
+               "pkcs11_module_path", "openssl_ciphers",
+               "pcsc_reader", "pcsc_pin",
                "driver_param", "dot11RSNAConfigPMKLifetime",
                "dot11RSNAConfigPMKReauthThreshold",
                "dot11RSNAConfigSATimeout",
@@ -628,7 +636,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
                "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"
+               "tdls_external_control", "p2p_search_delay"
        };
        int i, num_fields = ARRAY_SIZE(fields);
 
@@ -725,7 +733,7 @@ static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
                res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
        else
                res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long BSS_FLUSH command.\n");
                return -1;
        }
@@ -900,7 +908,7 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
                return -1;
        }
 
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long WPS_REG command.\n");
                return -1;
        }
@@ -1025,7 +1033,7 @@ static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
                return -1;
        }
 
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+       if (os_snprintf_error(sizeof(cmd), res)) {
                printf("Too long WPS_ER_CONFIG command.\n");
                return -1;
        }
@@ -1077,14 +1085,14 @@ static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
                          argv[0], argv[1]);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                printf("Too long IDENTITY command.\n");
                return -1;
        }
        pos += ret;
        for (i = 2; i < argc; i++) {
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        printf("Too long IDENTITY command.\n");
                        return -1;
                }
@@ -1110,14 +1118,14 @@ static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
                          argv[0], argv[1]);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                printf("Too long PASSWORD command.\n");
                return -1;
        }
        pos += ret;
        for (i = 2; i < argc; i++) {
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        printf("Too long PASSWORD command.\n");
                        return -1;
                }
@@ -1144,14 +1152,14 @@ static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
                          argv[0], argv[1]);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                printf("Too long NEW_PASSWORD command.\n");
                return -1;
        }
        pos += ret;
        for (i = 2; i < argc; i++) {
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        printf("Too long NEW_PASSWORD command.\n");
                        return -1;
                }
@@ -1177,14 +1185,14 @@ static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
                          argv[0], argv[1]);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                printf("Too long PIN command.\n");
                return -1;
        }
        pos += ret;
        for (i = 2; i < argc; i++) {
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        printf("Too long PIN command.\n");
                        return -1;
                }
@@ -1209,14 +1217,14 @@ static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
                          argv[0], argv[1]);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                printf("Too long OTP command.\n");
                return -1;
        }
        pos += ret;
        for (i = 2; i < argc; i++) {
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        printf("Too long OTP command.\n");
                        return -1;
                }
@@ -1242,14 +1250,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]);
-       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;
                }
@@ -1275,14 +1283,14 @@ static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
        pos = cmd;
        ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
                          argv[0], argv[1]);
-       if (ret < 0 || ret >= end - pos) {
+       if (os_snprintf_error(end - pos, ret)) {
                printf("Too long PASSPHRASE command.\n");
                return -1;
        }
        pos += ret;
        for (i = 2; i < argc; i++) {
                ret = os_snprintf(pos, end - pos, " %s", argv[i]);
-               if (ret < 0 || ret >= end - pos) {
+               if (os_snprintf_error(end - pos, ret)) {
                        printf("Too long PASSPHRASE command.\n");
                        return -1;
                }
@@ -1416,6 +1424,24 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
+                                  char *argv[])
+{
+       if (argc == 0) {
+               wpa_cli_show_network_variables();
+               return 0;
+       }
+
+       if (argc < 3) {
+               printf("Invalid DUP_NETWORK command: needs three arguments\n"
+                      "(src netid, dest netid, and variable name)\n");
+               return -1;
+       }
+
+       return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
+}
+
+
 static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
                                  char *argv[])
 {
@@ -1600,7 +1626,7 @@ static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
                          argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
                          argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
                          argc > 5 ? argv[5] : "");
-       if (res < 0 || (size_t) res >= sizeof(cmd))
+       if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -1726,6 +1752,31 @@ static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
+#ifdef CONFIG_MESH
+
+static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
+                                         char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
+                                        char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
+}
+
+#endif /* CONFIG_MESH */
+
+
 #ifdef CONFIG_P2P
 
 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
@@ -1889,7 +1940,7 @@ static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
 
        res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
                          argv[0], argv[1], argv[2], argv[3]);
-       if (res < 0 || (size_t) res >= sizeof(cmd))
+       if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -1937,7 +1988,7 @@ static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
                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))
+       if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -1964,7 +2015,7 @@ static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
                res = os_snprintf(cmd, sizeof(cmd),
                                  "P2P_SERVICE_DEL %s %s",
                                  argv[0], argv[1]);
-       if (res < 0 || (size_t) res >= sizeof(cmd))
+       if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -2186,7 +2237,7 @@ static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
 
        res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
                          argv[0], argc > 1 ? argv[1] : "");
-       if (res < 0 || (size_t) res >= sizeof(cmd))
+       if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -2207,7 +2258,7 @@ static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
 
        res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
                          argv[0]);
-       if (res < 0 || (size_t) res >= sizeof(cmd))
+       if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
        return wpa_ctrl_command(ctrl, cmd);
@@ -2354,6 +2405,41 @@ static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
+                                   char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
+                                   char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
+                                   char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
+}
+
+
+static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
+                                       char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
+                                              char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
+}
+
+
 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
@@ -2438,6 +2524,26 @@ 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);
+}
+
+
 enum wpa_cli_cmd_flags {
        cli_cmd_flag_none               = 0x00,
        cli_cmd_flag_sensitive          = 0x01
@@ -2501,6 +2607,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "pmksa", wpa_cli_cmd_pmksa, NULL,
          cli_cmd_flag_none,
          "= show PMKSA cache" },
+       { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
+         cli_cmd_flag_none,
+         "= flush PMKSA cache entries" },
        { "reassociate", wpa_cli_cmd_reassociate, NULL,
          cli_cmd_flag_none,
          "= force reassociation" },
@@ -2570,6 +2679,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "get_network", wpa_cli_cmd_get_network, NULL,
          cli_cmd_flag_none,
          "<network id> <variable> = get network variables" },
+       { "dup_network", wpa_cli_cmd_dup_network, NULL,
+         cli_cmd_flag_none,
+         "<src network id> <dst network id> <variable> = duplicate network variables"
+       },
        { "list_creds", wpa_cli_cmd_list_creds, NULL,
          cli_cmd_flag_none,
          "= list configured credentials" },
@@ -2748,6 +2861,17 @@ 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" },
+#ifdef CONFIG_MESH
+       { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
+         cli_cmd_flag_none,
+         "[ifname] = Create a new mesh interface" },
+       { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
+         cli_cmd_flag_none,
+         "<network id> = join a mesh network (disable others)" },
+       { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
+         cli_cmd_flag_none,
+         "<ifname> = Remove mesh group interface" },
+#endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
        { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
          cli_cmd_flag_none,
@@ -2888,6 +3012,25 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
          cli_cmd_flag_none,
          "<addr> = tear down TDLS with <addr>" },
+       { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
+         cli_cmd_flag_none,
+         "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
+         "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
+         "= add WMM-AC traffic stream" },
+       { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
+         cli_cmd_flag_none,
+         "<tsid> = delete WMM-AC traffic stream" },
+       { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
+         cli_cmd_flag_none,
+         "= show status for Wireless Multi-Media Admission-Control" },
+       { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
+         cli_cmd_flag_none,
+         "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
+         "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
+         "with TDLS peer" },
+       { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
+         cli_cmd_flag_none,
+         "<addr> = disable channel switching with TDLS peer <addr>" },
        { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
          cli_cmd_flag_none,
          "= get signal parameters" },
@@ -2920,6 +3063,18 @@ 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"
        },
+       { "neighbor_rep_request",
+         wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
+         "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
+         "(with optional given SSID, default: current SSID)"
+       },
+       { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
+         "= flush ERP keys" },
+       { "mac_rand_scan",
+         wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
+         "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
+         "mask=mac-address-mask] = scan MAC randomization"
+       },
        { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
@@ -3127,28 +3282,19 @@ static int str_match(const char *a, const char *b)
 static int wpa_cli_exec(const char *program, const char *arg1,
                        const char *arg2)
 {
-       char *cmd;
+       char *arg;
        size_t len;
        int res;
-       int ret = 0;
 
-       len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
-       cmd = os_malloc(len);
-       if (cmd == NULL)
-               return -1;
-       res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
-       if (res < 0 || (size_t) res >= len) {
-               os_free(cmd);
+       len = os_strlen(arg1) + os_strlen(arg2) + 2;
+       arg = os_malloc(len);
+       if (arg == NULL)
                return -1;
-       }
-       cmd[len - 1] = '\0';
-#ifndef _WIN32_WCE
-       if (system(cmd) < 0)
-               ret = -1;
-#endif /* _WIN32_WCE */
-       os_free(cmd);
+       os_snprintf(arg, len, "%s %s", arg1, arg2);
+       res = os_exec(program, arg, 1);
+       os_free(arg);
 
-       return ret;
+       return res;
 }
 
 
@@ -3156,15 +3302,29 @@ static void wpa_cli_action_process(const char *msg)
 {
        const char *pos;
        char *copy = NULL, *id, *pos2;
+       const char *ifname = ctrl_ifname;
+       char ifname_buf[100];
 
        pos = msg;
+       if (os_strncmp(pos, "IFNAME=", 7) == 0) {
+               const char *end;
+               end = os_strchr(pos + 7, ' ');
+               if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
+                       pos += 7;
+                       os_memcpy(ifname_buf, pos, end - pos);
+                       ifname_buf[end - pos] = '\0';
+                       ifname = ifname_buf;
+                       pos = end + 1;
+               }
+       }
        if (*pos == '<') {
+               const char *prev = pos;
                /* skip priority */
                pos = os_strchr(pos, '>');
                if (pos)
                        pos++;
                else
-                       pos = msg;
+                       pos = prev;
        }
 
        if (str_match(pos, WPA_EVENT_CONNECTED)) {
@@ -3201,37 +3361,45 @@ static void wpa_cli_action_process(const char *msg)
                if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
                        wpa_cli_connected = 1;
                        wpa_cli_last_id = new_id;
-                       wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
+                       wpa_cli_exec(action_file, ifname, "CONNECTED");
                }
        } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
                if (wpa_cli_connected) {
                        wpa_cli_connected = 0;
-                       wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
+                       wpa_cli_exec(action_file, ifname, "DISCONNECTED");
                }
-       } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+       } else if (str_match(pos, MESH_GROUP_STARTED)) {
                wpa_cli_exec(action_file, ctrl_ifname, pos);
-       } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+       } else if (str_match(pos, MESH_GROUP_REMOVED)) {
                wpa_cli_exec(action_file, ctrl_ifname, pos);
-       } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+       } else if (str_match(pos, MESH_PEER_CONNECTED)) {
                wpa_cli_exec(action_file, ctrl_ifname, pos);
-       } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+       } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
                wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+               wpa_cli_exec(action_file, ifname, pos);
+       } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+               wpa_cli_exec(action_file, ifname, pos);
+       } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+               wpa_cli_exec(action_file, ifname, pos);
+       } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, WPS_EVENT_FAIL)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, AP_STA_CONNECTED)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, AP_STA_DISCONNECTED)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
-               wpa_cli_exec(action_file, ctrl_ifname, pos);
+               wpa_cli_exec(action_file, ifname, pos);
        } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
                printf("wpa_supplicant is terminating - stop monitoring\n");
                wpa_cli_quit = 1;
@@ -3363,7 +3531,7 @@ static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
                return;
        }
        while (wpa_ctrl_pending(ctrl) > 0) {
-               char buf[256];
+               char buf[4096];
                size_t len = sizeof(buf) - 1;
                if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
                        buf[len] = '\0';
@@ -3427,10 +3595,18 @@ static int tokenize_cmd(char *cmd, char *argv[])
 
 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
 {
-       if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
-               printf("Connection to wpa_supplicant lost - trying to "
-                      "reconnect\n");
-               wpa_cli_close_connection();
+       if (ctrl_conn) {
+               int res;
+               char *prefix = ifname_prefix;
+
+               ifname_prefix = NULL;
+               res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
+               ifname_prefix = prefix;
+               if (res) {
+                       printf("Connection to wpa_supplicant lost - trying to "
+                              "reconnect\n");
+                       wpa_cli_close_connection();
+               }
        }
        if (!ctrl_conn)
                wpa_cli_reconnect();
@@ -3549,7 +3725,7 @@ static void update_ifnames(struct wpa_ctrl *ctrl)
                        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;
        }