summaryrefslogtreecommitdiff
path: root/src/charon/sa/ike_sa_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/ike_sa_manager.c')
-rw-r--r--src/charon/sa/ike_sa_manager.c52
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;
}