From d24b831fe7def230cc604a2a2bf3f1a05a523c23 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 11 Jul 2017 14:05:01 +0200 Subject: [PATCH] charon-tkm: Don't select new outbound SA until the policy is installed This tries to avoid packet loss during rekeying by delaying the usage of the new outbound IKE_SA until the old one is deleted. Note that esa_select() is a no-op in the current TKM implementation. And the implementation also doesn't benefit from the delayed deletion of the inbound SA as it calls esa_reset() when the outbound SA is deleted. --- src/charon-tkm/src/tkm/tkm_kernel_ipsec.c | 62 +++++++++++++++-------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 9229c3d67c..8ccae4cc22 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -1,7 +1,8 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2012-2014 Reto Buerki * Copyright (C) 2012 Adrian-Ken Rueegsegger - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -182,15 +183,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, tkm->chunk_map->remove(tkm->chunk_map, nonce_loc); tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id); } - if (ike_esa_select(esa_id) != TKM_OK) - { - DBG1(DBG_KNL, "error selecting new child SA (%llu)", esa_id); - if (ike_esa_reset(esa_id) != TKM_OK) - { - DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id); - } - goto failure; - } DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, " "esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc), @@ -221,23 +213,12 @@ METHOD(kernel_ipsec_t, del_sa, status_t, private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id, kernel_ipsec_del_sa_t *data) { - esa_id_type esa_id, other_esa_id; + esa_id_type esa_id; esa_id = tkm->sad->get_esa_id(tkm->sad, id->src, id->dst, id->spi, id->proto); if (esa_id) { - other_esa_id = tkm->sad->get_other_esa_id(tkm->sad, esa_id); - if (other_esa_id) - { - DBG1(DBG_KNL, "selecting child SA (esa: %llu)", other_esa_id); - if (ike_esa_select(other_esa_id) != TKM_OK) - { - DBG1(DBG_KNL, "error selecting other child SA (esa: %llu)", - other_esa_id); - } - } - DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id, ntohl(id->spi)); if (ike_esa_reset(esa_id) != TKM_OK) @@ -269,6 +250,43 @@ METHOD(kernel_ipsec_t, add_policy, status_t, private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id, kernel_ipsec_manage_policy_t *data) { + esa_id_type esa_id; + uint32_t spi; + uint8_t proto; + + if (id->dir == POLICY_OUT && data->type == POLICY_IPSEC && + data->prio == POLICY_PRIORITY_DEFAULT) + { + if (data->sa->esp.use) + { + spi = data->sa->esp.spi; + proto = IPPROTO_ESP; + } + else if (data->sa->ah.use) + { + spi = data->sa->ah.spi; + proto = IPPROTO_AH; + } + else + { + return FAILED; + } + esa_id = tkm->sad->get_esa_id(tkm->sad, data->src, data->dst, + spi, proto); + if (!esa_id) + { + DBG1(DBG_KNL, "unable to find esa ID for policy (spi: %x)", + ntohl(spi)); + return FAILED; + } + DBG1(DBG_KNL, "selecting child SA (esa: %llu, spi: %x)", esa_id, + ntohl(spi)); + if (ike_esa_select(esa_id) != TKM_OK) + { + DBG1(DBG_KNL, "error selecting new child SA (%llu)", esa_id); + return FAILED; + } + } return SUCCESS; } -- 2.47.2