job management:

moved job code from thread_pool to job, jobs have an "execute" method now
  added two new jobs: delete_child_sa & rekey_child_sa
kernel interface:
  listens now for ACQUIRE & EXPIRE
  supports hard and soft lifetimes
  fires jobs for delete and rekey child sa
ike sa manager:
  can checkout IKE SAs by requid of owned CHILD SAs
we have now the infrastructure to do the rekeying... :-)
This commit is contained in:
Martin Willi
2006-05-31 14:23:15 +00:00
parent 6f2aba1322
commit 32b6500fbf
31 changed files with 930 additions and 739 deletions
+12 -4
View File
@@ -119,6 +119,14 @@ struct private_child_sa_t {
logger_t *logger;
};
/**
* Implements child_sa_t.get_reqid
*/
static u_int32_t get_reqid(private_child_sa_t *this)
{
return this->reqid;
}
/**
* Implements child_sa_t.alloc
*/
@@ -300,6 +308,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
src, dst,
spi, protocols[i],
this->reqid,
5, 30,
enc_algo, enc_key,
int_algo, int_key, mine);
/* clean up for next round */
@@ -316,8 +325,6 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
{
return FAILED;
}
}
}
return SUCCESS;
@@ -564,10 +571,11 @@ static void destroy(private_child_sa_t *this)
*/
child_sa_t * child_sa_create(host_t *me, host_t* other)
{
static u_int32_t reqid = 0xc0000000;
static u_int32_t reqid = 2000000000;
private_child_sa_t *this = malloc_thing(private_child_sa_t);
/* public functions */
this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
@@ -583,7 +591,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other)
this->my_esp_spi = 0;
this->other_ah_spi = 0;
this->other_esp_spi = 0;
this->reqid = reqid++;
this->reqid = ++reqid;
this->policies = linked_list_create();
return (&this->public);
+11
View File
@@ -58,6 +58,17 @@ typedef struct child_sa_t child_sa_t;
*/
struct child_sa_t {
/**
* @brief Get the unique reqid of the CHILD SA.
*
* Every CHILD_SA has a unique reqid, which is also
* stored down in the kernel.
*
* @param this calling object
* @return reqid of the CHILD SA
*/
u_int32_t (*get_reqid)(child_sa_t *this);
/**
* @brief Allocate SPIs for a given proposals.
*
+29 -5
View File
@@ -886,6 +886,28 @@ static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
this->child_sas->insert_last(this->child_sas, child_sa);
}
/**
* Implementation of ike_sa_t.get_child_sa.
*/
static child_sa_t *get_child_sa(private_ike_sa_t *this, u_int32_t reqid)
{
iterator_t *iterator;
child_sa_t *current, *found = NULL;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current);
if (current->get_reqid(current) == reqid)
{
found = current;
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of protected_ike_sa_t.reset_message_buffers.
*/
@@ -929,18 +951,19 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
return;
}
}
else
{
name = this->connection->get_name(this->connection);
}
my_host = this->connection->get_my_host(this->connection);
other_host = this->connection->get_other_host(this->connection);
/* use policy information, if available */
if (this->policy)
{
my_id = this->policy->get_my_id(this->policy);
other_id = this->policy->get_other_id(this->policy);
name = this->policy->get_name(this->policy);
}
else
{
name = this->connection->get_name(this->connection);
}
if (logger == NULL)
@@ -1116,6 +1139,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
/* Public functions */
this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection;
this->protected.public.get_child_sa = (child_sa_t*(*)(ike_sa_t*,u_int32_t))get_child_sa;
this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host;
+14 -1
View File
@@ -113,6 +113,19 @@ struct ike_sa_t {
*/
ike_sa_id_t* (*get_id) (ike_sa_t *this);
/**
* @brief Get the CHILD_SA with the specified reqid.
*
* The reqid is a unique ID for a child SA, which is
* generated on child SA creation.
* Returned child_sa_t object is not cloned!
*
* @param this calling object
* @param reqid reqid of the child SA, as used in the kernel
* @return child_sa, or NULL if not found
*/
child_sa_t* (*get_child_sa) (ike_sa_t *this, u_int32_t reqid);
/**
* @brief Get local peer address of the IKE_SA.
*
@@ -184,7 +197,7 @@ struct ike_sa_t {
* @brief Initiates the deletion of an IKE_SA.
*
* Sends a delete message to the remote peer and waits for
* its response. If the response comes in, or a timeout occur,
* its response. If the response comes in, or a timeout occurs,
* the IKE SA gets deleted.
*
* @param this calling object
+43 -52
View File
@@ -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;
ike_sa_entry_t *entry;
iterator->current(iterator, (void**)&current);
sa_me = current->ike_sa->get_my_host(current->ike_sa);
sa_other = current->ike_sa->get_other_host(current->ike_sa);
/* 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;
+12 -12
View File
@@ -81,21 +81,21 @@ struct ike_sa_manager_t {
void (*create_and_checkout) (ike_sa_manager_t* this,ike_sa_t **ike_sa);
/**
* @brief Check out an IKE_SA, defined be the two peers.
*
* Checking out an IKE_SA by their peer addresses may be necessary
* for kernel traps, status querying and so on... one of the hosts
* may be 0.0.0.0 (defaultroute/any), but not both.
*
* @param this the manager object
* @param me host on local side
* @param other host on remote side
* @brief Check out an IKE_SA by the reqid of one of its CHILD_SAs.
*
* The kernel sends us expire messages for IPsec SAs. To fullfill
* this request, we must check out the IKE SA which contains the
* CHILD_SA the kernel wants to modify. We do this by the reqid, which
* is unique to every CHILD_SA.
*
* @param this the manager object
* @param reqid reqid of the IPsec SA
* @param ike_sa[out] checked out SA
* @return
* - NOT_FOUND, if no such SA found
* - SUCCESS, if SA found and ike_sa set appropriatly
* - NOT_FOUND, if no IKE SA with such a child found
* - SUCCESS, if ike_sa set
*/
status_t (*checkout_by_hosts) (ike_sa_manager_t* this, host_t *me, host_t *other, ike_sa_t **ike_sa);
status_t (*checkout_by_reqid) (ike_sa_manager_t* this, u_int32_t reqid, ike_sa_t **ike_sa);
/**
* @brief Get a list of all IKE_SA SAs currently set up.