From 0d4a5f6af6be7920c775d7d294af0767910cbf7b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 19 Mar 2020 13:39:48 +0100 Subject: [PATCH] ike: Add an option to trigger a DPD instead of a NAT keepalive This is useful on Android where the app might not be able to send keep-alives if the device is asleep for a while. If the NAT mapping has been deleted in the mean time, the NAT-D payloads allow detecting this and connectivity can be restored by doing a MOBIKE update or recreating the SA if the peer already deleted it because the client wasn't reachable. --- conf/options/charon.opt | 5 +++++ src/libcharon/sa/ike_sa.c | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/conf/options/charon.opt b/conf/options/charon.opt index fd2d36a0b..b6e55e112 100644 --- a/conf/options/charon.opt +++ b/conf/options/charon.opt @@ -220,6 +220,11 @@ charon.interfaces_use charon.keep_alive = 20s NAT keep alive interval. +charon.keep_alive_dpd_margin = 0s + Number of seconds the keep alive interval may be exceeded before a DPD is + sent instead of a NAT keep alive (0 to disable). This is only useful if a + clock is used that includes time spent suspended (e.g. CLOCK_BOOTTIME). + charon.leak_detective.detailed = yes Includes source file names and line numbers in leak detective output. diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index b44c157d9..5e54208ec 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -236,6 +236,12 @@ struct private_ike_sa_t { */ uint32_t keepalive_interval; + /** + * Time the NAT keep alive interval may be exceeded before triggering a DPD + * instead of a NAT keep alive + */ + uint32_t keepalive_dpd_margin; + /** * The scheduled keep alive job, if any */ @@ -655,7 +661,19 @@ METHOD(ike_sa_t, send_keepalive, void, diff = now - last_out; - if (diff >= this->keepalive_interval) + if (this->keepalive_dpd_margin && + diff > (this->keepalive_interval + this->keepalive_dpd_margin)) + { + if (!this->task_manager->busy(this->task_manager)) + { + DBG1(DBG_IKE, "sending DPD instead of keep alive %ds after last " + "outbound message", diff); + this->task_manager->queue_dpd(this->task_manager); + this->task_manager->initiate(this->task_manager); + } + diff = 0; + } + else if (diff >= this->keepalive_interval) { packet_t *packet; chunk_t data; @@ -3183,6 +3201,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, .unique_id = ref_get(&unique_id), .keepalive_interval = lib->settings->get_time(lib->settings, "%s.keep_alive", KEEPALIVE_INTERVAL, lib->ns), + .keepalive_dpd_margin = lib->settings->get_time(lib->settings, + "%s.keep_alive_dpd_margin", 0, lib->ns), .retry_initiate_interval = lib->settings->get_time(lib->settings, "%s.retry_initiate_interval", 0, lib->ns), .flush_auth_cfg = lib->settings->get_bool(lib->settings,