diff options
Diffstat (limited to 'src/charon/sa/ike_sa_manager.c')
-rw-r--r-- | src/charon/sa/ike_sa_manager.c | 95 |
1 files changed, 43 insertions, 52 deletions
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 9f09a8683..d38987dab 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -392,19 +392,19 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, /* we SHOULD have an IKE_SA for these SPIs in the list, * if not, we can't handle the request... */ - ike_sa_entry_t *entry; - /* look for the entry */ - if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) - { - /* can we give this ike_sa out to new requesters?*/ - if (entry->driveout_new_threads) - { - this->logger->log(this->logger, CONTROL|LEVEL1, "Drive out new thread for existing IKE_SA"); - /* no we can't */ - retval = NOT_FOUND; - } - else - { + ike_sa_entry_t *entry; + /* look for the entry */ + if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) + { + /* can we give this ike_sa out to new requesters?*/ + if (entry->driveout_new_threads) + { + this->logger->log(this->logger, CONTROL|LEVEL1, "Drive out new thread for existing IKE_SA"); + /* no we can't */ + retval = NOT_FOUND; + } + else + { /* is this IKE_SA already checked out ?? * are we welcome to get this SA ? */ while (entry->checked_out && !entry->driveout_waiting_threads) @@ -489,64 +489,55 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, } /** - * Implementation of of ike_sa_manager.checkout_by_hosts. + * Implementation of of ike_sa_manager.checkout_by_reqid. */ -static status_t checkout_by_hosts(private_ike_sa_manager_t *this, host_t *me, host_t *other, ike_sa_t **ike_sa) +static status_t checkout_by_reqid(private_ike_sa_manager_t *this, u_int32_t reqid, ike_sa_t **ike_sa) { iterator_t *iterator; - ike_sa_id_t *ike_sa_id = NULL; + status_t status = NOT_FOUND; pthread_mutex_lock(&(this->mutex)); iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); while (iterator->has_next(iterator)) { - ike_sa_entry_t *current; - host_t *sa_me, *sa_other; - - iterator->current(iterator, (void**)¤t); - sa_me = current->ike_sa->get_my_host(current->ike_sa); - sa_other = current->ike_sa->get_other_host(current->ike_sa); + ike_sa_entry_t *entry; - /* one end may be default/any, but not both */ - if (me->is_anyaddr(me)) + iterator->current(iterator, (void**)&entry); + if (entry->driveout_new_threads) { - if (other->is_anyaddr(other)) - { - break; - } - if (other->equals(other, sa_other)) - { - /* other matches */ - ike_sa_id = current->ike_sa_id; - } + /* we are not allowed to get this, get next one */ + continue; } - else if (other->is_anyaddr(other)) + while (entry->checked_out && !entry->driveout_waiting_threads) { - if (me->equals(me, sa_me)) - { - /* ME matches */ - ike_sa_id = current->ike_sa_id; - } + /* so wait until we can get it for us. + * we register us as waiting. */ + entry->waiting_threads++; + pthread_cond_wait(&(entry->condvar), &(this->mutex)); + entry->waiting_threads--; } - else + /* hm, a deletion request forbids us to get this SA, get next one */ + if (entry->driveout_waiting_threads) { - if (me->equals(me, sa_me) && other->equals(other, sa_other)) - { - /* both matches */ - ike_sa_id = current->ike_sa_id; - } + /* we must signal here, others may be waiting on it, too */ + pthread_cond_signal(&(entry->condvar)); + continue; + } + /* ok, access is exclusive for us, check reqid */ + if (entry->ike_sa->get_child_sa(entry->ike_sa, reqid) != NULL) + { + /* match */ + entry->checked_out = TRUE; + *ike_sa = entry->ike_sa; + status = SUCCESS; + break; } } iterator->destroy(iterator); pthread_mutex_unlock(&(this->mutex)); - if (ike_sa_id) - { - /* checkout is done in the checkout function, since its rather complex */ - return checkout(this, ike_sa_id, ike_sa); - } - return NOT_FOUND; + return status; } /** @@ -840,7 +831,7 @@ ike_sa_manager_t *ike_sa_manager_create() this->public.destroy = (void(*)(ike_sa_manager_t*))destroy; this->public.create_and_checkout = (void(*)(ike_sa_manager_t*,ike_sa_t**))create_and_checkout; this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t*,ike_sa_t**))checkout; - this->public.checkout_by_hosts = (status_t(*)(ike_sa_manager_t*,host_t*,host_t*,ike_sa_t**))checkout_by_hosts; + this->public.checkout_by_reqid = (status_t(*)(ike_sa_manager_t*,u_int32_t,ike_sa_t**))checkout_by_reqid; this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list; this->public.get_ike_sa_list_by_name = (linked_list_t*(*)(ike_sa_manager_t*,const char*))get_ike_sa_list_by_name; this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status; |