}
/**
- * handle exchange collisions
+ * Handle exchange collisions, returns TRUE if the given passive task was
+ * adopted by the active task and the task manager lost control over it.
*/
static bool handle_collisions(private_task_manager_t *this, task_t *task)
{
enumerator_t *enumerator;
task_t *active;
task_type_t type;
+ bool adopted = FALSE;
type = task->get_type(task);
if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE)
{
ike_rekey_t *rekey = (ike_rekey_t*)active;
- rekey->collide(rekey, task);
+ adopted = rekey->collide(rekey, task);
break;
}
continue;
if (type == TASK_CHILD_REKEY || type == TASK_CHILD_DELETE)
{
child_rekey_t *rekey = (child_rekey_t*)active;
- rekey->collide(rekey, task);
+ adopted = rekey->collide(rekey, task);
break;
}
continue;
continue;
}
enumerator->destroy(enumerator);
- return TRUE;
+ return adopted;
}
enumerator->destroy(enumerator);
}
- return FALSE;
+ return adopted;
}
/**
return FALSE;
}
-METHOD(child_rekey_t, collide, void,
+METHOD(child_rekey_t, collide, bool,
private_child_rekey_t *this, task_t *other)
{
/* the task manager only detects exchange collision, but not if
if (rekey->child_sa != this->child_sa)
{ /* not the same child => no collision */
- other->destroy(other);
- return;
+ return FALSE;
}
/* ignore passive tasks that did not successfully create a CHILD_SA */
other_child = rekey->child_create->get_child(rekey->child_create);
if (!other_child ||
other_child->get_state(other_child) != CHILD_INSTALLED)
{
- other->destroy(other);
- return;
+ return FALSE;
}
}
else if (other->get_type(other) == TASK_CHILD_DELETE)
if (is_redundant(this, del->get_child(del)))
{
this->other_child_destroyed = TRUE;
- other->destroy(other);
- return;
+ return FALSE;
}
if (del->get_child(del) != this->child_sa)
{
/* not the same child => no collision */
- other->destroy(other);
- return;
+ return FALSE;
}
}
else
{
- /* any other task is not critical for collisions, ignore */
- other->destroy(other);
- return;
+ /* shouldn't happen */
+ return FALSE;
}
DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
TASK_CHILD_REKEY, task_type_names, other->get_type(other));
DESTROY_IF(this->collision);
this->collision = other;
+ return TRUE;
}
METHOD(task_t, migrate, void,
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2020 Tobias Brunner
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks AG
* be handled gracefully. The task manager is aware of what exchanges
* are going on and notifies the active task by passing the passive.
*
- * @param other passive task (adopted)
+ * @param other passive task
+ * @return whether the task was adopted and should be removed from
+ * the task manager's control
*/
- void (*collide)(child_rekey_t* this, task_t *other);
+ bool (*collide)(child_rekey_t* this, task_t *other);
};
/**
return this->collision != NULL;
}
-METHOD(ike_rekey_t, collide, void,
+METHOD(ike_rekey_t, collide, bool,
private_ike_rekey_t* this, task_t *other)
{
DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
{
case TASK_IKE_DELETE:
conclude_undetected_collision(this);
- other->destroy(other);
break;
case TASK_IKE_REKEY:
{
{
DBG1(DBG_IKE, "colliding exchange did not result in an IKE_SA, "
"ignore");
- other->destroy(other);
break;
}
DESTROY_IF(&this->collision->public.task);
this->collision = rekey;
- break;
+ return TRUE;
}
default:
/* shouldn't happen */
break;
}
+ return FALSE;
}
/**
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2020 Tobias Brunner
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks AG
bool (*did_collide)(ike_rekey_t *this);
/**
- * Register a rekeying task which collides with this one.
+ * Register a rekeying/delete task which collides with this one.
*
* If two peers initiate rekeying at the same time, the collision must
* 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
+ * @return whether the task was adopted and should be removed from
+ * the task manager's control
*/
- void (*collide)(ike_rekey_t* this, task_t *other);
+ bool (*collide)(ike_rekey_t* this, task_t *other);
};
/**