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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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**)¤t);
|
||||
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
@@ -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
|
||||
|
||||
@@ -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**)¤t);
|
||||
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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user