From 977ec0c3169900d5905121917dd736ecfb0a7863 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 9 Jul 2009 14:44:08 +0200 Subject: [PATCH] implemented ike_down() bus hook --- src/charon/bus/bus.c | 130 +++++++++++++++++-------------- src/charon/sa/ike_sa_manager.c | 11 +++ src/charon/sa/task_manager.c | 23 ++++++ src/charon/sa/tasks/ike_delete.c | 36 +++++++-- src/charon/sa/tasks/task.h | 4 +- 5 files changed, 138 insertions(+), 66 deletions(-) diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c index d54aa1806..a5f8fc255 100644 --- a/src/charon/bus/bus.c +++ b/src/charon/bus/bus.c @@ -513,64 +513,6 @@ static void child_keys(private_bus_t *this, child_sa_t *child_sa, this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.ike_updown - */ -static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up) -{ - enumerator_t *enumerator; - entry_t *entry; - bool keep; - - this->mutex->lock(this->mutex); - enumerator = this->listeners->create_enumerator(this->listeners); - while (enumerator->enumerate(enumerator, &entry)) - { - if (entry->calling || !entry->listener->ike_updown) - { - continue; - } - entry->calling++; - keep = entry->listener->ike_updown(entry->listener, ike_sa, up); - entry->calling--; - if (!keep) - { - unregister_listener(this, entry, enumerator); - } - } - enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); -} - -/** - * Implementation of bus_t.ike_rekey - */ -static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new) -{ - enumerator_t *enumerator; - entry_t *entry; - bool keep; - - this->mutex->lock(this->mutex); - enumerator = this->listeners->create_enumerator(this->listeners); - while (enumerator->enumerate(enumerator, &entry)) - { - if (entry->calling || !entry->listener->ike_rekey) - { - continue; - } - entry->calling++; - keep = entry->listener->ike_rekey(entry->listener, old, new); - entry->calling--; - if (!keep) - { - unregister_listener(this, entry, enumerator); - } - } - enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); -} - /** * Implementation of bus_t.child_updown */ @@ -636,6 +578,78 @@ static void child_rekey(private_bus_t *this, child_sa_t *old, child_sa_t *new) this->mutex->unlock(this->mutex); } +/** + * Implementation of bus_t.ike_updown + */ +static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up) +{ + enumerator_t *enumerator; + entry_t *entry; + bool keep; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->ike_updown) + { + continue; + } + entry->calling++; + keep = entry->listener->ike_updown(entry->listener, ike_sa, up); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + /* a down event for IKE_SA implicitly downs all CHILD_SAs */ + if (!up) + { + iterator_t *iterator; + child_sa_t *child_sa; + + iterator = ike_sa->create_child_sa_iterator(ike_sa); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + child_updown(this, child_sa, FALSE); + } + iterator->destroy(iterator); + } +} + +/** + * Implementation of bus_t.ike_rekey + */ +static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new) +{ + enumerator_t *enumerator; + entry_t *entry; + bool keep; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->ike_rekey) + { + continue; + } + entry->calling++; + keep = entry->listener->ike_rekey(entry->listener, old, new); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + /** * Implementation of bus_t.authorize */ diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index efe7c228c..38a131970 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -1554,6 +1554,17 @@ static void flush(private_ike_sa_manager_t *this) while (enumerator->enumerate(enumerator, &entry, &segment)) { charon->bus->set_sa(charon->bus, entry->ike_sa); + /* as the delete never gets processed, fire down events */ + switch (entry->ike_sa->get_state(entry->ike_sa)) + { + case IKE_ESTABLISHED: + case IKE_REKEYING: + case IKE_DELETING: + charon->bus->ike_updown(charon->bus, entry->ike_sa, FALSE); + break; + default: + break; + } entry->ike_sa->delete(entry->ike_sa); } enumerator->destroy(enumerator); diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index 976ac2c7e..f33fcd6d4 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -220,6 +220,10 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id) { DBG1(DBG_IKE, "giving up after %d retransmits", this->initiating.retransmitted - 1); + if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) + { + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + } return DESTROY_ME; } @@ -240,6 +244,7 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id) { DBG1(DBG_IKE, "giving up after %d path probings", this->initiating.retransmitted - 1); + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); return DESTROY_ME; } @@ -431,6 +436,12 @@ static status_t build_request(private_task_manager_t *this) break; case FAILED: default: + if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) + { + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + } + /* FALL */ + case DESTROY_ME: /* critical failure, destroy IKE_SA */ iterator->destroy(iterator); message->destroy(message); @@ -451,6 +462,7 @@ static status_t build_request(private_task_manager_t *this) * close the SA */ message->destroy(message); flush(this); + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); return DESTROY_ME; } @@ -474,6 +486,7 @@ static status_t process_response(private_task_manager_t *this, DBG1(DBG_IKE, "received %N response, but expected %N", exchange_type_names, message->get_exchange_type(message), exchange_type_names, this->initiating.type); + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); return DESTROY_ME; } @@ -494,6 +507,9 @@ static status_t process_response(private_task_manager_t *this, break; case FAILED: default: + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + /* FALL */ + case DESTROY_ME: /* critical failure, destroy IKE_SA */ iterator->remove(iterator); iterator->destroy(iterator); @@ -604,6 +620,9 @@ static status_t build_response(private_task_manager_t *this, message_t *request) break; case FAILED: default: + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + /* FALL */ + case DESTROY_ME: /* destroy IKE_SA, but SEND response first */ delete = TRUE; break; @@ -631,6 +650,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) message->destroy(message); if (status != SUCCESS) { + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); return DESTROY_ME; } @@ -832,6 +852,9 @@ static status_t process_request(private_task_manager_t *this, break; case FAILED: default: + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + /* FALL */ + case DESTROY_ME: /* critical failure, destroy IKE_SA */ iterator->remove(iterator); iterator->destroy(iterator); diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c index f308a6358..cde117934 100644 --- a/src/charon/sa/tasks/ike_delete.c +++ b/src/charon/sa/tasks/ike_delete.c @@ -21,7 +21,7 @@ typedef struct private_ike_delete_t private_ike_delete_t; -/**file +/** * Private members of a ike_delete_t task. */ struct private_ike_delete_t { @@ -41,6 +41,11 @@ struct private_ike_delete_t { */ bool initiator; + /** + * are we deleting a rekeyed SA? + */ + bool rekeyed; + /** * are we responding to a delete, but have initated our own? */ @@ -64,6 +69,11 @@ static status_t build_i(private_ike_delete_t *this, message_t *message) delete_payload = delete_payload_create(PROTO_IKE); message->add_payload(message, (payload_t*)delete_payload); + + if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING) + { + this->rekeyed = TRUE; + } this->ike_sa->set_state(this->ike_sa, IKE_DELETING); DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]", @@ -79,8 +89,12 @@ static status_t build_i(private_ike_delete_t *this, message_t *message) static status_t process_i(private_ike_delete_t *this, message_t *message) { DBG0(DBG_IKE, "IKE_SA deleted"); - /* completed, delete IKE_SA by returning FAILED */ - return FAILED; + if (!this->rekeyed) + { /* invoke ike_down() hook if SA has not been rekeyed */ + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + } + /* completed, delete IKE_SA by returning DESTROY_ME */ + return DESTROY_ME; } /** @@ -106,14 +120,17 @@ static status_t process_r(private_ike_delete_t *this, message_t *message) case IKE_ESTABLISHED: this->ike_sa->set_state(this->ike_sa, IKE_DELETING); this->ike_sa->reestablish(this->ike_sa); + return NEED_MORE; + case IKE_REKEYING: + this->rekeyed = TRUE; break; case IKE_DELETING: this->simultaneous = TRUE; - /* FALL */ + break; default: - this->ike_sa->set_state(this->ike_sa, IKE_DELETING); break; } + this->ike_sa->set_state(this->ike_sa, IKE_DELETING); return NEED_MORE; } @@ -129,8 +146,12 @@ static status_t build_r(private_ike_delete_t *this, message_t *message) /* wait for peer's response for our delete request, but set a timeout */ return SUCCESS; } - /* completed, delete IKE_SA by returning FAILED */ - return FAILED; + if (!this->rekeyed) + { /* invoke ike_down() hook if SA has not been rekeyed */ + charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); + } + /* completed, delete IKE_SA by returning DESTROY_ME */ + return DESTROY_ME; } /** @@ -182,6 +203,7 @@ ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator) this->ike_sa = ike_sa; this->initiator = initiator; + this->rekeyed = FALSE; this->simultaneous = FALSE; return &this->public; diff --git a/src/charon/sa/tasks/task.h b/src/charon/sa/tasks/task.h index f9b409f35..3d2014599 100644 --- a/src/charon/sa/tasks/task.h +++ b/src/charon/sa/tasks/task.h @@ -100,7 +100,8 @@ struct task_t { * * @param message message to add payloads to * @return - * - FAILED if a critical error occured + * - FAILED if a critical error occured + * - DESTROY_ME if IKE_SA has been properly deleted * - NEED_MORE if another call to build/process needed * - SUCCESS if task completed */ @@ -112,6 +113,7 @@ struct task_t { * @param message message to read payloads from * @return * - FAILED if a critical error occured + * - DESTROY_ME if IKE_SA has been properly deleted * - NEED_MORE if another call to build/process needed * - SUCCESS if task completed */