child-rekey: Add method to check for the redundant SA created in a collision

This commit is contained in:
Tobias Brunner
2016-06-17 18:48:04 +02:00
parent f97bac5594
commit 4f1012b3e1
2 changed files with 37 additions and 18 deletions
+20 -14
View File
@@ -1,7 +1,8 @@
/* /*
* Copyright (C) 2009-2016 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* 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
@@ -434,6 +435,18 @@ METHOD(task_t, get_type, task_type_t,
return TASK_CHILD_REKEY; return TASK_CHILD_REKEY;
} }
METHOD(child_rekey_t, is_redundant, bool,
private_child_rekey_t *this, child_sa_t *child)
{
if (this->collision &&
this->collision->get_type(this->collision) == TASK_CHILD_REKEY)
{
private_child_rekey_t *rekey = (private_child_rekey_t*)this->collision;
return child == rekey->child_create->get_child(rekey->child_create);
}
return FALSE;
}
METHOD(child_rekey_t, collide, void, METHOD(child_rekey_t, collide, void,
private_child_rekey_t *this, task_t *other) private_child_rekey_t *this, task_t *other)
{ {
@@ -452,19 +465,11 @@ METHOD(child_rekey_t, collide, void,
else if (other->get_type(other) == TASK_CHILD_DELETE) else if (other->get_type(other) == TASK_CHILD_DELETE)
{ {
child_delete_t *del = (child_delete_t*)other; child_delete_t *del = (child_delete_t*)other;
if (this->collision && if (is_redundant(this, del->get_child(del)))
this->collision->get_type(this->collision) == TASK_CHILD_REKEY)
{ {
private_child_rekey_t *rekey; this->other_child_destroyed = TRUE;
other->destroy(other);
rekey = (private_child_rekey_t*)this->collision; return;
if (del->get_child(del) == rekey->child_create->get_child(rekey->child_create))
{
/* peer deletes redundant child created in collision */
this->other_child_destroyed = TRUE;
other->destroy(other);
return;
}
} }
if (del->get_child(del) != this->child_sa) if (del->get_child(del) != this->child_sa)
{ {
@@ -475,7 +480,7 @@ METHOD(child_rekey_t, collide, void,
} }
else else
{ {
/* any other task is not critical for collisisions, ignore */ /* any other task is not critical for collisions, ignore */
other->destroy(other); other->destroy(other);
return; return;
} }
@@ -532,6 +537,7 @@ child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol,
.migrate = _migrate, .migrate = _migrate,
.destroy = _destroy, .destroy = _destroy,
}, },
.is_redundant = _is_redundant,
.collide = _collide, .collide = _collide,
}, },
.ike_sa = ike_sa, .ike_sa = ike_sa,
+17 -4
View File
@@ -1,6 +1,7 @@
/* /*
* Copyright (C) 2016 Tobias Brunner
* Copyright (C) 2007 Martin Willi * Copyright (C) 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
@@ -39,13 +40,25 @@ struct child_rekey_t {
task_t task; task_t task;
/** /**
* Register a rekeying task which collides with this one * Check if the given SA is the redundant CHILD_SA created during a rekey
* collision.
*
* This is called if the other peer deletes the redundant SA before we were
* able to handle the CREATE_CHILD_SA response.
*
* @param child CHILD_SA to check
* @return TRUE if the SA is the redundant CHILD_SA
*/
bool (*is_redundant)(child_rekey_t *this, child_sa_t *child);
/**
* Register a rekeying/delete task which collides with this one
* *
* If two peers initiate rekeying at the same time, the collision must * If two peers initiate rekeying at the same time, the collision must
* be handled gracefully. The task manager is aware of what exchanges * be handled gracefully. The task manager is aware of what exchanges
* are going on and notifies the outgoing task by passing the incoming. * are going on and notifies the active task by passing the passive.
* *
* @param other incoming task * @param other passive task (adopted)
*/ */
void (*collide)(child_rekey_t* this, task_t *other); void (*collide)(child_rekey_t* this, task_t *other);
}; };