wlan-ap-Telecominfraproject/feeds/wifi-ax/hostapd/patches/a00-108-supplicant-tdls-peer-inactivity.patch
John Crispin 04f6078da6 ipq807x: update AX support
Signed-off-by: John Crispin <john@phrozen.org>
2020-10-04 14:28:57 +02:00

403 lines
13 KiB
Diff

--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1934,6 +1934,7 @@ struct wpa_driver_capa {
/** Driver supports Extended Key ID */
#define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID 0x8000000000000000ULL
u64 flags;
+#define WPA_DRIVER_FLAGS_TDLS_INACTIVITY_TIMER 0x0000040000000000ULL
/** Driver supports a separate control port RX for EAPOL frames */
#define WPA_DRIVER_FLAGS2_CONTROL_PORT_RX 0x0000000000000001ULL
@@ -4402,6 +4403,16 @@ struct wpa_driver_ops {
const u8 *bssid);
/**
+ * get_peer_inactive_time - Get peer inactive time
+ * @priv: Private driver interface data
+ * @addr: MAC address of the peer
+ *
+ * Get the peer inactive time in seconds, for now used only for
+ * TDLS peers.
+ */
+ int (*get_peer_inactive_time)(void *priv, const u8 *addr);
+
+ /**
* update_connect_params - Update the connection parameters
* @priv: Private driver interface data
* @params: Association parameters
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -11797,6 +11797,7 @@ const struct wpa_driver_ops wpa_driver_n
#endif /* CONFIG_DRIVER_NL80211_QCA */
.configure_data_frame_filters = nl80211_configure_data_frame_filters,
.get_ext_capab = nl80211_get_ext_capab,
+ .get_peer_inactive_time = i802_get_inact_sec,
.update_connect_params = nl80211_update_connection_params,
.send_external_auth_status = nl80211_send_external_auth_status,
.set_4addr_mode = nl80211_set_4addr_mode,
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -723,12 +723,12 @@ static void wpa_tdls_peer_clear(struct w
static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
{
+ eloop_cancel_timeout(wpa_tdls_peer_inactivity_handler, sm, peer);
wpa_tdls_peer_clear(sm, peer);
wpa_tdls_peer_remove_from_list(sm, peer);
os_free(peer);
}
-
static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
struct wpa_tdls_lnkid *lnkid)
{
@@ -1782,7 +1782,6 @@ static int tdls_nonce_set(const u8 *nonc
return 0;
}
-
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
@@ -2143,9 +2142,68 @@ error:
return -1;
}
+void wpa_tdls_peer_inactivity_handler(void *eloop_data, void *user_data)
+{
+ struct wpa_sm *sm = eloop_data;
+ struct wpa_tdls_peer *peer = user_data;
+ int inactive_time = 0;
+ unsigned long next_time = 0;
+ u8 teardown = 0;
+
+ if (peer->tpk_in_progress)
+ return;
+
+ inactive_time = wpa_sm_tdls_get_peer_inactive_time(sm,
+ peer->addr);
+
+ if (inactive_time == -1) {
+ wpa_printf(MSG_DEBUG, "TDLS: failed to get station info "
+ "for " MACSTR, MAC2STR(peer->addr));
+
+ next_time = sm->tdls_peer_max_inactive_time;
+ } else if (inactive_time == -ENOENT) {
+ wpa_printf(MSG_DEBUG, "TDLS: failed to find kernel entry for "
+ "peer " MACSTR ", teardown the link",
+ MAC2STR(peer->addr));
+
+ teardown = 1;
+ } else if (inactive_time < sm->tdls_peer_max_inactive_time) {
+ wpa_printf(MSG_DEBUG, "TDLS: peer " MACSTR " has been inactive "
+ "for %d seconds", MAC2STR(peer->addr), inactive_time);
+
+ next_time = sm->tdls_peer_max_inactive_time - inactive_time;
+ } else {
+ wpa_printf(MSG_DEBUG, "TDLS: peer " MACSTR " has been inactive "
+ "for long time: %d seconds, max inactive time: %d seconds",
+ MAC2STR(peer->addr), inactive_time,
+ sm->tdls_peer_max_inactive_time);
+
+ teardown = 1;
+ }
+
+ if (teardown) {
+ wpa_printf(MSG_DEBUG, "TDLS: tearing down TDLS link with peer "
+ MACSTR " (due to inactivity)", MAC2STR(peer->addr));
+
+ wpa_tdls_do_teardown(sm, peer,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+ return;
+ }
+
+ if (next_time) {
+ wpa_printf(MSG_DEBUG, "TDLS: reschedule inactivity timer for "
+ "peer " MACSTR " (%lu seconds)", MAC2STR(peer->addr),
+ next_time);
+
+ eloop_register_timeout(next_time, 0, wpa_tdls_peer_inactivity_handler,
+ sm, peer);
+ }
+}
static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
{
+ int ret;
+
peer->tpk_success = 1;
peer->tpk_in_progress = 0;
eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
@@ -2175,7 +2233,23 @@ static int wpa_tdls_enable_link(struct w
}
peer->reconfig_key = 0;
- return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
+ ret = wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
+
+ /* Do not trigger supplicant inactivity logic if driver
+ * already supports it
+ */
+ if (!ret && !sm->tdls_inactivity_teardown &&
+ (sm->tdls_peer_max_inactive_time > 0)) {
+ wpa_printf(MSG_DEBUG, "TDLS: register inactivity handler for "
+ "peer "MACSTR " (%d seconds)", MAC2STR(peer->addr),
+ sm->tdls_peer_max_inactive_time);
+
+ eloop_register_timeout(sm->tdls_peer_max_inactive_time,
+ 0, wpa_tdls_peer_inactivity_handler,
+ sm, peer);
+ }
+
+ return ret;
}
@@ -2824,9 +2898,12 @@ int wpa_tdls_init(struct wpa_sm *sm)
*/
if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
&sm->tdls_external_setup,
- &sm->tdls_chan_switch) < 0) {
+ &sm->tdls_chan_switch,
+ &sm->tdls_inactivity_teardown,
+ &sm->tdls_peer_max_inactive_time) < 0) {
sm->tdls_supported = 1;
sm->tdls_external_setup = 0;
+ sm->tdls_inactivity_teardown = 1;
}
wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
@@ -2835,6 +2912,8 @@ int wpa_tdls_init(struct wpa_sm *sm)
sm->tdls_external_setup ? "external" : "internal");
wpa_printf(MSG_DEBUG, "TDLS: Driver %s TDLS channel switching",
sm->tdls_chan_switch ? "supports" : "does not support");
+ wpa_printf(MSG_DEBUG, "TDLS: Driver %s TDLS peer inactivity teardown",
+ sm->tdls_inactivity_teardown ? "supports" : "does not support");
return 0;
}
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -58,7 +58,8 @@ struct wpa_sm_ctx {
int (*mark_authenticated)(void *ctx, const u8 *target_ap);
#ifdef CONFIG_TDLS
int (*tdls_get_capa)(void *ctx, int *tdls_supported,
- int *tdls_ext_setup, int *tdls_chan_switch);
+ int *tdls_ext_setup, int *tdls_chan_switch,
+ int *tdls_inact_teardown, int *tdls_inact_timeout);
int (*send_tdls_mgmt)(void *ctx, const u8 *dst,
u8 action_code, u8 dialog_token,
u16 status_code, u32 peer_capab,
@@ -78,6 +79,7 @@ struct wpa_sm_ctx {
void *ctx, const u8 *addr, u8 oper_class,
const struct hostapd_freq_params *params);
int (*tdls_disable_channel_switch)(void *ctx, const u8 *addr);
+ int (*tdls_get_peer_inact_time)(void *ctx, const u8 *addr);
#endif /* CONFIG_TDLS */
void (*set_rekey_offload)(void *ctx, const u8 *kek, size_t kek_len,
const u8 *kck, size_t kck_len,
@@ -476,6 +478,7 @@ int wpa_tdls_enable_chan_switch(struct w
u8 oper_class,
struct hostapd_freq_params *freq_params);
int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr);
+void wpa_tdls_peer_inactivity_handler(void *eloop_data, void *user_data);
#ifdef CONFIG_TDLS_TESTING
extern unsigned int tdls_testing;
#endif /* CONFIG_TDLS_TESTING */
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -121,6 +121,12 @@ struct wpa_sm {
/* The driver supports TDLS channel switching */
int tdls_chan_switch;
+
+ /* Driver supports TDLS peer inactivity teardown */
+ int tdls_inactivity_teardown;
+
+ /* Supplicant TDLS inactivity logic uses this timeout */
+ int tdls_peer_max_inactive_time;
#endif /* CONFIG_TDLS */
#ifdef CONFIG_IEEE80211R
@@ -333,11 +339,15 @@ static inline void wpa_sm_set_rekey_offl
static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm,
int *tdls_supported,
int *tdls_ext_setup,
- int *tdls_chan_switch)
+ int *tdls_chan_switch,
+ int *tdls_inact_teardown,
+ int *tdls_inact_timeout)
{
if (sm->ctx->tdls_get_capa)
return sm->ctx->tdls_get_capa(sm->ctx->ctx, tdls_supported,
- tdls_ext_setup, tdls_chan_switch);
+ tdls_ext_setup, tdls_chan_switch,
+ tdls_inact_teardown,
+ tdls_inact_timeout);
return -1;
}
@@ -406,6 +416,14 @@ wpa_sm_tdls_disable_channel_switch(struc
return sm->ctx->tdls_disable_channel_switch(sm->ctx->ctx, addr);
return -1;
}
+
+static inline int
+wpa_sm_tdls_get_peer_inactive_time(struct wpa_sm *sm, const u8 *addr)
+{
+ if (sm->ctx->tdls_get_peer_inact_time)
+ return sm->ctx->tdls_get_peer_inact_time(sm->ctx->ctx, addr);
+ return -1;
+}
#endif /* CONFIG_TDLS */
static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm,
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -4492,6 +4492,8 @@ struct wpa_config * wpa_config_alloc_emp
config->driver_param = os_strdup(driver_param);
config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
+ config->tdls_peer_max_inactivity = DEFAULT_TDLS_PEER_MAX_INACTIVITY;
+
return config;
}
@@ -5240,6 +5242,7 @@ static const struct global_parse_data gl
{ STR(dpp_mud_url), 0 },
#endif /* CONFIG_DPP */
{ INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
+ { INT(tdls_peer_max_inactivity), 0 },
#ifdef CONFIG_WNM
{ INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
{ INT_RANGE(extended_key_id, 0, 1), 0 },
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -44,6 +44,7 @@
#define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED
#define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
#define DEFAULT_OCE_SUPPORT OCE_STA
+#define DEFAULT_TDLS_PEER_MAX_INACTIVITY 300
#define DEFAULT_EXTENDED_KEY_ID 0
#include "config_ssid.h"
@@ -1536,6 +1537,15 @@ struct wpa_config {
int coloc_intf_reporting;
/**
+ * tdls_peer_max_inactivity - Timeout to detect TDLS peer inactivity
+ *
+ * Time duration in seconds to detect TDLS peer inactivity and clean up
+ * of inactive TDLS peers.
+ * Default Value: 300 seconds.
+ */
+ int tdls_peer_max_inactivity;
+
+ /**
* p2p_device_random_mac_addr - P2P Device MAC address policy default
*
* 0 = use permanent MAC address
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1591,6 +1591,9 @@ static void wpa_config_write_global(FILE
if (config->coloc_intf_reporting)
fprintf(f, "coloc_intf_reporting=%d\n",
config->coloc_intf_reporting);
+ if (config->tdls_peer_max_inactivity != DEFAULT_TDLS_PEER_MAX_INACTIVITY)
+ fprintf(f, "tdls_peer_max_inactivity=%d\n",
+ config->tdls_peer_max_inactivity);
if (config->p2p_device_random_mac_addr)
fprintf(f, "p2p_device_random_mac_addr=%d\n",
config->p2p_device_random_mac_addr);
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -1115,4 +1115,12 @@ static inline int wpa_drv_dpp_listen(str
return wpa_s->driver->dpp_listen(wpa_s->drv_priv, enable);
}
+static inline int wpa_drv_get_inactive_time(struct wpa_supplicant *wpa_s,
+ const u8 *addr)
+{
+ if (!wpa_s->driver->get_peer_inactive_time)
+ return -1;
+ return wpa_s->driver->get_peer_inactive_time(wpa_s->drv_priv, addr);
+}
+
#endif /* DRIVER_I_H */
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1646,6 +1646,18 @@ fast_reauth=1
# In STA mode it defines the EDMG channel for connection (if supported by AP).
#edmg_channel=9
+# Inactivity limit for TDLS peers
+#
+# If a TDLS peer is inactive for tdls_peer_max_inactivity seconds,
+# the direct link with that TDLS peer will be terminated. This does
+# not break the communication between the peers, they can still
+# communicate through the AP, only the direct link will be torn down.
+#
+# When teardown happens, the STA entries of the TDLS peers will be
+# flushed out so that the TDLS link can be re-established if required.
+# default: 300 seconds
+#tdls_peer_max_inactivity=300
+
# Example blocks:
# Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -728,13 +728,17 @@ static int wpa_supplicant_mark_authentic
static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported,
int *tdls_ext_setup,
- int *tdls_chan_switch)
+ int *tdls_chan_switch,
+ int *tdls_inact_teardown,
+ int *tdls_inact_timeout)
{
struct wpa_supplicant *wpa_s = ctx;
*tdls_supported = 0;
*tdls_ext_setup = 0;
*tdls_chan_switch = 0;
+ *tdls_inact_teardown = 0;
+ *tdls_inact_timeout = 0;
if (!wpa_s->drv_capa_known)
return -1;
@@ -748,6 +752,11 @@ static int wpa_supplicant_tdls_get_capa(
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH)
*tdls_chan_switch = 1;
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_INACTIVITY_TIMER)
+ *tdls_inact_teardown = 1;
+
+ *tdls_inact_timeout = wpa_s->conf->tdls_peer_max_inactivity;
+
return 0;
}
@@ -834,6 +843,13 @@ static int wpa_supplicant_tdls_disable_c
return wpa_drv_tdls_disable_channel_switch(wpa_s, addr);
}
+static int wpa_supplicant_tdls_get_peer_inact_time(void *ctx, const u8 *addr)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ return wpa_drv_get_inactive_time(wpa_s, addr);
+}
+
#endif /* CONFIG_TDLS */
#endif /* CONFIG_NO_WPA */
@@ -1388,6 +1404,7 @@ int wpa_supplicant_init_wpa(struct wpa_s
wpa_supplicant_tdls_enable_channel_switch;
ctx->tdls_disable_channel_switch =
wpa_supplicant_tdls_disable_channel_switch;
+ ctx->tdls_get_peer_inact_time = wpa_supplicant_tdls_get_peer_inact_time;
#endif /* CONFIG_TDLS */
ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;