child-delete: Check if the deleted CHILD_SA is the redundant SA of a collision
This happens if the peer deletes the redundant SA before we are able to handle the response. The deleted SA will be in state CHILD_INSTALLED but we don't want to trigger the child_updown() event for it or recreate it.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2009-2016 Tobias Brunner
|
||||||
* Copyright (C) 2006-2007 Martin Willi
|
* Copyright (C) 2006-2007 Martin Willi
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -18,7 +19,7 @@
|
|||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <encoding/payloads/delete_payload.h>
|
#include <encoding/payloads/delete_payload.h>
|
||||||
#include <sa/ikev2/tasks/child_create.h>
|
#include <sa/ikev2/tasks/child_create.h>
|
||||||
|
#include <sa/ikev2/tasks/child_rekey.h>
|
||||||
|
|
||||||
typedef struct private_child_delete_t private_child_delete_t;
|
typedef struct private_child_delete_t private_child_delete_t;
|
||||||
|
|
||||||
@@ -118,6 +119,33 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
|
|||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given CHILD_SA is the redundant SA created in a rekey collision.
|
||||||
|
*/
|
||||||
|
static bool is_redundant(private_child_delete_t *this, child_sa_t *child)
|
||||||
|
{
|
||||||
|
enumerator_t *tasks;
|
||||||
|
task_t *task;
|
||||||
|
|
||||||
|
tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
|
||||||
|
TASK_QUEUE_ACTIVE);
|
||||||
|
while (tasks->enumerate(tasks, &task))
|
||||||
|
{
|
||||||
|
if (task->get_type(task) == TASK_CHILD_REKEY)
|
||||||
|
{
|
||||||
|
child_rekey_t *rekey = (child_rekey_t*)task;
|
||||||
|
|
||||||
|
if (rekey->is_redundant(rekey, child))
|
||||||
|
{
|
||||||
|
tasks->destroy(tasks);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks->destroy(tasks);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read in payloads and find the children to delete
|
* read in payloads and find the children to delete
|
||||||
*/
|
*/
|
||||||
@@ -171,8 +199,15 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
|
|||||||
/* we reply as usual, rekeying will fail */
|
/* we reply as usual, rekeying will fail */
|
||||||
case CHILD_INSTALLED:
|
case CHILD_INSTALLED:
|
||||||
if (!this->initiator)
|
if (!this->initiator)
|
||||||
{ /* reestablish installed children if required */
|
{
|
||||||
this->check_delete_action = TRUE;
|
if (is_redundant(this, child_sa))
|
||||||
|
{
|
||||||
|
this->rekeyed = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->check_delete_action = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user