diff options
Diffstat (limited to 'src/charon/sa/ike_sa_manager.c')
-rw-r--r-- | src/charon/sa/ike_sa_manager.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 9c1b2d413..bd7b84c6f 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: ike_sa_manager.c 4044 2008-06-06 15:05:54Z martin $ + * $Id: ike_sa_manager.c 4234 2008-07-30 14:15:08Z martin $ */ #include <pthread.h> @@ -80,6 +80,16 @@ struct entry_t { host_t *other; /** + * own identity, required for duplicate checking + */ + identification_t *my_id; + + /** + * remote identity, required for duplicate checking + */ + identification_t *other_id; + + /** * message ID currently processing, if any */ u_int32_t message_id; @@ -95,6 +105,8 @@ static status_t entry_destroy(entry_t *this) this->ike_sa_id->destroy(this->ike_sa_id); chunk_free(&this->init_hash); DESTROY_IF(this->other); + DESTROY_IF(this->my_id); + DESTROY_IF(this->other_id); free(this); return SUCCESS; } @@ -116,6 +128,8 @@ static entry_t *entry_create(ike_sa_id_t *ike_sa_id) this->message_id = -1; this->init_hash = chunk_empty; this->other = NULL; + this->my_id = NULL; + this->other_id = NULL; /* ike_sa_id is always cloned */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); @@ -157,6 +171,11 @@ struct private_ike_sa_manager_t { * SHA1 hasher for IKE_SA_INIT retransmit detection */ hasher_t *hasher; + + /** + * reuse existing IKE_SAs in checkout_by_config + */ + bool reuse_ikesa; }; /** @@ -504,7 +523,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, pthread_mutex_lock(&(this->mutex)); - if (my_host && other_host) + if (my_host && other_host && this->reuse_ikesa) { enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); while (enumerator->enumerate(enumerator, &entry)) @@ -721,10 +740,13 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this, { /* self is not a duplicate */ continue; } - if (wait_for_entry(this, entry)) - { - if (me->equals(me, entry->ike_sa->get_my_id(entry->ike_sa)) && - other->equals(other, entry->ike_sa->get_other_id(entry->ike_sa))) + if (entry->my_id && me->equals(me, entry->my_id) && + entry->other_id && other->equals(other, entry->other_id)) + { + /* we are sure that the other entry is not calling + * checkout_duplicate here, as the identities in entry would not + * have been set yet. Otherwise we would risk a deadlock. */ + if (wait_for_entry(this, entry)) { duplicate = entry->ike_sa; entry->checked_out = TRUE; @@ -784,6 +806,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) entry_t *entry; ike_sa_id_t *ike_sa_id; host_t *other; + identification_t *my_id, *other_id; ike_sa_id = ike_sa->get_id(ike_sa); @@ -806,6 +829,21 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) DESTROY_IF(entry->other); entry->other = other->clone(other); } + /* apply identities for diplicate test */ + my_id = ike_sa->get_my_id(ike_sa); + other_id = ike_sa->get_other_id(ike_sa); + if (!entry->my_id || + entry->my_id->get_type(entry->my_id) == ID_ANY) + { + DESTROY_IF(entry->my_id); + entry->my_id = my_id->clone(my_id); + } + if (!entry->other_id || + entry->other_id->get_type(entry->other_id) == ID_ANY) + { + DESTROY_IF(entry->other_id); + entry->other_id = other_id->clone(other_id); + } DBG2(DBG_MGR, "check-in of IKE_SA successful."); pthread_cond_signal(&(entry->condvar)); retval = SUCCESS; @@ -1009,6 +1047,8 @@ ike_sa_manager_t *ike_sa_manager_create() } this->ike_sa_list = linked_list_create(); pthread_mutex_init(&this->mutex, NULL); + this->reuse_ikesa = lib->settings->get_bool(lib->settings, + "charon.reuse_ikesa", TRUE); return &this->public; } |