mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 18:01:23 +00:00
403 lines
13 KiB
Diff
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;
|