mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-09 00:00:53 -04:00
added IKE_SA_INIT retransmission detection
fixed thread exhaustion when IKE_SA is blocked for a longer time
This commit is contained in:
parent
891e69944f
commit
b9e363f86f
@ -57,12 +57,9 @@ static job_type_t get_type(private_process_message_job_t *this)
|
|||||||
static status_t execute(private_process_message_job_t *this)
|
static status_t execute(private_process_message_job_t *this)
|
||||||
{
|
{
|
||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
ike_sa_id_t *ike_sa_id;
|
|
||||||
|
|
||||||
ike_sa_id = this->message->get_ike_sa_id(this->message);
|
ike_sa = charon->ike_sa_manager->checkout_by_message(charon->ike_sa_manager,
|
||||||
ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
this->message);
|
||||||
ike_sa_id->switch_initiator(ike_sa_id);
|
|
||||||
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, ike_sa_id);
|
|
||||||
if (ike_sa)
|
if (ike_sa)
|
||||||
{
|
{
|
||||||
DBG1(DBG_NET, "received packet: from %#H to %#H",
|
DBG1(DBG_NET, "received packet: from %#H to %#H",
|
||||||
@ -80,10 +77,10 @@ static status_t execute(private_process_message_job_t *this)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG1(DBG_NET, "received packet from %#H for IKE_SA: %J, but no such "
|
DBG1(DBG_NET, "unable to handle message from %#H for IKE_SA: %J",
|
||||||
"IKE_SA", this->message->get_source(this->message), ike_sa_id);
|
this->message->get_source(this->message),
|
||||||
|
this->message->get_ike_sa_id(this->message));
|
||||||
}
|
}
|
||||||
ike_sa_id->destroy(ike_sa_id);
|
|
||||||
return DESTROY_ME;
|
return DESTROY_ME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,14 +1088,11 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
|
|||||||
/* create a new IKE_SA if we have to route or to restart */
|
/* create a new IKE_SA if we have to route or to restart */
|
||||||
if (to_route->get_count(to_route) || to_restart->get_count(to_restart))
|
if (to_route->get_count(to_route) || to_restart->get_count(to_restart))
|
||||||
{
|
{
|
||||||
ike_sa_id_t *other_id;
|
|
||||||
private_ike_sa_t *new;
|
private_ike_sa_t *new;
|
||||||
task_t *task;
|
task_t *task;
|
||||||
|
|
||||||
other_id = ike_sa_id_create(0, 0, TRUE);
|
new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
|
||||||
new = (private_ike_sa_t*)charon->ike_sa_manager->checkout(
|
charon->ike_sa_manager, TRUE);
|
||||||
charon->ike_sa_manager, other_id);
|
|
||||||
other_id->destroy(other_id);
|
|
||||||
|
|
||||||
apply_config(new, this->connection, this->policy);
|
apply_config(new, this->connection, this->policy);
|
||||||
/* use actual used host, not the wildcarded one in connection */
|
/* use actual used host, not the wildcarded one in connection */
|
||||||
@ -1542,7 +1539,6 @@ static status_t rekey(private_ike_sa_t *this)
|
|||||||
*/
|
*/
|
||||||
static void reestablish(private_ike_sa_t *this)
|
static void reestablish(private_ike_sa_t *this)
|
||||||
{
|
{
|
||||||
ike_sa_id_t *other_id;
|
|
||||||
private_ike_sa_t *other;
|
private_ike_sa_t *other;
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
@ -1550,10 +1546,8 @@ static void reestablish(private_ike_sa_t *this)
|
|||||||
task_t *task;
|
task_t *task;
|
||||||
job_t *job;
|
job_t *job;
|
||||||
|
|
||||||
other_id = ike_sa_id_create(0, 0, TRUE);
|
other = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
|
||||||
other = (private_ike_sa_t*)charon->ike_sa_manager->checkout(
|
charon->ike_sa_manager, TRUE);
|
||||||
charon->ike_sa_manager, other_id);
|
|
||||||
other_id->destroy(other_id);
|
|
||||||
|
|
||||||
apply_config(other, this->connection, this->policy);
|
apply_config(other, this->connection, this->policy);
|
||||||
other->other_host->destroy(other->other_host);
|
other->other_host->destroy(other->other_host);
|
||||||
|
@ -72,6 +72,16 @@ struct entry_t {
|
|||||||
* The contained ike_sa_t object.
|
* The contained ike_sa_t object.
|
||||||
*/
|
*/
|
||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hash of the IKE_SA_INIT message, used to detect retransmissions
|
||||||
|
*/
|
||||||
|
chunk_t init_hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message ID currently processing, if any
|
||||||
|
*/
|
||||||
|
u_int32_t message_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,6 +92,7 @@ static status_t entry_destroy(entry_t *this)
|
|||||||
/* also destroy IKE SA */
|
/* also destroy IKE SA */
|
||||||
this->ike_sa->destroy(this->ike_sa);
|
this->ike_sa->destroy(this->ike_sa);
|
||||||
this->ike_sa_id->destroy(this->ike_sa_id);
|
this->ike_sa_id->destroy(this->ike_sa_id);
|
||||||
|
chunk_free(&this->init_hash);
|
||||||
free(this);
|
free(this);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
@ -94,12 +105,14 @@ static entry_t *entry_create(ike_sa_id_t *ike_sa_id)
|
|||||||
entry_t *this = malloc_thing(entry_t);
|
entry_t *this = malloc_thing(entry_t);
|
||||||
|
|
||||||
this->waiting_threads = 0;
|
this->waiting_threads = 0;
|
||||||
pthread_cond_init(&(this->condvar), NULL);
|
pthread_cond_init(&this->condvar, NULL);
|
||||||
|
|
||||||
/* we set checkout flag when we really give it out */
|
/* we set checkout flag when we really give it out */
|
||||||
this->checked_out = FALSE;
|
this->checked_out = FALSE;
|
||||||
this->driveout_new_threads = FALSE;
|
this->driveout_new_threads = FALSE;
|
||||||
this->driveout_waiting_threads = FALSE;
|
this->driveout_waiting_threads = FALSE;
|
||||||
|
this->message_id = -1;
|
||||||
|
this->init_hash = chunk_empty;
|
||||||
|
|
||||||
/* ike_sa_id is always cloned */
|
/* ike_sa_id is always cloned */
|
||||||
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
||||||
@ -136,6 +149,11 @@ struct private_ike_sa_manager_t {
|
|||||||
* A randomizer, to get random SPIs for our side
|
* A randomizer, to get random SPIs for our side
|
||||||
*/
|
*/
|
||||||
randomizer_t *randomizer;
|
randomizer_t *randomizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SHA1 hasher for IKE_SA_INIT retransmit detection
|
||||||
|
*/
|
||||||
|
hasher_t *hasher;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,7 +287,7 @@ static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry)
|
|||||||
while (entry->checked_out && !entry->driveout_waiting_threads)
|
while (entry->checked_out && !entry->driveout_waiting_threads)
|
||||||
{
|
{
|
||||||
/* so wait until we can get it for us.
|
/* so wait until we can get it for us.
|
||||||
* we register us as waiting. */
|
* we register us as waiting. */
|
||||||
entry->waiting_threads++;
|
entry->waiting_threads++;
|
||||||
pthread_cond_wait(&(entry->condvar), &(this->mutex));
|
pthread_cond_wait(&(entry->condvar), &(this->mutex));
|
||||||
entry->waiting_threads--;
|
entry->waiting_threads--;
|
||||||
@ -291,8 +309,8 @@ static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
|
|||||||
{
|
{
|
||||||
u_int64_t spi;
|
u_int64_t spi;
|
||||||
|
|
||||||
this->randomizer->get_pseudo_random_bytes(this->randomizer, 8, (u_int8_t*)&spi);
|
this->randomizer->get_pseudo_random_bytes(this->randomizer, sizeof(spi),
|
||||||
|
(u_int8_t*)&spi);
|
||||||
return spi;
|
return spi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,119 +319,156 @@ static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
|
|||||||
*/
|
*/
|
||||||
static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
|
static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
|
||||||
{
|
{
|
||||||
bool responder_spi_set;
|
|
||||||
bool initiator_spi_set;
|
|
||||||
bool original_initiator;
|
|
||||||
ike_sa_t *ike_sa = NULL;
|
ike_sa_t *ike_sa = NULL;
|
||||||
|
entry_t *entry;
|
||||||
|
|
||||||
DBG2(DBG_MGR, "checkout IKE_SA: %J", ike_sa_id);
|
DBG2(DBG_MGR, "checkout IKE_SA: %J, %d IKE_SAs in manager",
|
||||||
|
ike_sa_id, this->ike_sa_list->get_count(this->ike_sa_list));
|
||||||
|
|
||||||
DBG2(DBG_MGR, "%d IKE_SAs in manager",
|
|
||||||
this->ike_sa_list->get_count(this->ike_sa_list));
|
|
||||||
|
|
||||||
/* each access is locked */
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
||||||
responder_spi_set = ike_sa_id->get_responder_spi(ike_sa_id);
|
|
||||||
initiator_spi_set = ike_sa_id->get_initiator_spi(ike_sa_id);
|
|
||||||
original_initiator = ike_sa_id->is_initiator(ike_sa_id);
|
|
||||||
|
|
||||||
if ((initiator_spi_set && responder_spi_set) ||
|
|
||||||
((initiator_spi_set && !responder_spi_set) && (original_initiator)))
|
|
||||||
{
|
{
|
||||||
/* we SHOULD have an IKE_SA for these SPIs in the list,
|
if (wait_for_entry(this, entry))
|
||||||
* if not, we can't handle the request...
|
|
||||||
*/
|
|
||||||
entry_t *entry;
|
|
||||||
/* look for the entry */
|
|
||||||
if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
|
||||||
{
|
{
|
||||||
if (wait_for_entry(this, entry))
|
DBG2(DBG_MGR, "IKE_SA successfully checked out");
|
||||||
{
|
entry->checked_out = TRUE;
|
||||||
DBG2(DBG_MGR, "IKE_SA successfully checked out");
|
ike_sa = entry->ike_sa;
|
||||||
/* ok, this IKE_SA is finally ours */
|
|
||||||
entry->checked_out = TRUE;
|
|
||||||
ike_sa = entry->ike_sa;
|
|
||||||
/* update responder SPI when it's not set */
|
|
||||||
if (entry->ike_sa_id->get_responder_spi(entry->ike_sa_id) == 0)
|
|
||||||
{
|
|
||||||
ike_sa_id_t *ike_sa_ike_sa_id = ike_sa->get_id(ike_sa);
|
|
||||||
u_int64_t spi = ike_sa_id->get_responder_spi(ike_sa_id);
|
|
||||||
|
|
||||||
ike_sa_ike_sa_id->set_responder_spi(ike_sa_ike_sa_id, spi);
|
|
||||||
entry->ike_sa_id->set_responder_spi(entry->ike_sa_id, spi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG2(DBG_MGR, "IKE_SA found, but not allowed to check it out");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG2(DBG_MGR, "IKE_SA not stored in list");
|
|
||||||
/* looks like there is no such IKE_SA, better luck next time... */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((initiator_spi_set && !responder_spi_set) && (!original_initiator))
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
charon->bus->set_sa(charon->bus, ike_sa);
|
||||||
|
return ike_sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of of ike_sa_manager.checkout_new.
|
||||||
|
*/
|
||||||
|
static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
|
||||||
|
{
|
||||||
|
entry_t *entry;
|
||||||
|
ike_sa_id_t *id;
|
||||||
|
|
||||||
|
if (initiator)
|
||||||
{
|
{
|
||||||
/* an IKE_SA_INIT from an another endpoint,
|
id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
|
||||||
* he is the initiator.
|
|
||||||
* For simplicity, we do NOT check for retransmitted
|
|
||||||
* IKE_SA_INIT-Requests here, so EVERY single IKE_SA_INIT-
|
|
||||||
* Request (even a retransmitted one) will result in a
|
|
||||||
* IKE_SA. This could be improved...
|
|
||||||
*/
|
|
||||||
u_int64_t responder_spi;
|
|
||||||
entry_t *new_entry;
|
|
||||||
|
|
||||||
/* set SPIs, we are the responder */
|
|
||||||
responder_spi = get_next_spi(this);
|
|
||||||
|
|
||||||
/* we also set arguments spi, so its still valid */
|
|
||||||
ike_sa_id->set_responder_spi(ike_sa_id, responder_spi);
|
|
||||||
|
|
||||||
/* create entry */
|
|
||||||
new_entry = entry_create(ike_sa_id);
|
|
||||||
|
|
||||||
this->ike_sa_list->insert_last(this->ike_sa_list, new_entry);
|
|
||||||
|
|
||||||
/* check ike_sa out */
|
|
||||||
DBG2(DBG_MGR, "IKE_SA added to list of known IKE_SAs");
|
|
||||||
new_entry->checked_out = TRUE;
|
|
||||||
ike_sa = new_entry->ike_sa;
|
|
||||||
}
|
|
||||||
else if (!initiator_spi_set && !responder_spi_set)
|
|
||||||
{
|
|
||||||
/* checkout of a new and unused IKE_SA, used for rekeying */
|
|
||||||
entry_t *new_entry;
|
|
||||||
|
|
||||||
if (original_initiator)
|
|
||||||
{
|
|
||||||
ike_sa_id->set_initiator_spi(ike_sa_id, get_next_spi(this));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ike_sa_id->set_responder_spi(ike_sa_id, get_next_spi(this));
|
|
||||||
}
|
|
||||||
/* create entry */
|
|
||||||
new_entry = entry_create(ike_sa_id);
|
|
||||||
DBG2(DBG_MGR, "created IKE_SA: %J", ike_sa_id);
|
|
||||||
|
|
||||||
this->ike_sa_list->insert_last(this->ike_sa_list, new_entry);
|
|
||||||
|
|
||||||
/* check ike_sa out */
|
|
||||||
new_entry->checked_out = TRUE;
|
|
||||||
ike_sa = new_entry->ike_sa;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* responder set, initiator not: here is something seriously wrong! */
|
id = ike_sa_id_create(0, get_next_spi(this), FALSE);
|
||||||
DBG2(DBG_MGR, "invalid IKE_SA SPIs");
|
}
|
||||||
|
entry = entry_create(id);
|
||||||
|
pthread_mutex_lock(&this->mutex);
|
||||||
|
this->ike_sa_list->insert_last(this->ike_sa_list, entry);
|
||||||
|
entry->checked_out = TRUE;
|
||||||
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
DBG2(DBG_MGR, "created IKE_SA: %J, %d IKE_SAs in manager",
|
||||||
|
id, this->ike_sa_list->get_count(this->ike_sa_list));
|
||||||
|
return entry->ike_sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of of ike_sa_manager.checkout_by_id.
|
||||||
|
*/
|
||||||
|
static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
|
||||||
|
message_t *message)
|
||||||
|
{
|
||||||
|
entry_t *entry;
|
||||||
|
ike_sa_t *ike_sa = NULL;
|
||||||
|
ike_sa_id_t *id = message->get_ike_sa_id(message);
|
||||||
|
id = id->clone(id);
|
||||||
|
id->switch_initiator(id);
|
||||||
|
|
||||||
|
DBG2(DBG_MGR, "checkout IKE_SA: %J by message, %d IKE_SAs in manager",
|
||||||
|
id, this->ike_sa_list->get_count(this->ike_sa_list));
|
||||||
|
|
||||||
|
if (message->get_request(message) &&
|
||||||
|
message->get_exchange_type(message) == IKE_SA_INIT)
|
||||||
|
{
|
||||||
|
/* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
|
||||||
|
iterator_t *iterator;
|
||||||
|
chunk_t data, hash;
|
||||||
|
bool occupied = FALSE;
|
||||||
|
|
||||||
|
data = message->get_packet_data(message);
|
||||||
|
this->hasher->allocate_hash(this->hasher, data, &hash);
|
||||||
|
chunk_free(&data);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&this->mutex);
|
||||||
|
iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
|
||||||
|
while (iterator->iterate(iterator, (void**)&entry))
|
||||||
|
{
|
||||||
|
if (chunk_equals(hash, entry->init_hash))
|
||||||
|
{
|
||||||
|
if (entry->message_id == 0)
|
||||||
|
{
|
||||||
|
occupied = TRUE;
|
||||||
|
}
|
||||||
|
else if (wait_for_entry(this, entry))
|
||||||
|
{
|
||||||
|
DBG2(DBG_MGR, "IKE_SA checked out by hash");
|
||||||
|
entry->checked_out = TRUE;
|
||||||
|
entry->message_id = message->get_message_id(message);
|
||||||
|
ike_sa = entry->ike_sa;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
if (occupied)
|
||||||
|
{
|
||||||
|
/* already processing this message ID, discard */
|
||||||
|
chunk_free(&hash);
|
||||||
|
id->destroy(id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ike_sa == NULL)
|
||||||
|
{
|
||||||
|
/* no IKE_SA found, create a new one */
|
||||||
|
id->set_responder_spi(id, get_next_spi(this));
|
||||||
|
entry = entry_create(id);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&this->mutex);
|
||||||
|
this->ike_sa_list->insert_last(this->ike_sa_list, entry);
|
||||||
|
entry->checked_out = TRUE;
|
||||||
|
entry->message_id = message->get_message_id(message);
|
||||||
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
entry->init_hash = hash;
|
||||||
|
ike_sa = entry->ike_sa;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk_free(&hash);
|
||||||
|
}
|
||||||
|
id->destroy(id);
|
||||||
|
charon->bus->set_sa(charon->bus, ike_sa);
|
||||||
|
return ike_sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
if (get_entry_by_id(this, id, &entry) == SUCCESS)
|
||||||
|
{
|
||||||
|
/* only check out if we are not processing this request */
|
||||||
|
if (message->get_request(message) &&
|
||||||
|
message->get_message_id(message) == entry->message_id)
|
||||||
|
{
|
||||||
|
DBG2(DBG_MGR, "not checking out, message already processing");
|
||||||
|
}
|
||||||
|
else if (wait_for_entry(this, entry))
|
||||||
|
{
|
||||||
|
ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
|
||||||
|
DBG2(DBG_MGR, "IKE_SA successfully checked out");
|
||||||
|
entry->checked_out = TRUE;
|
||||||
|
entry->message_id = message->get_message_id(message);
|
||||||
|
if (ike_id->get_responder_spi(ike_id) == 0)
|
||||||
|
{
|
||||||
|
ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
|
||||||
|
}
|
||||||
|
ike_sa = entry->ike_sa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
id->destroy(id);
|
||||||
charon->bus->set_sa(charon->bus, ike_sa);
|
charon->bus->set_sa(charon->bus, ike_sa);
|
||||||
return ike_sa;
|
return ike_sa;
|
||||||
}
|
}
|
||||||
@ -669,6 +724,7 @@ 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));
|
entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
|
||||||
/* signal waiting threads */
|
/* signal waiting threads */
|
||||||
entry->checked_out = FALSE;
|
entry->checked_out = FALSE;
|
||||||
|
entry->message_id = -1;
|
||||||
DBG2(DBG_MGR, "check-in of IKE_SA successful.");
|
DBG2(DBG_MGR, "check-in of IKE_SA successful.");
|
||||||
pthread_cond_signal(&(entry->condvar));
|
pthread_cond_signal(&(entry->condvar));
|
||||||
retval = SUCCESS;
|
retval = SUCCESS;
|
||||||
@ -816,6 +872,7 @@ static void destroy(private_ike_sa_manager_t *this)
|
|||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_unlock(&(this->mutex));
|
||||||
|
|
||||||
this->randomizer->destroy(this->randomizer);
|
this->randomizer->destroy(this->randomizer);
|
||||||
|
this->hasher->destroy(this->hasher);
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@ -830,6 +887,8 @@ ike_sa_manager_t *ike_sa_manager_create()
|
|||||||
/* assign public functions */
|
/* assign public functions */
|
||||||
this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
|
this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
|
||||||
this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
|
this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
|
||||||
|
this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
|
||||||
|
this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
|
||||||
this->public.checkout_by_peer = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_peer;
|
this->public.checkout_by_peer = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_peer;
|
||||||
this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
|
this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
|
||||||
this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
|
this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
|
||||||
@ -842,6 +901,7 @@ ike_sa_manager_t *ike_sa_manager_create()
|
|||||||
this->ike_sa_list = linked_list_create();
|
this->ike_sa_list = linked_list_create();
|
||||||
pthread_mutex_init(&this->mutex, NULL);
|
pthread_mutex_init(&this->mutex, NULL);
|
||||||
this->randomizer = randomizer_create();
|
this->randomizer = randomizer_create();
|
||||||
|
this->hasher = hasher_create(HASH_SHA1);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ typedef struct ike_sa_manager_t ike_sa_manager_t;
|
|||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <sa/ike_sa.h>
|
#include <sa/ike_sa.h>
|
||||||
|
#include <encoding/message.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's.
|
* @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's.
|
||||||
@ -47,25 +48,51 @@ typedef struct ike_sa_manager_t ike_sa_manager_t;
|
|||||||
* @ingroup sa
|
* @ingroup sa
|
||||||
*/
|
*/
|
||||||
struct ike_sa_manager_t {
|
struct ike_sa_manager_t {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checkout an IKE_SA, create it when necesarry.
|
* @brief Checkout an existing IKE_SA.
|
||||||
*
|
|
||||||
* Checks out a SA by its ID. An SA will be created, when the responder
|
|
||||||
* SPI is not set (when received an IKE_SA_INIT from initiator).
|
|
||||||
* Management of SPIs is the managers job, he will set it.
|
|
||||||
* This function blocks until SA is available for checkout.
|
|
||||||
*
|
|
||||||
* @warning checking out two times without checking in will
|
|
||||||
* result in a deadlock!
|
|
||||||
*
|
*
|
||||||
* @param this the manager object
|
* @param this the manager object
|
||||||
* @param ike_sa_id the SA identifier, will be updated
|
* @param ike_sa_id the SA identifier, will be updated
|
||||||
* @returns
|
* @returns
|
||||||
* - checked out IKE_SA if found
|
* - checked out IKE_SA if found
|
||||||
* - NULL, if no such IKE_SA available
|
* - NULL, if specified IKE_SA is not found.
|
||||||
*/
|
*/
|
||||||
ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id);
|
ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create and check out a new IKE_SA.
|
||||||
|
*
|
||||||
|
* @param this the manager object
|
||||||
|
* @param initiator TRUE for initiator, FALSE otherwise
|
||||||
|
* @returns created andchecked out IKE_SA
|
||||||
|
*/
|
||||||
|
ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checkout an IKE_SA by a message.
|
||||||
|
*
|
||||||
|
* In some situations, it is necessary that the manager knows the
|
||||||
|
* message to use for the checkout. This has the folloing reasons:
|
||||||
|
*
|
||||||
|
* 1. If the targeted IKE_SA is already processing a message, we do not
|
||||||
|
* check it out if the message ID is the same.
|
||||||
|
* 2. If it is an IKE_SA_INIT request, we have to check if it is a
|
||||||
|
* retransmission. If so, we have to drop the message, we would
|
||||||
|
* create another unneded IKE_SA for each retransmitted packet.
|
||||||
|
*
|
||||||
|
* A call to checkout_by_message() returns a (maybe new created) IKE_SA.
|
||||||
|
* If processing the message does not make sense (for the reasons above),
|
||||||
|
* NULL is returned.
|
||||||
|
*
|
||||||
|
* @param this the manager object
|
||||||
|
* @param ike_sa_id the SA identifier, will be updated
|
||||||
|
* @returns
|
||||||
|
* - checked out/created IKE_SA
|
||||||
|
* - NULL to not process message further
|
||||||
|
*/
|
||||||
|
ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checkout an existing IKE_SA by hosts and identifications.
|
* @brief Checkout an existing IKE_SA by hosts and identifications.
|
||||||
*
|
*
|
||||||
|
@ -75,11 +75,9 @@ static status_t build_i(private_ike_rekey_t *this, message_t *message)
|
|||||||
{
|
{
|
||||||
connection_t *connection;
|
connection_t *connection;
|
||||||
policy_t *policy;
|
policy_t *policy;
|
||||||
ike_sa_id_t *id;
|
|
||||||
|
|
||||||
id = ike_sa_id_create(0, 0, TRUE);
|
this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
|
||||||
this->new_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
|
TRUE);
|
||||||
id->destroy(id);
|
|
||||||
|
|
||||||
connection = this->ike_sa->get_connection(this->ike_sa);
|
connection = this->ike_sa->get_connection(this->ike_sa);
|
||||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
policy = this->ike_sa->get_policy(this->ike_sa);
|
||||||
@ -101,7 +99,6 @@ static status_t process_r(private_ike_rekey_t *this, message_t *message)
|
|||||||
{
|
{
|
||||||
connection_t *connection;
|
connection_t *connection;
|
||||||
policy_t *policy;
|
policy_t *policy;
|
||||||
ike_sa_id_t *id;
|
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
|
|
||||||
@ -129,9 +126,8 @@ static status_t process_r(private_ike_rekey_t *this, message_t *message)
|
|||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
id = ike_sa_id_create(0, 0, FALSE);
|
this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
|
||||||
this->new_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
|
FALSE);
|
||||||
id->destroy(id);
|
|
||||||
|
|
||||||
connection = this->ike_sa->get_connection(this->ike_sa);
|
connection = this->ike_sa->get_connection(this->ike_sa);
|
||||||
policy = this->ike_sa->get_policy(this->ike_sa);
|
policy = this->ike_sa->get_policy(this->ike_sa);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user