diff options
Diffstat (limited to 'Source/charon/ike_sa_manager.c')
-rw-r--r-- | Source/charon/ike_sa_manager.c | 126 |
1 files changed, 95 insertions, 31 deletions
diff --git a/Source/charon/ike_sa_manager.c b/Source/charon/ike_sa_manager.c index a3011b315..506be85d1 100644 --- a/Source/charon/ike_sa_manager.c +++ b/Source/charon/ike_sa_manager.c @@ -76,6 +76,7 @@ struct ike_sa_entry_s { */ static status_t ike_sa_entry_destroy(ike_sa_entry_t *this) { + /* also destroy IKE SA */ this->ike_sa->destroy(this->ike_sa); this->ike_sa_id->destroy(this->ike_sa_id); allocator_free(this); @@ -94,6 +95,11 @@ static ike_sa_entry_t *ike_sa_entry_create(ike_sa_id_t *ike_sa_id) { ike_sa_entry_t *this = allocator_alloc_thing(ike_sa_entry_t); + if (this == NULL) + { + return NULL; + } + /* destroy function */ this->destroy = ike_sa_entry_destroy; @@ -107,7 +113,21 @@ static ike_sa_entry_t *ike_sa_entry_create(ike_sa_id_t *ike_sa_id) /* ike_sa_id is always cloned */ ike_sa_id->clone(ike_sa_id, &(this->ike_sa_id)); + if (this->ike_sa_id == NULL) + { + allocator_free(this); + return NULL; + } + + /* create new ike_sa */ this->ike_sa = ike_sa_create(ike_sa_id); + if (this->ike_sa == NULL) + { + this->ike_sa_id->destroy(this->ike_sa_id); + allocator_free(this); + return NULL; + + } return this; } @@ -189,7 +209,8 @@ struct private_ike_sa_manager_s { /** * Linked list with entries for the ike_sa */ - linked_list_t *list; + linked_list_t *ike_sa_list; + /** * Next SPI, needed for incremental creation of SPIs */ @@ -202,12 +223,16 @@ struct private_ike_sa_manager_s { */ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry) { - linked_list_t *list = this->list; + linked_list_t *list = this->ike_sa_list; linked_list_iterator_t *iterator; status_t status; + + /* create iterator over list of ike_sa's */ status = list->create_iterator(list, &iterator, TRUE); if (status != SUCCESS) { + this->logger->log(this->logger,ERROR,"Fatal Error: could not create iterator: %s",mapping_find(status_m,status)); + /* out of res */ return status; } @@ -219,10 +244,14 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike { ike_sa_entry_t *current; bool are_equal = FALSE; + iterator->current(iterator, (void**)¤t); if (current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0) { - if (current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id)) + /* seems to be a half ready ike_sa */ + if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id)) + && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id))) { + this->logger->log(this->logger,CONTROL | MOST,"Found entry by initiator spi %d",ike_sa_id->get_initiator_spi(ike_sa_id)); *entry = current; status = SUCCESS; break; @@ -231,6 +260,7 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id, &are_equal); if (are_equal) { + this->logger->log(this->logger,CONTROL | MOST,"Found entry by full ID"); *entry = current; status = SUCCESS; break; @@ -246,12 +276,14 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike */ static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry) { - linked_list_t *list = this->list; + linked_list_t *list = this->ike_sa_list; linked_list_iterator_t *iterator; status_t status; + status = list->create_iterator(list, &iterator, TRUE); if (status != SUCCESS) { + this->logger->log(this->logger,ERROR,"Fatal Error: could not create iterator: %s",mapping_find(status_m,status)); return status; } @@ -265,6 +297,7 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa /* only pointers are compared */ if (current->ike_sa == ike_sa) { + this->logger->log(this->logger,CONTROL | MOST,"Found entry by pointer"); *entry = current; status = SUCCESS; break; @@ -279,23 +312,35 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa */ static status_t delete_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *entry) { - linked_list_t *list = this->list; + linked_list_t *list = this->ike_sa_list; linked_list_iterator_t *iterator; - list->create_iterator(list, &iterator, TRUE); + status_t status; + + status = list->create_iterator(list, &iterator, TRUE); + + if (status != SUCCESS) + { + this->logger->log(this->logger,ERROR,"Fatal Error: could not create iterator: %s",mapping_find(status_m,status)); + return status; + } + + status = NOT_FOUND; + while (iterator->has_next(iterator)) { ike_sa_entry_t *current; iterator->current(iterator, (void**)¤t); if (current == entry) { + this->logger->log(this->logger,CONTROL | MOST,"Found entry by pointer. Going to delete it."); list->remove(list, iterator); entry->destroy(entry); - iterator->destroy(iterator); - return SUCCESS; + status = SUCCESS; + break; } } iterator->destroy(iterator); - return NOT_FOUND; + return status; } @@ -308,7 +353,8 @@ static status_t get_next_spi(private_ike_sa_manager_t *this, u_int64_t *spi) if (this->next_spi == 0) { /* our software ran so incredible stable, we have no more * SPIs to give away :-/. */ - return OUT_OF_RES; + this->logger->log(this->logger,CONTROL | MOST,"No more SPI values available. WOW!"); + return OUT_OF_RES; } *spi = this->next_spi; return SUCCESS; @@ -323,6 +369,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, bool initiator_spi_set; status_t retval; + /* each access is locked */ pthread_mutex_lock(&(this->mutex)); responder_spi_set = (FALSE != ike_sa_id->get_responder_spi(ike_sa_id)); @@ -337,7 +384,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, /* look for the entry */ if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) { - /* can we give this out to new requesters?*/ + /* can we give this ike_sa out to new requesters?*/ if (entry->driveout_new_threads) { this->logger->log(this->logger,CONTROL|MORE,"Drive out new thread for existing IKE_SA"); @@ -368,6 +415,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, } else { + this->logger->log(this->logger,CONTROL|MOST,"IKE SA successfully checked out"); /* ok, this IKE_SA is finally ours */ entry->checked_out = TRUE; *ike_sa = entry->ike_sa; @@ -378,6 +426,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, } else { + this->logger->log(this->logger,ERROR | MORE,"IKE SA not stored in known IKE_SA list"); /* looks like there is no such IKE_SA, better luck next time... */ /* DON'T use return, we must unlock the mutex! */ retval = NOT_FOUND; @@ -409,10 +458,11 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, new_ike_sa_entry = ike_sa_entry_create(ike_sa_id); if (new_ike_sa_entry != NULL) { - retval = this->list->insert_last(this->list, new_ike_sa_entry); + 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 ,"IKE_SA added to list of known IKE_SA's"); new_ike_sa_entry->checked_out = TRUE; *ike_sa = new_ike_sa_entry->ike_sa; @@ -421,18 +471,18 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, else { /* ike_sa_entry could not be added to list*/ - this->logger->log(this->logger,CONTROL,"Fatal error: 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,CONTROL,"Fatal error: 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,CONTROL,"Fatal error: Next SPI could not be created"); + this->logger->log(this->logger,ERROR,"Fatal error: Next SPI could not be created"); } } @@ -454,11 +504,12 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, new_ike_sa_entry = ike_sa_entry_create(ike_sa_id); if (new_ike_sa_entry != NULL) { - retval = this->list->insert_last(this->list, new_ike_sa_entry); + 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; @@ -467,19 +518,19 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, else { /* ike_sa_entry could not be added to list*/ - this->logger->log(this->logger,CONTROL,"Fatal error: 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,CONTROL,"Fatal error: 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,CONTROL,"Fatal error: Next SPI could not be created"); + this->logger->log(this->logger,ERROR,"Fatal error: Next SPI could not be created"); } @@ -487,7 +538,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, else { /* responder set, initiator not: here is something seriously wrong! */ - this->logger->log(this->logger,CONTROL|MORE,"Invalid IKE_SA SPI's"); + this->logger->log(this->logger,ERROR | MORE,"Invalid IKE_SA SPI's"); /* DON'T use return, we must unlock the mutex! */ retval = INVALID_ARG; } @@ -520,12 +571,13 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa)); /* signal waiting threads */ entry->checked_out = FALSE; + this->logger->log(this->logger,CONTROL | MORE,"Checkin of IKE_SA successful."); pthread_cond_signal(&(entry->condvar)); retval = SUCCESS; } else { - this->logger->log(this->logger,CONTROL,"Fatal Error: Tried to checkin nonexisting IKE_SA"); + this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin nonexisting IKE_SA"); /* this SA is no more, this REALLY should not happen */ retval = NOT_FOUND; } @@ -567,11 +619,12 @@ static status_t checkin_and_delete(private_ike_sa_manager_t *this, ike_sa_t *ike } /* ok, we are alone now, no threads waiting in the entry's condvar */ this->delete_entry(this, entry); + this->logger->log(this->logger,CONTROL | MORE,"Checkin and delete of IKE_SA successful"); retval = SUCCESS; } else { - this->logger->log(this->logger,CONTROL,"Fatal Error: Tried to checkin and delete nonexisting IKE_SA"); + this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin and delete nonexisting IKE_SA"); retval = NOT_FOUND; } @@ -610,11 +663,12 @@ static status_t delete(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id) } /* ok, we are alone now, no threads waiting in the entry's condvar */ this->delete_entry(this, entry); + this->logger->log(this->logger,CONTROL | MORE,"Delete of IKE_SA successful"); retval = SUCCESS; } else { - this->logger->log(this->logger,CONTROL,"Fatal Error: Tried to delete nonexisting IKE_SA"); + this->logger->log(this->logger,ERROR,"Fatal Error: Tried to delete nonexisting IKE_SA"); retval = NOT_FOUND; } @@ -629,21 +683,24 @@ static status_t delete(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id) static status_t destroy(private_ike_sa_manager_t *this) { /* destroy all list entries */ - linked_list_t *list = this->list; + linked_list_t *list = this->ike_sa_list; linked_list_iterator_t *iterator; status_t status; pthread_mutex_lock(&(this->mutex)); + this->logger->log(this->logger,CONTROL | MORE,"Going to destroy IKE_SA manager and all managed IKE_SA's"); + /* Step 1: drive out all waiting threads */ status = list->create_iterator(list, &iterator, TRUE); if (status != SUCCESS) { - this->logger->log(this->logger,CONTROL,"Fatal Error: Out of Ressources to greate interator while destroying IKE_SA-Manager"); + this->logger->log(this->logger,ERROR,"Fatal Error: Create of iterator while destroying IKE_SA-Manager failed"); return FAILED; } + this->logger->log(this->logger,CONTROL | MOST,"Set driveout flags for all stored IKE_SA's"); while (iterator->has_next(iterator)) { ike_sa_entry_t *entry; @@ -652,6 +709,8 @@ static status_t destroy(private_ike_sa_manager_t *this) entry->driveout_new_threads = TRUE; entry->driveout_waiting_threads = TRUE; } + + this->logger->log(this->logger,CONTROL | MOST,"Wait for all threads to leave IKE_SA's"); /* Step 2: wait until all are gone */ iterator->reset(iterator); while (iterator->has_next(iterator)) @@ -666,6 +725,7 @@ static status_t destroy(private_ike_sa_manager_t *this) pthread_cond_wait(&(entry->condvar), &(this->mutex)); } } + this->logger->log(this->logger,CONTROL | MOST,"Delete all IKE_SA's"); /* Step 3: delete all entries */ iterator->reset(iterator); while (iterator->has_next(iterator)) @@ -678,8 +738,11 @@ static status_t destroy(private_ike_sa_manager_t *this) list->destroy(list); pthread_mutex_unlock(&(this->mutex)); + + /* destroy logger at end */ + global_logger_manager->destroy_logger(global_logger_manager,this->logger); allocator_free(this); - + return SUCCESS; } @@ -704,17 +767,18 @@ ike_sa_manager_t *ike_sa_manager_create() this->delete_entry = delete_entry; /* initialize private variables */ - this->list = linked_list_create(); - if (this->list == NULL) + this->logger = global_logger_manager->create_logger(global_logger_manager,IKE_SA_MANAGER,NULL); + if (this->logger == NULL) { allocator_free(this); return NULL; } - this->logger = global_logger_manager->create_logger(global_logger_manager,IKE_SA_MANAGER,NULL); - if (this->logger == NULL) + this->ike_sa_list = linked_list_create(); + if (this->ike_sa_list == NULL) { - this->list->destroy(this->list); + this->logger->log(this->logger,ERROR,"Fatal error: Failed to create list for managed IKE_SA"); + global_logger_manager->destroy_logger(global_logger_manager,this->logger); allocator_free(this); return NULL; } |