diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6be938582..cc75514a0 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2727,6 +2727,18 @@ static int wpa_supplicant_ctrl_iface_mesh_group_remove( return 0; } + +static int wpa_supplicant_ctrl_iface_mesh_peer_remove( + struct wpa_supplicant *wpa_s, char *cmd) +{ + u8 addr[ETH_ALEN]; + + if (hwaddr_aton(cmd, addr) < 0) + return -1; + + return wpas_mesh_peer_remove(wpa_s, addr); +} + #endif /* CONFIG_MESH */ @@ -8572,6 +8584,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s, buf + 18)) reply_len = -1; + } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) { + if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17)) + reply_len = -1; #endif /* CONFIG_MESH */ #ifdef CONFIG_P2P } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 7925aa91a..c6d1d7366 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -597,3 +597,9 @@ int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname, mesh_wpa_s->mesh_if_created = 1; return 0; } + + +int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr) +{ + return mesh_mpm_close_peer(wpa_s, addr); +} diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h index 3cb7f1b13..31b9f0787 100644 --- a/wpa_supplicant/mesh.h +++ b/wpa_supplicant/mesh.h @@ -18,6 +18,7 @@ int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end); int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname, size_t len); +int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr); #ifdef CONFIG_MESH diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 27be46cd1..a3b17c494 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -472,8 +472,8 @@ mesh_mpm_plink_open(struct wpa_supplicant *wpa_s, struct sta_info *sta, } -int mesh_mpm_plink_close(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) +static int mesh_mpm_plink_close(struct hostapd_data *hapd, struct sta_info *sta, + void *ctx) { struct wpa_supplicant *wpa_s = ctx; int reason = WLAN_REASON_MESH_PEERING_CANCELLED; @@ -491,6 +491,27 @@ int mesh_mpm_plink_close(struct hostapd_data *hapd, } +int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr) +{ + struct hostapd_data *hapd; + struct sta_info *sta; + + if (!wpa_s->ifmsh) { + wpa_msg(wpa_s, MSG_INFO, "Mesh is not prepared yet"); + return -1; + } + + hapd = wpa_s->ifmsh->bss[0]; + sta = ap_get_sta(hapd, addr); + if (!sta) { + wpa_msg(wpa_s, MSG_INFO, "No such mesh peer"); + return -1; + } + + return mesh_mpm_plink_close(hapd, sta, wpa_s) == 0 ? 0 : -1; +} + + void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh) { struct hostapd_data *hapd = ifmsh->bss[0]; diff --git a/wpa_supplicant/mesh_mpm.h b/wpa_supplicant/mesh_mpm.h index 9af756356..71880869a 100644 --- a/wpa_supplicant/mesh_mpm.h +++ b/wpa_supplicant/mesh_mpm.h @@ -18,6 +18,7 @@ void mesh_mpm_free_sta(struct hostapd_data *hapd, struct sta_info *sta); void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s, struct sta_info *sta, enum mesh_plink_state state); +int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr); #ifdef CONFIG_MESH diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index eecb1dca7..e681d8225 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -2042,6 +2042,13 @@ static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc, 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); +} + #endif /* CONFIG_MESH */ @@ -3210,6 +3217,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL, cli_cmd_flag_none, " = Remove mesh group interface" }, + { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL, + cli_cmd_flag_none, + " = Remove a mesh peer" }, #endif /* CONFIG_MESH */ #ifdef CONFIG_P2P { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,