aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/charon/sa/ike_sa_manager.c119
-rw-r--r--Source/charon/sa/ike_sa_manager.h31
-rw-r--r--Source/charon/threads/thread_pool.c19
3 files changed, 96 insertions, 73 deletions
diff --git a/Source/charon/sa/ike_sa_manager.c b/Source/charon/sa/ike_sa_manager.c
index 31bc74a2f..8348dae38 100644
--- a/Source/charon/sa/ike_sa_manager.c
+++ b/Source/charon/sa/ike_sa_manager.c
@@ -363,7 +363,73 @@ static status_t get_next_spi(private_ike_sa_manager_t *this, u_int64_t *spi)
}
/**
- * @see ike_sa_manager_s.checkout_ike_sa
+ * Implementation of ike_sa_manager.create_and_checkout.
+ */
+static status_t create_and_checkout(private_ike_sa_manager_t *this,ike_sa_t **ike_sa)
+{
+ status_t retval;
+ u_int64_t initiator_spi;
+ ike_sa_entry_t *new_ike_sa_entry;
+ ike_sa_id_t *new_ike_sa_id;
+
+ retval = this->get_next_spi(this, &initiator_spi);
+ if (retval == SUCCESS)
+ {
+ new_ike_sa_id = ike_sa_id_create(0, 0, TRUE);
+ if (new_ike_sa_id != NULL)
+ {
+ new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi);
+
+ /* create entry */
+ new_ike_sa_entry = ike_sa_entry_create(new_ike_sa_id);
+ new_ike_sa_id->destroy(new_ike_sa_id);
+ if (new_ike_sa_entry != NULL)
+ {
+ /* each access is locked */
+ pthread_mutex_lock(&(this->mutex));
+
+ retval = this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
+
+ if (retval == SUCCESS)
+ {
+ /* check ike_sa out */
+ this->logger->log(this->logger,CONTROL | MORE ,"New IKE_SA created and added to list of known IKE_SA's");
+ new_ike_sa_entry->checked_out = TRUE;
+ *ike_sa = new_ike_sa_entry->ike_sa;
+ /* DON'T use return, we must unlock the mutex! */
+ }
+ else
+ {
+ /* ike_sa_entry could not be added to list*/
+ this->logger->log(this->logger,ERROR,"Fatal error: ike_sa_entry_t could not be added to list");
+ }
+ pthread_mutex_unlock(&(this->mutex));
+ }
+ else
+ {
+ /* new ike_sa_entry could not be created */
+ this->logger->log(this->logger,ERROR,"Fatal error: ike_sa_entry_t could not be created");
+ retval = OUT_OF_RES;
+ }
+ }
+ else
+ {
+ /* new ike_sa_id could not be created */
+ this->logger->log(this->logger,ERROR,"Fatal error: ike_sa_id_t could not be created");
+ retval = OUT_OF_RES;
+ }
+ }
+ else
+ {
+ /* next SPI could not be created */
+ this->logger->log(this->logger,ERROR,"Fatal error: Next SPI could not be created");
+ }
+
+ return retval;
+}
+
+/**
+ * Implementation of ike_sa_manager.checkout.
*/
static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_t **ike_sa)
{
@@ -480,6 +546,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
{
/* new ike_sa_entry could not be created */
this->logger->log(this->logger,ERROR,"Fatal error: ike_sa_entry could not be created");
+ retval = OUT_OF_RES;
}
}
else
@@ -488,55 +555,6 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
}
}
- else if (!initiator_spi_set && !responder_spi_set)
- {
- /* creation of an IKE_SA from local site,
- * we are the initiator!
- */
- u_int64_t initiator_spi;
- ike_sa_entry_t *new_ike_sa_entry;
-
- retval = this->get_next_spi(this, &initiator_spi);
- if (retval == SUCCESS)
- {
- /* we also set arguments SPI, so its still valid */
- ike_sa_id->set_initiator_spi(ike_sa_id, initiator_spi);
-
- /* create entry */
- new_ike_sa_entry = ike_sa_entry_create(ike_sa_id);
- if (new_ike_sa_entry != NULL)
- {
- retval = this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
-
- if (retval == SUCCESS)
- {
- /* check ike_sa out */
- this->logger->log(this->logger,CONTROL | MORE ,"New IKE_SA created and added to list of known IKE_SA's");
- new_ike_sa_entry->checked_out = TRUE;
- *ike_sa = new_ike_sa_entry->ike_sa;
-
- /* DON'T use return, we must unlock the mutex! */
- }
- else
- {
- /* ike_sa_entry could not be added to list*/
- this->logger->log(this->logger,ERROR,"Fatal error: ike_sa_entry could not be added to list");
- }
- }
- else
- {
- /* new ike_sa_entry could not be created */
- this->logger->log(this->logger,ERROR,"Fatal error: ike_sa_entry could not be created");
- }
- }
- else
- {
- /* next SPI could not be created */
- this->logger->log(this->logger,ERROR,"Fatal error: Next SPI could not be created");
- }
-
-
- }
else
{
/* responder set, initiator not: here is something seriously wrong! */
@@ -756,6 +774,7 @@ ike_sa_manager_t *ike_sa_manager_create()
/* assign public functions */
this->public.destroy = (status_t(*)(ike_sa_manager_t*))destroy;
+ this->public.create_and_checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_t **sa))create_and_checkout;
this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t *sa_id, ike_sa_t **sa))checkout;
this->public.checkin = (status_t(*)(ike_sa_manager_t*, ike_sa_t *sa))checkin;
this->public.delete = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t *sa_id))delete;
diff --git a/Source/charon/sa/ike_sa_manager.h b/Source/charon/sa/ike_sa_manager.h
index 1481ebb40..4ef1bf75d 100644
--- a/Source/charon/sa/ike_sa_manager.h
+++ b/Source/charon/sa/ike_sa_manager.h
@@ -1,7 +1,7 @@
/**
* @file ike_sa_manager.h
*
- * @brief Central point for managing IKE-SAs (creation, locking, deleting...)
+ * @brief Interface of ike_sa_manager_t.
*
*/
@@ -33,7 +33,7 @@ typedef struct ike_sa_manager_t ike_sa_manager_t;
* @brief The IKE_SA-Manager manages the IKE_SAs ;-).
*
* To avoid access from multiple threads, IKE_SAs must be checked out from
- * the manager, and checked back in after usage.
+ * the manager, and checked in after usage.
* The manager also handles deletion of SAs.
*
* @todo checking of double-checkouts from the same threads would be nice.
@@ -46,7 +46,6 @@ struct ike_sa_manager_t {
*
* Checks out a SA by its ID. An SA will be created, when:
* - Responder SPI is not set (when received an IKE_SA_INIT from initiator)
- * - Both SPIs are not set (for initiating IKE_SA_INIT)
* Management of SPIs is the managers job, he will set it.
* This function blocks until SA is available for checkout.
*
@@ -62,16 +61,34 @@ struct ike_sa_manager_t {
* - OUT_OF_RES
*/
status_t (*checkout) (ike_sa_manager_t* ike_sa_manager, ike_sa_id_t *sa_id, ike_sa_t **ike_sa);
+
+ /**
+ * @brief Create and checkout an IKE_SA as original initator.
+ *
+ * Creates and checks out a SA as initiator. An SA will be created, when:
+ * Management of SPIs is the managers job, he will set it.
+ *
+ * @warning checking out two times without checking in will
+ * result in a deadlock!
+ *
+ * @param ike_sa_manager the manager object
+ * @param ike_sa[out] checked out SA
+ * @returns
+ * - SUCCESS if checkout successful
+ * - OUT_OF_RES
+ */
+ status_t (*create_and_checkout) (ike_sa_manager_t* ike_sa_manager,ike_sa_t **ike_sa);
+
/**
* @brief Checkin the SA after usage
*
- * @warning the SA pointer MUST NOT be used after checkin! The SA must be checked
- * out again!
+ * @warning the SA pointer MUST NOT be used after checkin!
+ * The SA must be checked out again!
*
* @param ike_sa_manager the manager object
* @param ike_sa_id[in/out] the SA identifier, will be updated
* @param ike_sa[out] checked out SA
- * @returns SUCCESS if checked in
+ * @returns SUCCESS if checked in
* NOT_FOUND when not found (shouldn't happen!)
*/
status_t (*checkin) (ike_sa_manager_t* ike_sa_manager, ike_sa_t *ike_sa);
@@ -83,7 +100,7 @@ struct ike_sa_manager_t {
*
* @param ike_sa_manager the manager object
* @param ike_sa_id[in/out] the SA identifier
- * @returns SUCCESS if found
+ * @returns SUCCESS if found
* NOT_FOUND when no such SA is available
*/
status_t (*delete) (ike_sa_manager_t* ike_sa_manager, ike_sa_id_t *ike_sa_id);
diff --git a/Source/charon/threads/thread_pool.c b/Source/charon/threads/thread_pool.c
index 7cf802bda..1ed3a20b5 100644
--- a/Source/charon/threads/thread_pool.c
+++ b/Source/charon/threads/thread_pool.c
@@ -192,27 +192,14 @@ static void job_processing(private_thread_pool_t *this)
* - call initiate_connection on this sa
*/
initiate_ike_sa_job_t *initiate_job;
- ike_sa_id_t *ike_sa_id;
ike_sa_t *ike_sa;
status_t status;
initiate_job = (initiate_ike_sa_job_t *)job;
+
+ this->worker_logger->log(this->worker_logger, CONTROL|MOST, "create and checking out IKE SA");
- ike_sa_id = ike_sa_id_create(0, 0, TRUE);
- if (ike_sa_id == NULL)
- {
- this->worker_logger->log(this->worker_logger, ERROR, "%s by creating ike_sa_id_t, job rejected.",
- mapping_find(status_m, status));
- break;
- }
-
- this->worker_logger->log(this->worker_logger, CONTROL|MOST, "checking out IKE SA %lld:%lld, role %s",
- ike_sa_id->get_initiator_spi(ike_sa_id),
- ike_sa_id->get_responder_spi(ike_sa_id),
- ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
-
- status = global_ike_sa_manager->checkout(global_ike_sa_manager, ike_sa_id, &ike_sa);
- ike_sa_id->destroy(ike_sa_id);
+ status = global_ike_sa_manager->create_and_checkout(global_ike_sa_manager, &ike_sa);
if (status != SUCCESS)
{
this->worker_logger->log(this->worker_logger, ERROR, "%s by checking out new IKE_SA, job rejected.",