Do not query CHILD_SA during delete if they already expired

This commit is contained in:
Martin Willi
2012-03-20 17:31:31 +01:00
parent 07202a2bf1
commit 3a925f74ab
18 changed files with 97 additions and 44 deletions
+1 -1
View File
@@ -368,7 +368,7 @@ METHOD(job_t, terminate_child_execute, void,
charon->bus->set_sa(charon->bus, ike_sa); charon->bus->set_sa(charon->bus, ike_sa);
if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa), if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE)) != DESTROY_ME) child_sa->get_spi(child_sa, TRUE), FALSE) != DESTROY_ME)
{ {
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
listener->status = SUCCESS; listener->status = SUCCESS;
+1 -1
View File
@@ -84,7 +84,7 @@ METHOD(kernel_listener_t, expire, bool,
protocol_id_names, proto, ntohl(spi), reqid); protocol_id_names, proto, ntohl(spi), reqid);
if (hard) if (hard)
{ {
job = (job_t*)delete_child_sa_job_create(reqid, proto, spi); job = (job_t*)delete_child_sa_job_create(reqid, proto, spi, hard);
} }
else else
{ {
+2 -1
View File
@@ -212,7 +212,8 @@ static status_t rekey_children(ike_sa_t *ike_sa)
DBG1(DBG_CFG, "resyncing CHILD_SA using a delete"); DBG1(DBG_CFG, "resyncing CHILD_SA using a delete");
status = ike_sa->delete_child_sa(ike_sa, status = ike_sa->delete_child_sa(ike_sa,
child_sa->get_protocol(child_sa), child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE)); child_sa->get_spi(child_sa, TRUE),
FALSE);
} }
else else
{ {
@@ -44,6 +44,11 @@ struct private_delete_child_sa_job_t {
* inbound SPI of the CHILD_SA * inbound SPI of the CHILD_SA
*/ */
u_int32_t spi; u_int32_t spi;
/**
* Delete for an expired CHILD_SA
*/
bool expired;
}; };
METHOD(job_t, destroy, void, METHOD(job_t, destroy, void,
@@ -66,7 +71,7 @@ METHOD(job_t, execute, void,
} }
else else
{ {
ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi); ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi, this->expired);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
} }
@@ -83,8 +88,7 @@ METHOD(job_t, get_priority, job_priority_t,
* Described in header * Described in header
*/ */
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol, protocol_id_t protocol, u_int32_t spi, bool expired)
u_int32_t spi)
{ {
private_delete_child_sa_job_t *this; private_delete_child_sa_job_t *this;
@@ -99,6 +103,7 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
.reqid = reqid, .reqid = reqid,
.protocol = protocol, .protocol = protocol,
.spi = spi, .spi = spi,
.expired = expired,
); );
return &this->public; return &this->public;
@@ -50,10 +50,10 @@ struct delete_child_sa_job_t {
* @param reqid reqid of the CHILD_SA, as used in kernel * @param reqid reqid of the CHILD_SA, as used in kernel
* @param protocol protocol of the CHILD_SA * @param protocol protocol of the CHILD_SA
* @param spi security parameter index of the CHILD_SA * @param spi security parameter index of the CHILD_SA
* @param expired TRUE if CHILD_SA already expired
* @return delete_child_sa_job_t object * @return delete_child_sa_job_t object
*/ */
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol, protocol_id_t protocol, u_int32_t spi, bool expired);
u_int32_t spi);
#endif /** DELETE_CHILD_SA_JOB_H_ @}*/ #endif /** DELETE_CHILD_SA_JOB_H_ @}*/
@@ -108,7 +108,7 @@ METHOD(job_t, execute, void,
{ {
DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds " DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
"of inactivity", this->timeout); "of inactivity", this->timeout);
status = ike_sa->delete_child_sa(ike_sa, proto, delete); status = ike_sa->delete_child_sa(ike_sa, proto, delete, FALSE);
} }
} }
if (status == DESTROY_ME) if (status == DESTROY_ME)
+3 -2
View File
@@ -1256,9 +1256,10 @@ METHOD(ike_sa_t, rekey_child_sa, status_t,
} }
METHOD(ike_sa_t, delete_child_sa, status_t, METHOD(ike_sa_t, delete_child_sa, status_t,
private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi) private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool expired)
{ {
this->task_manager->queue_child_delete(this->task_manager, protocol, spi); this->task_manager->queue_child_delete(this->task_manager,
protocol, spi, expired);
return this->task_manager->initiate(this->task_manager); return this->task_manager->initiate(this->task_manager);
} }
+3 -1
View File
@@ -845,11 +845,13 @@ struct ike_sa_t {
* *
* @param protocol protocol of the SA * @param protocol protocol of the SA
* @param spi inbound SPI of the CHILD_SA * @param spi inbound SPI of the CHILD_SA
* @param expired TRUE if CHILD_SA is expired
* @return * @return
* - NOT_FOUND, if IKE_SA has no such CHILD_SA * - NOT_FOUND, if IKE_SA has no such CHILD_SA
* - SUCCESS, if delete message sent * - SUCCESS, if delete message sent
*/ */
status_t (*delete_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi); status_t (*delete_child_sa)(ike_sa_t *this, protocol_id_t protocol,
u_int32_t spi, bool expired);
/** /**
* Destroy a CHILD SA with the specified protocol/SPI. * Destroy a CHILD SA with the specified protocol/SPI.
+4 -3
View File
@@ -1141,7 +1141,7 @@ METHOD(task_manager_t, queue_ike_delete, void,
{ {
queue_task(this, (task_t*) queue_task(this, (task_t*)
quick_delete_create(this->ike_sa, child_sa->get_protocol(child_sa), quick_delete_create(this->ike_sa, child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE), FALSE)); child_sa->get_spi(child_sa, TRUE), FALSE, FALSE));
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
@@ -1190,10 +1190,11 @@ METHOD(task_manager_t, queue_child_rekey, void,
} }
METHOD(task_manager_t, queue_child_delete, void, METHOD(task_manager_t, queue_child_delete, void,
private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi) private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
bool expired)
{ {
queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol, queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol,
spi, FALSE)); spi, FALSE, expired));
} }
METHOD(task_manager_t, queue_dpd, void, METHOD(task_manager_t, queue_dpd, void,
+1 -1
View File
@@ -108,7 +108,7 @@ METHOD(task_t, process_r, status_t,
else else
{ {
this->del = (task_t*)quick_delete_create(this->ike_sa, this->del = (task_t*)quick_delete_create(this->ike_sa,
PROTO_NONE, 0, FALSE); PROTO_NONE, 0, FALSE, FALSE);
} }
} }
break; break;
+22 -3
View File
@@ -54,6 +54,11 @@ struct private_quick_delete_t {
* Send delete even if SA does not exist * Send delete even if SA does not exist
*/ */
bool force; bool force;
/**
* SA already expired?
*/
bool expired;
}; };
/** /**
@@ -78,16 +83,29 @@ static bool delete_child(private_quick_delete_t *this,
child_sa->set_state(child_sa, CHILD_DELETING); child_sa->set_state(child_sa, CHILD_DELETING);
if (this->expired)
{
DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
ntohl(child_sa->get_spi(child_sa, TRUE)),
ntohl(child_sa->get_spi(child_sa, FALSE)),
child_sa->get_traffic_selectors(child_sa, TRUE),
child_sa->get_traffic_selectors(child_sa, FALSE));
}
else
{
child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in); child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out); child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
DBG0(DBG_IKE, "closing CHILD_SA %s{%d} " DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
"with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
child_sa->get_traffic_selectors(child_sa, TRUE), child_sa->get_traffic_selectors(child_sa, TRUE),
child_sa->get_traffic_selectors(child_sa, FALSE)); child_sa->get_traffic_selectors(child_sa, FALSE));
}
charon->bus->child_updown(charon->bus, child_sa, FALSE); charon->bus->child_updown(charon->bus, child_sa, FALSE);
@@ -190,7 +208,7 @@ METHOD(task_t, destroy, void,
* Described in header. * Described in header.
*/ */
quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
u_int32_t spi, bool force) u_int32_t spi, bool force, bool expired)
{ {
private_quick_delete_t *this; private_quick_delete_t *this;
@@ -206,6 +224,7 @@ quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
.protocol = protocol, .protocol = protocol,
.spi = spi, .spi = spi,
.force = force, .force = force,
.expired = expired,
); );
if (protocol != PROTO_NONE) if (protocol != PROTO_NONE)
+2 -1
View File
@@ -46,9 +46,10 @@ struct quick_delete_t {
* @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder * @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder
* @param spi inbound SPI of CHILD_SA to delete * @param spi inbound SPI of CHILD_SA to delete
* @param force send delete even if SA does not exist * @param force send delete even if SA does not exist
* @param expired TRUE if SA already expired
* @return quick_delete task to handle by the task_manager * @return quick_delete task to handle by the task_manager
*/ */
quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
u_int32_t spi, bool force); u_int32_t spi, bool force, bool expired);
#endif /** QUICK_DELETE_H_ @}*/ #endif /** QUICK_DELETE_H_ @}*/
+1 -1
View File
@@ -773,7 +773,7 @@ METHOD(task_t, process_r, status_t,
this->ike_sa->queue_task(this->ike_sa, this->ike_sa->queue_task(this->ike_sa,
(task_t*)quick_delete_create(this->ike_sa, (task_t*)quick_delete_create(this->ike_sa,
this->proposal->get_protocol(this->proposal), this->proposal->get_protocol(this->proposal),
this->spi_i, TRUE)); this->spi_i, TRUE, TRUE));
return ALREADY_DONE; return ALREADY_DONE;
} }
return SUCCESS; return SUCCESS;
+5 -3
View File
@@ -825,7 +825,7 @@ static status_t process_request(private_task_manager_t *this,
else else
{ {
task = (task_t*)child_delete_create(this->ike_sa, task = (task_t*)child_delete_create(this->ike_sa,
PROTO_NONE, 0); PROTO_NONE, 0, FALSE);
} }
break; break;
} }
@@ -1308,9 +1308,11 @@ METHOD(task_manager_t, queue_child_rekey, void,
} }
METHOD(task_manager_t, queue_child_delete, void, METHOD(task_manager_t, queue_child_delete, void,
private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi) private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
bool expired)
{ {
queue_task(this, (task_t*)child_delete_create(this->ike_sa, protocol, spi)); queue_task(this, (task_t*)child_delete_create(this->ike_sa,
protocol, spi, expired));
} }
METHOD(task_manager_t, queue_dpd, void, METHOD(task_manager_t, queue_dpd, void,
+22 -3
View File
@@ -61,6 +61,11 @@ struct private_child_delete_t {
*/ */
bool rekeyed; bool rekeyed;
/**
* CHILD_SA already expired?
*/
bool expired;
/** /**
* CHILD_SAs which get deleted * CHILD_SAs which get deleted
*/ */
@@ -246,18 +251,31 @@ static void log_children(private_child_delete_t *this)
enumerator = this->child_sas->create_enumerator(this->child_sas); enumerator = this->child_sas->create_enumerator(this->child_sas);
while (enumerator->enumerate(enumerator, (void**)&child_sa)) while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (this->expired)
{
DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
ntohl(child_sa->get_spi(child_sa, TRUE)),
ntohl(child_sa->get_spi(child_sa, FALSE)),
child_sa->get_traffic_selectors(child_sa, TRUE),
child_sa->get_traffic_selectors(child_sa, FALSE));
}
else
{ {
child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in); child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out); child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
DBG0(DBG_IKE, "closing CHILD_SA %s{%d} " DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
"with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", "(%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
child_sa->get_traffic_selectors(child_sa, TRUE), child_sa->get_traffic_selectors(child_sa, TRUE),
child_sa->get_traffic_selectors(child_sa, FALSE)); child_sa->get_traffic_selectors(child_sa, FALSE));
} }
}
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
} }
@@ -356,7 +374,7 @@ METHOD(task_t, destroy, void,
* Described in header. * Described in header.
*/ */
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
u_int32_t spi) u_int32_t spi, bool expired)
{ {
private_child_delete_t *this; private_child_delete_t *this;
@@ -373,6 +391,7 @@ child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
.child_sas = linked_list_create(), .child_sas = linked_list_create(),
.protocol = protocol, .protocol = protocol,
.spi = spi, .spi = spi,
.expired = expired,
); );
if (protocol != PROTO_NONE) if (protocol != PROTO_NONE)
+2 -1
View File
@@ -52,9 +52,10 @@ struct child_delete_t {
* @param ike_sa IKE_SA this task works for * @param ike_sa IKE_SA this task works for
* @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder * @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder
* @param spi inbound SPI of CHILD_SA to delete * @param spi inbound SPI of CHILD_SA to delete
* @param expired TRUE if CHILD_SA already expired
* @return child_delete task to handle by the task_manager * @return child_delete task to handle by the task_manager
*/ */
child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
u_int32_t spi); u_int32_t spi, bool expired);
#endif /** CHILD_DELETE_H_ @}*/ #endif /** CHILD_DELETE_H_ @}*/
+1 -1
View File
@@ -352,7 +352,7 @@ METHOD(task_t, process_i, status_t,
protocol = to_delete->get_protocol(to_delete); protocol = to_delete->get_protocol(to_delete);
/* rekeying done, delete the obsolete CHILD_SA using a subtask */ /* rekeying done, delete the obsolete CHILD_SA using a subtask */
this->child_delete = child_delete_create(this->ike_sa, protocol, spi); this->child_delete = child_delete_create(this->ike_sa, protocol, spi, FALSE);
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete; this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete; this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete;
+2 -1
View File
@@ -177,9 +177,10 @@ struct task_manager_t {
* *
* @param protocol CHILD_SA protocol, AH|ESP * @param protocol CHILD_SA protocol, AH|ESP
* @param spi CHILD_SA SPI to rekey * @param spi CHILD_SA SPI to rekey
* @param expired TRUE if SA already expired
*/ */
void (*queue_child_delete)(task_manager_t *this, protocol_id_t protocol, void (*queue_child_delete)(task_manager_t *this, protocol_id_t protocol,
u_int32_t spi); u_int32_t spi, bool expired);
/** /**
* Queue liveness checking tasks. * Queue liveness checking tasks.