diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/charon/sa/ike_sa_manager.c | 119 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa_manager.h | 31 | ||||
-rw-r--r-- | Source/charon/threads/thread_pool.c | 19 |
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.", |