old child_sa gets deleted after rekeying

rekeying almost complete, but:
	IKE_SA get in an invalid state when both initiate rekeying at the same time,
This commit is contained in:
Martin Willi
2006-06-09 15:12:43 +00:00
parent 2a13996de0
commit 695723d4e8
19 changed files with 586 additions and 102 deletions
+48 -28
View File
@@ -92,6 +92,11 @@ struct private_child_sa_t {
*/
u_int32_t hard_lifetime;
/**
* reqid of a CHILD_SA which rekeyed this one
*/
u_int32_t rekeyed;
/**
* CHILD_SAs own logger
*/
@@ -378,6 +383,14 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
return SUCCESS;
}
/**
* Implementation of child_sa_t.set_rekeyed.
*/
static void set_rekeyed(private_child_sa_t *this, u_int32_t reqid)
{
this->rekeyed = reqid;
}
/**
* Implementation of child_sa_t.log_status.
*/
@@ -428,42 +441,47 @@ static void log_status(private_child_sa_t *this, logger_t *logger, char* name)
*/
static void destroy(private_child_sa_t *this)
{
/* delete all policies in the kernel */
sa_policy_t *policy;
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
this->me.addr, this->other.addr,
policy->me.net, policy->other.net,
policy->me.net_mask, policy->other.net_mask,
XFRM_POLICY_OUT, policy->upper_proto);
charon->kernel_interface->del_policy(charon->kernel_interface,
this->other.addr, this->me.addr,
policy->other.net, policy->me.net,
policy->other.net_mask, policy->me.net_mask,
XFRM_POLICY_IN, policy->upper_proto);
charon->kernel_interface->del_policy(charon->kernel_interface,
this->other.addr, this->me.addr,
policy->other.net, policy->me.net,
policy->other.net_mask, policy->me.net_mask,
XFRM_POLICY_FWD, policy->upper_proto);
policy->me.net->destroy(policy->me.net);
policy->other.net->destroy(policy->other.net);
free(policy);
}
this->policies->destroy(this->policies);
/* delete SAs in the kernel, if they are set up */
if (this->protocol != PROTO_NONE)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
this->other.addr, this->me.spi, this->protocol);
this->me.addr, this->me.spi, this->protocol);
charon->kernel_interface->del_sa(charon->kernel_interface,
this->me.addr, this->other.spi, this->protocol);
this->other.addr, this->other.spi, this->protocol);
}
/* delete all policies in the kernel */
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
{
if (!this->rekeyed)
{
/* let rekeyed policies, as they are used by another child_sa */
charon->kernel_interface->del_policy(charon->kernel_interface,
this->me.addr, this->other.addr,
policy->me.net, policy->other.net,
policy->me.net_mask, policy->other.net_mask,
XFRM_POLICY_OUT, policy->upper_proto);
charon->kernel_interface->del_policy(charon->kernel_interface,
this->other.addr, this->me.addr,
policy->other.net, policy->me.net,
policy->other.net_mask, policy->me.net_mask,
XFRM_POLICY_IN, policy->upper_proto);
charon->kernel_interface->del_policy(charon->kernel_interface,
this->other.addr, this->me.addr,
policy->other.net, policy->me.net,
policy->other.net_mask, policy->me.net_mask,
XFRM_POLICY_FWD, policy->upper_proto);
}
policy->me.net->destroy(policy->me.net);
policy->other.net->destroy(policy->other.net);
free(policy);
}
this->policies->destroy(this->policies);
free(this);
}
@@ -483,6 +501,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, u_int32_t soft_lifetime,
this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
this->public.set_rekeyed = (void (*)(child_sa_t*,u_int32_t))set_rekeyed;
this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status;
this->public.destroy = (void(*)(child_sa_t*))destroy;
@@ -497,6 +516,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, u_int32_t soft_lifetime,
this->reqid = ++reqid;
this->policies = linked_list_create();
this->protocol = PROTO_NONE;
this->rekeyed = 0;
return (&this->public);
}
+12
View File
@@ -145,6 +145,18 @@ struct child_sa_t {
*/
status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list);
/**
* @brief Mark this child_sa as rekeyed.
*
* Since an SA which rekeys a old SA shares the same policy,
* we must mark a child_sa as rekeyed. A so marked SA does
* not remove its policy, as the new SA uses it.
*
* @param this calling object
* @param reqid reqid of the SA which replaces this one.
*/
void (*set_rekeyed) (child_sa_t *this, u_int32_t reqid);
/**
* @brief Log the status of a child_sa to a logger.
*
+93 -7
View File
@@ -42,6 +42,7 @@
#include <sa/states/initiator_init.h>
#include <sa/states/responder_init.h>
#include <sa/states/create_child_sa_requested.h>
#include <sa/states/delete_child_sa_requested.h>
#include <sa/states/delete_ike_sa_requested.h>
#include <queues/jobs/retransmit_request_job.h>
#include <queues/jobs/delete_established_ike_sa_job.h>
@@ -898,7 +899,92 @@ static child_sa_t *get_child_sa(private_ike_sa_t *this, u_int32_t reqid)
*/
static status_t delete_child_sa(private_ike_sa_t *this, u_int32_t reqid)
{
return NOT_FOUND;
message_t *request;
child_sa_t *child_sa;
delete_payload_t *delete_payload;
state_t *old_state;
if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED)
{
this->logger->log(this->logger, ERROR|LEVEL1,
"Delete of a CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting");
return FAILED;
}
child_sa = get_child_sa(this, reqid);
if (child_sa == NULL)
{
this->logger->log(this->logger, ERROR|LEVEL1,
"IKE_SA does not contain a CHILD_SA with reqid %d", reqid);
return FAILED;
}
build_message(this, INFORMATIONAL, TRUE, &request);
delete_payload = delete_payload_create(child_sa->get_protocol(child_sa));
delete_payload->add_spi(delete_payload, child_sa->get_spi(child_sa, FALSE));
request->add_payload(request, (payload_t*)delete_payload);
send_request(this, request);
old_state = this->current_state;
set_new_state(this, (state_t*)delete_child_sa_requested_create(&this->protected));
old_state->destroy(old_state);
return SUCCESS;
}
/**
* Implementation of protected_ike_sa_t.destroy_child_sa.
*/
static u_int32_t destroy_child_sa(private_ike_sa_t *this, u_int32_t spi)
{
iterator_t *iterator;
child_sa_t *child_sa;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&child_sa);
if (child_sa->get_spi(child_sa, TRUE) == spi)
{
iterator->remove(iterator);
break;
}
else
{
child_sa = NULL;
}
}
iterator->destroy(iterator);
if (child_sa == NULL)
{
this->logger->log(this->logger, ERROR,
"IKE_SA does not contain a CHILD_SA with spi 0x%x", spi);
return 0;
}
spi = child_sa->get_spi(child_sa, FALSE);
child_sa->destroy(child_sa);
return spi;
}
/**
* Implementation of protected_ike_sa_t.get_child_sa.
*/
static child_sa_t* get_child_sa_by_spi(private_ike_sa_t *this, u_int32_t spi)
{
iterator_t *iterator;
child_sa_t *current, *found = NULL;
iterator = this->child_sas->create_iterator(this->child_sas, FALSE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current);
if (current->get_spi(current, TRUE) == spi)
{
found = current;
}
}
iterator->destroy(iterator);
return found;
}
/**
@@ -920,7 +1006,7 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED)
{
this->logger->log(this->logger, ERROR|LEVEL1,
"Rekeying of an IKE_SA not in state IKE_SA_ESTABLISHED, aborting", reqid);
"Rekeying of an CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting");
return FAILED;
}
@@ -935,7 +1021,7 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
build_message(this, CREATE_CHILD_SA, TRUE, &request);
notify = notify_payload_create_from_protocol_and_type(
child_sa->get_protocol(child_sa), REKEY_SA);
notify->set_spi(notify, child_sa->get_spi(child_sa, TRUE));
notify->set_spi(notify, child_sa->get_spi(child_sa, FALSE));
request->add_payload(request, (payload_t*)notify);
proposals = this->policy->get_proposals(this->policy);
@@ -967,7 +1053,7 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
send_request(this, request);
old_state = this->current_state;
set_new_state(this, (state_t*)create_child_sa_requested_create(&this->protected, child_sa, nonce));
set_new_state(this, (state_t*)create_child_sa_requested_create(&this->protected, child_sa, nonce, reqid));
old_state->destroy(old_state);
return SUCCESS;
@@ -1074,8 +1160,7 @@ static status_t delete_(private_ike_sa_t *this)
build_message(this, INFORMATIONAL, TRUE, &informational_request);
/* delete for the full IKE_SA, this deletes all child_sa's implicit */
delete_payload = delete_payload_create();
delete_payload->set_protocol_id(delete_payload, PROTO_IKE);
delete_payload = delete_payload_create(PROTO_IKE);
informational_request->add_payload(informational_request, (payload_t*)delete_payload);
@@ -1241,8 +1326,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers;
this->protected.get_last_responded_message = (message_t * (*) (protected_ike_sa_t *)) get_last_responded_message;
this->protected.get_last_requested_message = (message_t * (*) (protected_ike_sa_t *)) get_last_requested_message;
this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id;
this->protected.destroy_child_sa = (u_int32_t (*)(protected_ike_sa_t*,u_int32_t))destroy_child_sa;
this->protected.get_child_sa = (child_sa_t* (*)(protected_ike_sa_t*,u_int32_t))get_child_sa_by_spi;
/* initialize private fields */
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
+18
View File
@@ -463,6 +463,24 @@ struct protected_ike_sa_t {
*/
void (*add_child_sa) (protected_ike_sa_t *this, child_sa_t *child_sa);
/**
* @brief Destroys a CHILD_SA upon request from the other peer.
*
* @param this calling object
* @param spi inbound spi of the CHILD_SA to destroy
* @return outbound spi of the destroyed CHILD_SA
*/
u_int32_t (*destroy_child_sa) (protected_ike_sa_t *this, u_int32_t spi);
/**
* @brief Get a CHILD_SA upon request from the other peer.
*
* @param this calling object
* @param spi spi of the CHILD_SA
* @return child_sa, or NULL if none found
*/
child_sa_t* (*get_child_sa) (protected_ike_sa_t *this, u_int32_t spi);
/**
* @brief Get the last responded message.
*
@@ -85,6 +85,11 @@ struct private_create_child_sa_requested_t {
*/
child_sa_t *child_sa;
/**
* Reqid of the old CHILD_SA, when rekeying
*/
u_int32_t reqid;
/**
* Assigned logger.
*
@@ -205,6 +210,7 @@ static status_t process_message(private_create_child_sa_requested_t *this, messa
status_t status;
chunk_t seed;
prf_plus_t *prf_plus;
child_sa_t *old_child_sa;
this->policy = this->ike_sa->get_policy(this->ike_sa);
if (response->get_exchange_type(response) != CREATE_CHILD_SA)
@@ -339,7 +345,7 @@ static status_t process_message(private_create_child_sa_requested_t *this, messa
memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
this->logger->log_chunk(this->logger, CONTROL, "Seed", seed);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "Rekey seed", seed);
chunk_free(&seed);
status = this->child_sa->update(this->child_sa, this->proposal, prf_plus);
@@ -364,6 +370,17 @@ static status_t process_message(private_create_child_sa_requested_t *this, messa
this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
this->public.state_interface.destroy(&this->public.state_interface);
/* if we are rekeying, inform the old child SA that it has been superseeded and
* start its delete */
if (this->reqid)
{
old_child_sa = this->ike_sa->public.get_child_sa(&this->ike_sa->public, this->reqid);
if (old_child_sa)
{
old_child_sa->set_rekeyed(old_child_sa, this->child_sa->get_reqid(this->child_sa));
}
this->ike_sa->public.delete_child_sa(&this->ike_sa->public, this->reqid);
}
return SUCCESS;
}
@@ -388,7 +405,7 @@ static void destroy(private_create_child_sa_requested_t *this)
/*
* Described in header.
*/
create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i)
create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i, u_int32_t reqid)
{
private_create_child_sa_requested_t *this = malloc_thing(private_create_child_sa_requested_t);
@@ -402,6 +419,7 @@ create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t
this->child_sa = child_sa;
this->nonce_i = nonce_i;
this->nonce_r = CHUNK_INITIALIZER;
this->reqid = reqid;
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
return &(this->public);
@@ -47,13 +47,18 @@ struct create_child_sa_requested_t {
/**
* @brief Constructor of class create_child_sa_requested_t
*
* If this CREATE_CHILD_SA message is to rekey a CHILD_SA,
* the child_sa with the specified reqid gets deleted after a new
* one is set up.
*
* @param ike_sa assigned ike_sa
* @param child_sa newly created child sa to complete
* @param nonce nonce sent at initialization
* @param reqid reqid, when rekeying a child SA.
* @return created create_child_sa_requested_t object
*
* @ingroup states
*/
create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i);
create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i, u_int32_t reqid);
#endif /*CREATE_CHILD_SA_REQEUSTED_H_*/
@@ -0,0 +1,177 @@
/**
* @file delete_child_sa_requested.c
*
* @brief State after a CREATE_CHILD_SA request was sent.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <string.h>
#include "delete_child_sa_requested.h"
#include <sa/child_sa.h>
#include <sa/states/delete_ike_sa_requested.h>
#include <sa/states/ike_sa_established.h>
#include <encoding/payloads/notify_payload.h>
#include <encoding/payloads/delete_payload.h>
#include <utils/logger_manager.h>
typedef struct private_delete_child_sa_requested_t private_delete_child_sa_requested_t;
/**
* Private data of a delete_child_sa_requested_t object.
*/
struct private_delete_child_sa_requested_t {
/**
* Public interface of delete_child_sa_requested_t.
*/
delete_child_sa_requested_t public;
/**
* Assigned IKE_SA.
*/
protected_ike_sa_t *ike_sa;
/**
* Assigned logger.
*
* Is logger of ike_sa!
*/
logger_t *logger;
};
/**
* Process the response
*/
static status_t process_message(private_delete_child_sa_requested_t *this, message_t *response)
{
ike_sa_id_t *ike_sa_id;
crypter_t *crypter;
signer_t *signer;
status_t status;
iterator_t *iterator;
payload_t *payload;
delete_payload_t *delete_response;
if (response->get_exchange_type(response) != INFORMATIONAL)
{
this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state delete_child_sa_requested",
mapping_find(exchange_type_m, response->get_exchange_type(response)));
return FAILED;
}
if (response->get_request(response))
{
this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL requests not allowed state delete_child_sa_requested");
return FAILED;
}
/* get signer for verification and crypter for decryption */
ike_sa_id = this->ike_sa->public.get_id(&this->ike_sa->public);
if (!ike_sa_id->is_initiator(ike_sa_id))
{
crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
signer = this->ike_sa->get_signer_initiator(this->ike_sa);
}
else
{
crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
signer = this->ike_sa->get_signer_responder(this->ike_sa);
}
/* parse incoming message */
status = response->parse_body(response, crypter, signer);
if (status != SUCCESS)
{
this->logger->log(this->logger, AUDIT, "INFORMATIONAL response decryption failed. Ignoring message");
return status;
}
iterator = response->get_payload_iterator(response);
while (iterator->has_next(iterator)) {
iterator->current(iterator, (void**)&payload);
switch (payload->get_type(payload))
{
case DELETE:
delete_response = (delete_payload_t*)payload;
break;
default:
break;
}
}
iterator->destroy(iterator);
if (delete_response)
{
iterator = delete_response->create_spi_iterator(delete_response);
while (iterator->has_next(iterator))
{
u_int32_t spi;
iterator->current(iterator, (void**)&spi);
this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA with SPI 0x%x received", spi);
this->ike_sa->destroy_child_sa(this->ike_sa, spi);
}
iterator->destroy(iterator);
}
this->ike_sa->set_last_replied_message_id(this->ike_sa, response->get_message_id(response));
/* create new state */
this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
this->public.state_interface.destroy(&this->public.state_interface);
return SUCCESS;
}
/**
* Implements state_t.get_state
*/
static ike_sa_state_t get_state(private_delete_child_sa_requested_t *this)
{
return DELETE_CHILD_SA_REQUESTED;
}
/**
* Implementation of state_t.destroy.
*/
static void destroy(private_delete_child_sa_requested_t *this)
{
free(this);
}
/*
* Described in header.
*/
delete_child_sa_requested_t *delete_child_sa_requested_create(protected_ike_sa_t *ike_sa)
{
private_delete_child_sa_requested_t *this = malloc_thing(private_delete_child_sa_requested_t);
/* interface functions */
this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
this->public.state_interface.destroy = (void (*) (state_t *)) destroy;
/* private data */
this->ike_sa = ike_sa;
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
return &(this->public);
}
@@ -0,0 +1,57 @@
/**
* @file delete_child_sa_requested.h
*
* @brief Interface of delete_child_sa_requested_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef DELETE_CHILD_SA_REQEUSTED_H_
#define DELETE_CHILD_SA_REQEUSTED_H_
#include <sa/states/state.h>
#include <sa/ike_sa.h>
#include <sa/child_sa.h>
typedef struct delete_child_sa_requested_t delete_child_sa_requested_t;
/**
* @brief State after a CREATE_CHILD_SA request was sent.
*
* @b Constructors:
* - delete_child_sa_requested_create()
*
* @ingroup states
*/
struct delete_child_sa_requested_t {
/**
* methods of the state_t interface
*/
state_t state_interface;
};
/**
* @brief Constructor of class delete_child_sa_requested_t
*
* @param ike_sa assigned ike_sa
* @return created delete_child_sa_requested_t object
*
* @ingroup states
*/
delete_child_sa_requested_t *delete_child_sa_requested_create(protected_ike_sa_t *ike_sa);
#endif /*DELETE_CHILD_SA_REQEUSTED_H_*/
+31 -5
View File
@@ -125,7 +125,7 @@ static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_
memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
this->logger->log_chunk(this->logger, CONTROL, "Seed", seed);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "Rekey seed", seed);
chunk_free(&seed);
policy = this->ike_sa->get_policy(this->ike_sa);
@@ -240,8 +240,10 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess
ts_payload_t *tsi_request = NULL, *tsr_request = NULL;
sa_payload_t *sa_request = NULL;
nonce_payload_t *nonce_request = NULL;
notify_payload_t *notify = NULL;
iterator_t *payloads;
status_t status;
child_sa_t *old_child_sa;
/* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
payloads = request->get_payload_iterator(request);
@@ -260,7 +262,7 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess
case TRAFFIC_SELECTOR_INITIATOR:
{
tsi_request = (ts_payload_t*)payload;
break;
break;
}
case TRAFFIC_SELECTOR_RESPONDER:
{
@@ -274,7 +276,7 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess
}
case NOTIFY:
{
/* TODO: handle notifys */
notify = (notify_payload_t*)payload;
break;
}
default:
@@ -351,6 +353,16 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess
{
this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy!");
}
if (notify && notify->get_notify_message_type(notify) == REKEY_SA)
{
/* mark old child sa as rekeyed */
old_child_sa = this->ike_sa->get_child_sa(this->ike_sa, notify->get_spi(notify));
if (old_child_sa)
{
old_child_sa->set_rekeyed(old_child_sa, this->child_sa->get_reqid(this->child_sa));
}
}
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
}
@@ -403,8 +415,22 @@ static status_t process_informational(private_ike_sa_established_t *this, messag
}
else
{
this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA received. Ignored");
return SUCCESS;
iterator_t *iterator;
delete_payload_t *delete_response = delete_payload_create(delete_request->get_protocol_id(delete_request));
iterator = delete_request->create_spi_iterator(delete_request);
while (iterator->has_next(iterator))
{
u_int32_t spi;
iterator->current(iterator, (void**)&spi);
this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA with SPI 0x%x received", spi);
spi = this->ike_sa->destroy_child_sa(this->ike_sa, spi);
if (spi)
{
delete_response->add_spi(delete_response, spi);
}
}
iterator->destroy(iterator);
response->add_payload(response, (payload_t*)delete_response);
}
}