diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c index 996b2483e9..afb76b39ea 100644 --- a/src/libcharon/plugins/ha/ha_segments.c +++ b/src/libcharon/plugins/ha/ha_segments.c @@ -135,9 +135,11 @@ static void enable_disable(private_ha_segments_t *this, u_int segment, { ike_sa_t *ike_sa; enumerator_t *enumerator; - ike_sa_state_t old, new; + ike_sa_state_t old, new, cur; ha_message_t *message = NULL; ha_message_type_t type; + array_t *to_destroy; + uint32_t unique_id; bool changes = FALSE; if (segment > this->count) @@ -172,11 +174,13 @@ static void enable_disable(private_ha_segments_t *this, u_int segment, if (changes) { + to_destroy = array_create(sizeof(u_int), 0); enumerator = charon->ike_sa_manager->create_enumerator( charon->ike_sa_manager, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { - if (ike_sa->get_state(ike_sa) != old) + cur = ike_sa->get_state(ike_sa); + if (cur != old && cur != IKE_CONNECTING) { continue; } @@ -187,11 +191,34 @@ static void enable_disable(private_ha_segments_t *this, u_int segment, if (this->kernel->get_segment(this->kernel, ike_sa->get_other_host(ike_sa)) == segment) { - ike_sa->set_state(ike_sa, new); + if (cur == IKE_CONNECTING) + { + unique_id = ike_sa->get_unique_id(ike_sa); + array_insert(to_destroy, ARRAY_TAIL, &unique_id); + } + else + { + ike_sa->set_state(ike_sa, new); + } } } enumerator->destroy(enumerator); log_segments(this, enable, segment); + + while (array_remove(to_destroy, ARRAY_HEAD, &unique_id)) + { + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + unique_id); + if (ike_sa) + { + DBG1(DBG_IKE, "destroying incomplete IKE_SA %s[%d] after " + "%sactivating HA segment %d", ike_sa->get_name(ike_sa), + unique_id, segment, enable ? "" : "de"); + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + ike_sa); + } + } + array_destroy(to_destroy); } if (notify)