further work done for simultaneous rekeying/delete
still some cases which cause trouble
This commit is contained in:
@@ -138,34 +138,18 @@ static packet_t *clone(private_packet_t *this)
|
|||||||
{
|
{
|
||||||
other->destination = this->destination->clone(this->destination);
|
other->destination = this->destination->clone(this->destination);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
other->destination = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->source != NULL)
|
if (this->source != NULL)
|
||||||
{
|
{
|
||||||
other->source = this->source->clone(this->source);
|
other->source = this->source->clone(this->source);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
other->source = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only clone existing chunks :-) */
|
|
||||||
if (this->data.ptr != NULL)
|
if (this->data.ptr != NULL)
|
||||||
{
|
{
|
||||||
other->data.ptr = clalloc(this->data.ptr,this->data.len);
|
other->data.ptr = clalloc(this->data.ptr,this->data.len);
|
||||||
other->data.len = this->data.len;
|
other->data.len = this->data.len;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
other->data = CHUNK_INITIALIZER;
|
|
||||||
}
|
|
||||||
return &(other->public);
|
return &(other->public);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Documented in header
|
* Documented in header
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,12 +34,9 @@
|
|||||||
typedef struct event_t event_t;
|
typedef struct event_t event_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Represents an event as it is stored in the event queue.
|
* Event containing a job and a schedule time
|
||||||
*
|
|
||||||
* A event consists of a event time and an assigned job object.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
struct event_t{
|
struct event_t {
|
||||||
/**
|
/**
|
||||||
* Time to fire the event.
|
* Time to fire the event.
|
||||||
*/
|
*/
|
||||||
@@ -49,48 +46,12 @@ struct event_t{
|
|||||||
* Every event has its assigned job.
|
* Every event has its assigned job.
|
||||||
*/
|
*/
|
||||||
job_t * job;
|
job_t * job;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroys a event_t object.
|
|
||||||
*
|
|
||||||
* @param event_t calling object
|
|
||||||
*/
|
|
||||||
void (*destroy) (event_t *event);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* implements event_t.destroy
|
|
||||||
*/
|
|
||||||
static void event_destroy(event_t *event)
|
|
||||||
{
|
|
||||||
free(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Creates a event for a specific time
|
|
||||||
*
|
|
||||||
* @param time absolute time to fire the event
|
|
||||||
* @param job job to add to job-queue at specific time
|
|
||||||
*
|
|
||||||
* @returns created event_t object
|
|
||||||
*/
|
|
||||||
static event_t *event_create(timeval_t time, job_t *job)
|
|
||||||
{
|
|
||||||
event_t *this = malloc_thing(event_t);
|
|
||||||
|
|
||||||
this->destroy = event_destroy;
|
|
||||||
this->time = time;
|
|
||||||
this->job = job;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct private_event_queue_t private_event_queue_t;
|
typedef struct private_event_queue_t private_event_queue_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private Variables and Functions of event_queue_t class.
|
* Private Variables and Functions of event_queue_t class.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
struct private_event_queue_t {
|
struct private_event_queue_t {
|
||||||
/**
|
/**
|
||||||
@@ -155,7 +116,7 @@ static job_t *get(private_event_queue_t *this)
|
|||||||
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
|
||||||
while (1)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
while(this->list->get_count(this->list) == 0)
|
while(this->list->get_count(this->list) == 0)
|
||||||
{
|
{
|
||||||
@@ -170,7 +131,7 @@ static job_t *get(private_event_queue_t *this)
|
|||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->list->get_first(this->list,(void **) &next_event);
|
this->list->get_first(this->list, (void **)&next_event);
|
||||||
|
|
||||||
gettimeofday(¤t_time, NULL);
|
gettimeofday(¤t_time, NULL);
|
||||||
long difference = time_difference(¤t_time,&(next_event->time));
|
long difference = time_difference(¤t_time,&(next_event->time));
|
||||||
@@ -192,11 +153,9 @@ static job_t *get(private_event_queue_t *this)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* event available */
|
/* event available */
|
||||||
this->list->remove_first(this->list,(void **) &next_event);
|
this->list->remove_first(this->list, (void **)&next_event);
|
||||||
|
|
||||||
job = next_event->job;
|
job = next_event->job;
|
||||||
|
free(next_event);
|
||||||
next_event->destroy(next_event);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,10 +171,15 @@ static job_t *get(private_event_queue_t *this)
|
|||||||
*/
|
*/
|
||||||
static void add_absolute(private_event_queue_t *this, job_t *job, timeval_t time)
|
static void add_absolute(private_event_queue_t *this, job_t *job, timeval_t time)
|
||||||
{
|
{
|
||||||
event_t *event = event_create(time,job);
|
event_t *event;
|
||||||
event_t *current_event;
|
event_t *current_event;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
|
/* create event */
|
||||||
|
event = malloc_thing(event_t);
|
||||||
|
event->time = time;
|
||||||
|
event->job = job;
|
||||||
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
|
||||||
/* while just used to break out */
|
/* while just used to break out */
|
||||||
@@ -298,24 +262,15 @@ static void add_relative(event_queue_t *this, job_t *job, u_int32_t ms)
|
|||||||
*/
|
*/
|
||||||
static void event_queue_destroy(private_event_queue_t *this)
|
static void event_queue_destroy(private_event_queue_t *this)
|
||||||
{
|
{
|
||||||
while (this->list->get_count(this->list) > 0)
|
event_t *event;
|
||||||
|
while (this->list->remove_last(this->list, (void**)&event) == SUCCESS)
|
||||||
{
|
{
|
||||||
event_t *event;
|
|
||||||
|
|
||||||
if (this->list->remove_first(this->list,(void *) &event) != SUCCESS)
|
|
||||||
{
|
|
||||||
this->list->destroy(this->list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
event->job->destroy(event->job);
|
event->job->destroy(event->job);
|
||||||
event->destroy(event);
|
free(event);
|
||||||
}
|
}
|
||||||
this->list->destroy(this->list);
|
this->list->destroy(this->list);
|
||||||
|
|
||||||
pthread_mutex_destroy(&(this->mutex));
|
pthread_mutex_destroy(&(this->mutex));
|
||||||
|
|
||||||
pthread_cond_destroy(&(this->condvar));
|
pthread_cond_destroy(&(this->condvar));
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ static job_t *get(private_job_queue_t *this)
|
|||||||
pthread_setcancelstate(oldstate, NULL);
|
pthread_setcancelstate(oldstate, NULL);
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
}
|
}
|
||||||
this->list->remove_first(this->list,(void **) &job);
|
this->list->remove_first(this->list, (void **)&job);
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_unlock(&(this->mutex));
|
||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
@@ -114,22 +114,14 @@ static void add(private_job_queue_t *this, job_t *job)
|
|||||||
*/
|
*/
|
||||||
static void job_queue_destroy (private_job_queue_t *this)
|
static void job_queue_destroy (private_job_queue_t *this)
|
||||||
{
|
{
|
||||||
while (this->list->get_count(this->list) > 0)
|
job_t *job;
|
||||||
|
while (this->list->remove_last(this->list, (void**)&job) == SUCCESS)
|
||||||
{
|
{
|
||||||
job_t *job;
|
|
||||||
if (this->list->remove_first(this->list,(void *) &job) != SUCCESS)
|
|
||||||
{
|
|
||||||
this->list->destroy(this->list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
job->destroy(job);
|
job->destroy(job);
|
||||||
}
|
}
|
||||||
this->list->destroy(this->list);
|
this->list->destroy(this->list);
|
||||||
|
|
||||||
pthread_mutex_destroy(&(this->mutex));
|
pthread_mutex_destroy(&(this->mutex));
|
||||||
|
|
||||||
pthread_cond_destroy(&(this->condvar));
|
pthread_cond_destroy(&(this->condvar));
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ struct private_send_queue_t {
|
|||||||
static int get_count(private_send_queue_t *this)
|
static int get_count(private_send_queue_t *this)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&this->mutex);
|
||||||
count = this->list->get_count(this->list);
|
count = this->list->get_count(this->list);
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_unlock(&this->mutex);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,22 +82,23 @@ static packet_t *get(private_send_queue_t *this)
|
|||||||
{
|
{
|
||||||
int oldstate;
|
int oldstate;
|
||||||
packet_t *packet;
|
packet_t *packet;
|
||||||
pthread_mutex_lock(&(this->mutex));
|
|
||||||
/* go to wait while no packets available */
|
|
||||||
|
|
||||||
|
pthread_mutex_lock(&this->mutex);
|
||||||
|
|
||||||
|
/* go to wait while no packets available */
|
||||||
while(this->list->get_count(this->list) == 0)
|
while(this->list->get_count(this->list) == 0)
|
||||||
{
|
{
|
||||||
/* add mutex unlock handler for cancellation, enable cancellation */
|
/* add mutex unlock handler for cancellation, enable cancellation */
|
||||||
pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex));
|
pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&this->mutex);
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
|
||||||
pthread_cond_wait( &(this->condvar), &(this->mutex));
|
pthread_cond_wait(&this->condvar, &this->mutex);
|
||||||
|
|
||||||
/* reset cancellation, remove mutex-unlock handler (without executing) */
|
/* reset cancellation, remove mutex-unlock handler (without executing) */
|
||||||
pthread_setcancelstate(oldstate, NULL);
|
pthread_setcancelstate(oldstate, NULL);
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
}
|
}
|
||||||
this->list->remove_first(this->list,(void **)&packet);
|
this->list->remove_first(this->list, (void**)&packet);
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_unlock(&this->mutex);
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,10 +115,10 @@ static void add(private_send_queue_t *this, packet_t *packet)
|
|||||||
src->get_address(src), src->get_port(src),
|
src->get_address(src), src->get_port(src),
|
||||||
dst->get_address(dst), dst->get_port(dst));
|
dst->get_address(dst), dst->get_port(dst));
|
||||||
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&this->mutex);
|
||||||
this->list->insert_last(this->list,packet);
|
this->list->insert_last(this->list, packet);
|
||||||
pthread_cond_signal( &(this->condvar));
|
pthread_cond_signal(&this->condvar);
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_unlock(&this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,24 +126,14 @@ static void add(private_send_queue_t *this, packet_t *packet)
|
|||||||
*/
|
*/
|
||||||
static void destroy (private_send_queue_t *this)
|
static void destroy (private_send_queue_t *this)
|
||||||
{
|
{
|
||||||
|
packet_t *packet;
|
||||||
/* destroy all packets in list before destroying list */
|
while (this->list->remove_last(this->list, (void**)&packet) == SUCCESS)
|
||||||
while (this->list->get_count(this->list) > 0)
|
|
||||||
{
|
{
|
||||||
packet_t *packet;
|
|
||||||
if (this->list->remove_first(this->list,(void *) &packet) != SUCCESS)
|
|
||||||
{
|
|
||||||
this->list->destroy(this->list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
packet->destroy(packet);
|
packet->destroy(packet);
|
||||||
}
|
}
|
||||||
this->list->destroy(this->list);
|
this->list->destroy(this->list);
|
||||||
|
|
||||||
pthread_mutex_destroy(&(this->mutex));
|
pthread_mutex_destroy(&(this->mutex));
|
||||||
|
|
||||||
pthread_cond_destroy(&(this->condvar));
|
pthread_cond_destroy(&(this->condvar));
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,8 +151,8 @@ send_queue_t *send_queue_create(void)
|
|||||||
this->public.destroy = (void(*)(send_queue_t*)) destroy;
|
this->public.destroy = (void(*)(send_queue_t*)) destroy;
|
||||||
|
|
||||||
this->list = linked_list_create();
|
this->list = linked_list_create();
|
||||||
pthread_mutex_init(&(this->mutex), NULL);
|
pthread_mutex_init(&this->mutex, NULL);
|
||||||
pthread_cond_init(&(this->condvar), NULL);
|
pthread_cond_init(&this->condvar, NULL);
|
||||||
this->logger = logger_manager->get_logger(logger_manager, SOCKET);
|
this->logger = logger_manager->get_logger(logger_manager, SOCKET);
|
||||||
|
|
||||||
return (&this->public);
|
return (&this->public);
|
||||||
|
|||||||
+48
-21
@@ -110,9 +110,14 @@ struct private_child_sa_t {
|
|||||||
u_int32_t hard_lifetime;
|
u_int32_t hard_lifetime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* has this CHILD_SA been rekeyed?
|
* transaction which is rekeying this CHILD_SA
|
||||||
*/
|
*/
|
||||||
bool rekeyed;
|
void *rekeying_transaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* has this child SA been rekeyed/is rekeying?
|
||||||
|
*/
|
||||||
|
bool is_rekeying;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies if NAT traversal is used
|
* Specifies if NAT traversal is used
|
||||||
@@ -477,11 +482,28 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of child_sa_t.set_rekeyed.
|
* Implementation of child_sa_t.set_rekeying_transaction.
|
||||||
*/
|
*/
|
||||||
static void set_rekeyed(private_child_sa_t *this)
|
static void set_rekeying_transaction(private_child_sa_t *this, void *transaction)
|
||||||
{
|
{
|
||||||
this->rekeyed = TRUE;
|
this->rekeying_transaction = transaction;
|
||||||
|
this->is_rekeying = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of child_sa_t.get_rekeying_transaction.
|
||||||
|
*/
|
||||||
|
static void* get_rekeying_transaction(private_child_sa_t *this)
|
||||||
|
{
|
||||||
|
return this->rekeying_transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of child_sa_t.is_rekeying.
|
||||||
|
*/
|
||||||
|
static bool is_rekeying(private_child_sa_t *this)
|
||||||
|
{
|
||||||
|
return this->is_rekeying;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -684,16 +706,6 @@ static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t
|
|||||||
u_int32_t spi;
|
u_int32_t spi;
|
||||||
|
|
||||||
if (mine)
|
if (mine)
|
||||||
{
|
|
||||||
src = this->me.addr;
|
|
||||||
dst = this->other.addr;
|
|
||||||
new_src = new_me;
|
|
||||||
new_dst = new_other;
|
|
||||||
src_changes = my_changes;
|
|
||||||
dst_changes = other_changes;
|
|
||||||
spi = this->me.spi;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
src = this->other.addr;
|
src = this->other.addr;
|
||||||
dst = this->me.addr;
|
dst = this->me.addr;
|
||||||
@@ -703,6 +715,16 @@ static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t
|
|||||||
dst_changes = my_changes;
|
dst_changes = my_changes;
|
||||||
spi = this->other.spi;
|
spi = this->other.spi;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src = this->me.addr;
|
||||||
|
dst = this->other.addr;
|
||||||
|
new_src = new_me;
|
||||||
|
new_dst = new_other;
|
||||||
|
src_changes = my_changes;
|
||||||
|
dst_changes = other_changes;
|
||||||
|
spi = this->me.spi;
|
||||||
|
}
|
||||||
|
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL1,
|
this->logger->log(this->logger, CONTROL|LEVEL1,
|
||||||
"updating %s SA 0x%x, from %s:%d..%s:%d to %s:%d..%s:%d",
|
"updating %s SA 0x%x, from %s:%d..%s:%d to %s:%d..%s:%d",
|
||||||
@@ -783,7 +805,7 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
|
|||||||
static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
|
static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
|
||||||
int my_changes, int other_changes)
|
int my_changes, int other_changes)
|
||||||
{
|
{
|
||||||
if (!my_changes || !other_changes)
|
if (!my_changes && !other_changes)
|
||||||
{
|
{
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -857,7 +879,7 @@ static void destroy(private_child_sa_t *this)
|
|||||||
/* delete all policies in the kernel */
|
/* delete all policies in the kernel */
|
||||||
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
|
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
|
||||||
{
|
{
|
||||||
if (!this->rekeyed)
|
if (!this->is_rekeying)
|
||||||
{
|
{
|
||||||
/* let rekeyed policies, as they are used by another child_sa */
|
/* let rekeyed policies, as they are used by another child_sa */
|
||||||
charon->kernel_interface->del_policy(charon->kernel_interface,
|
charon->kernel_interface->del_policy(charon->kernel_interface,
|
||||||
@@ -884,6 +906,8 @@ static void destroy(private_child_sa_t *this)
|
|||||||
}
|
}
|
||||||
this->policies->destroy(this->policies);
|
this->policies->destroy(this->policies);
|
||||||
|
|
||||||
|
this->me.addr->destroy(this->me.addr);
|
||||||
|
this->other.addr->destroy(this->other.addr);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,14 +931,16 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
|||||||
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,int,int))update_hosts;
|
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,int,int))update_hosts;
|
||||||
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
|
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
|
||||||
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
|
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
|
||||||
this->public.set_rekeyed = (void (*)(child_sa_t*))set_rekeyed;
|
this->public.set_rekeying_transaction = (void (*)(child_sa_t*,void*))set_rekeying_transaction;
|
||||||
|
this->public.get_rekeying_transaction = (void* (*)(child_sa_t*))get_rekeying_transaction;
|
||||||
|
this->public.is_rekeying = (bool (*)(child_sa_t*))is_rekeying;
|
||||||
this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status;
|
this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status;
|
||||||
this->public.destroy = (void(*)(child_sa_t*))destroy;
|
this->public.destroy = (void(*)(child_sa_t*))destroy;
|
||||||
|
|
||||||
/* private data */
|
/* private data */
|
||||||
this->logger = logger_manager->get_logger(logger_manager, CHILD_SA);
|
this->logger = logger_manager->get_logger(logger_manager, CHILD_SA);
|
||||||
this->me.addr = me;
|
this->me.addr = me->clone(me);
|
||||||
this->other.addr = other;
|
this->other.addr = other->clone(other);
|
||||||
this->me.spi = 0;
|
this->me.spi = 0;
|
||||||
this->other.spi = 0;
|
this->other.spi = 0;
|
||||||
this->alloc_ah_spi = 0;
|
this->alloc_ah_spi = 0;
|
||||||
@@ -926,7 +952,8 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
|||||||
this->reqid = rekey ? rekey : ++reqid;
|
this->reqid = rekey ? rekey : ++reqid;
|
||||||
this->policies = linked_list_create();
|
this->policies = linked_list_create();
|
||||||
this->protocol = PROTO_NONE;
|
this->protocol = PROTO_NONE;
|
||||||
this->rekeyed = FALSE;
|
this->rekeying_transaction = NULL;
|
||||||
|
this->is_rekeying = FALSE;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
typedef struct child_sa_t child_sa_t;
|
typedef struct child_sa_t child_sa_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Represents multiple IPsec SAs between two hosts.
|
* @brief Represents an IPsec SAs between two hosts.
|
||||||
*
|
*
|
||||||
* A child_sa_t contains two SAs. SAs for both
|
* A child_sa_t contains two SAs. SAs for both
|
||||||
* directions are managed in one child_sa_t object. Both
|
* directions are managed in one child_sa_t object. Both
|
||||||
@@ -168,15 +168,35 @@ struct child_sa_t {
|
|||||||
status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time);
|
status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mark this child_sa as rekeyed.
|
* @brief Set the transaction which rekeys this CHILD_SA.
|
||||||
*
|
*
|
||||||
* Since an SA which rekeys a old SA shares the same policy,
|
* Since either end may initiate CHILD_SA rekeying, we must detect
|
||||||
* we must mark a child_sa as rekeyed. A so marked SA does
|
* such situations to handle them cleanly. A rekeying transaction
|
||||||
* not remove its policy, as the new SA uses it.
|
* registers itself to the CHILD_SA, and checks later if another
|
||||||
|
* transaction is in progress of a rekey.
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
*/
|
*/
|
||||||
void (*set_rekeyed) (child_sa_t *this);
|
void (*set_rekeying_transaction) (child_sa_t *this, void *transaction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the transaction which rekeys this CHILD_SA.
|
||||||
|
*
|
||||||
|
* See set_rekeying_transactoin
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
*/
|
||||||
|
void* (*get_rekeying_transaction) (child_sa_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is the CHILD SA rekeying/in progress of rekeying?
|
||||||
|
*
|
||||||
|
* This is a readonly parameter. It is set whenever the
|
||||||
|
* set_rekeying_transaction() method is called.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
*/
|
||||||
|
bool (*is_rekeying) (child_sa_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log the status of a child_sa to a logger.
|
* @brief Log the status of a child_sa to a logger.
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include <encoding/payloads/sa_payload.h>
|
#include <encoding/payloads/sa_payload.h>
|
||||||
#include <encoding/payloads/nonce_payload.h>
|
#include <encoding/payloads/nonce_payload.h>
|
||||||
#include <encoding/payloads/ts_payload.h>
|
#include <encoding/payloads/ts_payload.h>
|
||||||
#include <sa/child_sa.h>
|
|
||||||
#include <sa/transactions/delete_child_sa.h>
|
#include <sa/transactions/delete_child_sa.h>
|
||||||
#include <utils/randomizer.h>
|
#include <utils/randomizer.h>
|
||||||
|
|
||||||
@@ -115,6 +114,11 @@ struct private_create_child_sa_t {
|
|||||||
*/
|
*/
|
||||||
child_sa_t *rekeyed_sa;
|
child_sa_t *rekeyed_sa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Have we lost the simultaneous rekeying nonce compare?
|
||||||
|
*/
|
||||||
|
bool lost;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* source of randomness
|
* source of randomness
|
||||||
*/
|
*/
|
||||||
@@ -143,13 +147,22 @@ static u_int32_t requested(private_create_child_sa_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of transaction_t.rekeys_child.
|
* Implementation of create_child_sa_t.rekeys_child.
|
||||||
*/
|
*/
|
||||||
static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
|
static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
|
||||||
{
|
{
|
||||||
this->rekeyed_sa = child_sa;
|
this->rekeyed_sa = child_sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of create_child_sa_t.cancel.
|
||||||
|
*/
|
||||||
|
static void cancel(private_create_child_sa_t *this)
|
||||||
|
{
|
||||||
|
this->rekeyed_sa = NULL;
|
||||||
|
this->lost = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of transaction_t.get_request.
|
* Implementation of transaction_t.get_request.
|
||||||
*/
|
*/
|
||||||
@@ -158,6 +171,15 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
|
|||||||
message_t *request;
|
message_t *request;
|
||||||
host_t *me, *other;
|
host_t *me, *other;
|
||||||
|
|
||||||
|
/* check if we are not already rekeying */
|
||||||
|
if (this->rekeyed_sa &&
|
||||||
|
this->rekeyed_sa->is_rekeying(this->rekeyed_sa))
|
||||||
|
{
|
||||||
|
this->logger->log(this->logger, ERROR,
|
||||||
|
"rekeying a CHILD_SA which is already rekeying, aborted");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* check if we already have built a message (retransmission) */
|
/* check if we already have built a message (retransmission) */
|
||||||
if (this->message)
|
if (this->message)
|
||||||
{
|
{
|
||||||
@@ -249,8 +271,8 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
|
|||||||
notify->set_spi(notify, this->rekeyed_sa->get_spi(this->rekeyed_sa, TRUE));
|
notify->set_spi(notify, this->rekeyed_sa->get_spi(this->rekeyed_sa, TRUE));
|
||||||
request->add_payload(request, (payload_t*)notify);
|
request->add_payload(request, (payload_t*)notify);
|
||||||
|
|
||||||
/* and mark sa with rekeying-in-progress */
|
/* register us as rekeying to detect multiple rekeying */
|
||||||
this->rekeyed_sa->set_rekeyed(this->rekeyed_sa);
|
this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, &this->public);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@@ -605,12 +627,21 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
|
|||||||
ts_response = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
|
ts_response = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
|
||||||
response->add_payload(response, (payload_t*)ts_response);
|
response->add_payload(response, (payload_t*)ts_response);
|
||||||
}
|
}
|
||||||
/* CHILD_SA successfully created. Now we must check if it rekeys an old one,
|
/* CHILD_SA successfully created. We set us as the rekeying transaction of
|
||||||
* and if so, mark the old as rekeyed. It will get deleted from the other
|
* this SA. If we already initiated rekeying of the same SA, we will detect
|
||||||
* peer. */
|
* this later in the conclude() call. */
|
||||||
if (this->rekeyed_sa)
|
if (this->rekeyed_sa)
|
||||||
{
|
{
|
||||||
this->rekeyed_sa->set_rekeyed(this->rekeyed_sa);
|
if (this->rekeyed_sa->is_rekeying(this->rekeyed_sa))
|
||||||
|
{
|
||||||
|
/* rekeying already in progress, register us, too */
|
||||||
|
this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, &this->public);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no rekeying in progress. mark SA as rekeyed, but not conflicted */
|
||||||
|
this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -628,6 +659,8 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
|
|||||||
ts_payload_t *tsi_payload = NULL;
|
ts_payload_t *tsi_payload = NULL;
|
||||||
ts_payload_t *tsr_payload = NULL;
|
ts_payload_t *tsr_payload = NULL;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
child_sa_t *new_child = NULL;
|
||||||
|
delete_child_sa_t *delete_child_sa;
|
||||||
|
|
||||||
/* check message type */
|
/* check message type */
|
||||||
if (response->get_exchange_type(response) != CREATE_CHILD_SA)
|
if (response->get_exchange_type(response) != CREATE_CHILD_SA)
|
||||||
@@ -726,6 +759,7 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
|
|||||||
"CHILD_SA creation failed");
|
"CHILD_SA creation failed");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
new_child = this->child_sa;
|
||||||
if (install_child_sa(this, TRUE) != SUCCESS)
|
if (install_child_sa(this, TRUE) != SUCCESS)
|
||||||
{
|
{
|
||||||
this->logger->log(this->logger, ERROR,
|
this->logger->log(this->logger, ERROR,
|
||||||
@@ -733,14 +767,73 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
|
|||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* CHILD_SA successfully created. If we have rekeyed an old one, delete it */
|
/* CHILD_SA successfully created. If the other peer initiated rekeying
|
||||||
|
* in the meantime, we detect this by comparing the rekeying_transaction
|
||||||
|
* of the SA. If it changed, we are not alone. Then we must compare the nonces.
|
||||||
|
* If no simultaneous rekeying is going on, we just initiate the delete of
|
||||||
|
* the superseded SA. */
|
||||||
if (this->rekeyed_sa)
|
if (this->rekeyed_sa)
|
||||||
{
|
{
|
||||||
delete_child_sa_t *delete_child_sa;
|
private_create_child_sa_t *other;
|
||||||
|
|
||||||
delete_child_sa = delete_child_sa_create(this->ike_sa,
|
other = (private_create_child_sa_t*)
|
||||||
this->message_id + 1);
|
this->rekeyed_sa->get_rekeying_transaction(this->rekeyed_sa);
|
||||||
delete_child_sa->set_child_sa(delete_child_sa, this->rekeyed_sa);
|
|
||||||
|
/* we are not rekeying anymore, unregister us */
|
||||||
|
this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, NULL);
|
||||||
|
|
||||||
|
if (other != this)
|
||||||
|
{ /* simlutaneous rekeying is going on, not so good */
|
||||||
|
chunk_t this_lowest, other_lowest;
|
||||||
|
|
||||||
|
/* check if this has a lower nonce the other */
|
||||||
|
if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
|
||||||
|
min(this->nonce_i.len, this->nonce_r.len)) < 0)
|
||||||
|
{
|
||||||
|
this_lowest = this->nonce_i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this_lowest = this->nonce_r;
|
||||||
|
}
|
||||||
|
if (memcmp(other->nonce_i.ptr, other->nonce_r.ptr,
|
||||||
|
min(other->nonce_i.len, other->nonce_r.len)) < 0)
|
||||||
|
{
|
||||||
|
other_lowest = other->nonce_i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
other_lowest = other->nonce_r;
|
||||||
|
}
|
||||||
|
if (memcmp(this_lowest.ptr, other_lowest.ptr,
|
||||||
|
min(this_lowest.len, other_lowest.len)) < 0)
|
||||||
|
{
|
||||||
|
this->logger->log(this->logger, ERROR,
|
||||||
|
"detected simultaneous CHILD_SA rekeying, but ours is preferred");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
this->logger->log(this->logger, ERROR,
|
||||||
|
"detected simultaneous CHILD_SA rekeying, deleting ours");
|
||||||
|
this->lost = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* delete the old SA if we have won the rekeying nonce compare*/
|
||||||
|
if (!this->lost)
|
||||||
|
{
|
||||||
|
other->rekeyed_sa->set_rekeying_transaction(other->rekeyed_sa, NULL);
|
||||||
|
delete_child_sa = delete_child_sa_create(this->ike_sa, this->message_id + 1);
|
||||||
|
delete_child_sa->set_child_sa(delete_child_sa, this->rekeyed_sa);
|
||||||
|
*next = (transaction_t*)delete_child_sa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this->lost)
|
||||||
|
{
|
||||||
|
/* we have lost simlutaneous rekeying, delete the CHILD_SA we just have created */
|
||||||
|
delete_child_sa = delete_child_sa_create(this->ike_sa, this->message_id + 1);
|
||||||
|
new_child->set_rekeying_transaction(new_child, NULL);
|
||||||
|
delete_child_sa->set_child_sa(delete_child_sa, new_child);
|
||||||
*next = (transaction_t*)delete_child_sa;
|
*next = (transaction_t*)delete_child_sa;
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@@ -788,6 +881,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa, u_int32_t message_id
|
|||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
|
this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
|
||||||
|
this->public.cancel = (void(*)(create_child_sa_t*))cancel;
|
||||||
|
|
||||||
/* private data */
|
/* private data */
|
||||||
this->ike_sa = ike_sa;
|
this->ike_sa = ike_sa;
|
||||||
@@ -799,6 +893,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa, u_int32_t message_id
|
|||||||
this->nonce_r = CHUNK_INITIALIZER;
|
this->nonce_r = CHUNK_INITIALIZER;
|
||||||
this->child_sa = NULL;
|
this->child_sa = NULL;
|
||||||
this->rekeyed_sa = NULL;
|
this->rekeyed_sa = NULL;
|
||||||
|
this->lost = FALSE;
|
||||||
this->proposal = NULL;
|
this->proposal = NULL;
|
||||||
this->tsi = NULL;
|
this->tsi = NULL;
|
||||||
this->tsr = NULL;
|
this->tsr = NULL;
|
||||||
|
|||||||
@@ -20,9 +20,8 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef CREATE_CHILD_SA_H_
|
||||||
#ifndef CREATE_CHILD_SA_
|
#define CREATE_CHILD_SA_H_
|
||||||
#define CREATE_CHILD_SA_
|
|
||||||
|
|
||||||
#include <sa/ike_sa.h>
|
#include <sa/ike_sa.h>
|
||||||
#include <sa/child_sa.h>
|
#include <sa/child_sa.h>
|
||||||
@@ -38,6 +37,23 @@ typedef struct create_child_sa_t create_child_sa_t;
|
|||||||
* but includes an additional REKEY_SA notify and deletes the old
|
* but includes an additional REKEY_SA notify and deletes the old
|
||||||
* one (in a separate transaction).
|
* one (in a separate transaction).
|
||||||
*
|
*
|
||||||
|
* ¦__________ _________¦
|
||||||
|
* ¦ Cyq \/ Czq ¦
|
||||||
|
* ¦__________/\_________¦
|
||||||
|
* detect ¦__________ _________¦ detect
|
||||||
|
* ¦ Czp \/ Czp ¦
|
||||||
|
* compare nonces, won ¦__________/\_________¦ compare nonces, lost
|
||||||
|
* ¦ ¦
|
||||||
|
* delete old ¦__________ ¦
|
||||||
|
* ¦ Dxq \__________¦
|
||||||
|
* ¦ __________¦
|
||||||
|
* ¦__________/ Dxp ¦
|
||||||
|
* ¦ __________¦ delete created
|
||||||
|
* ¦__________/ Dzq ¦
|
||||||
|
* ¦__________ ¦
|
||||||
|
* ¦ Dzp \__________¦
|
||||||
|
*
|
||||||
|
*
|
||||||
* @b Constructors:
|
* @b Constructors:
|
||||||
* - create_child_sa_create()
|
* - create_child_sa_create()
|
||||||
* - transaction_create() with the appropriate message
|
* - transaction_create() with the appropriate message
|
||||||
@@ -61,6 +77,18 @@ struct create_child_sa_t {
|
|||||||
* @param child_sa CHILD_SA to rekey
|
* @param child_sa CHILD_SA to rekey
|
||||||
*/
|
*/
|
||||||
void (*rekeys_child) (create_child_sa_t* this, child_sa_t *child_sa);
|
void (*rekeys_child) (create_child_sa_t* this, child_sa_t *child_sa);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cancel a rekeying request.
|
||||||
|
*
|
||||||
|
* Cancelling a rekeying request will set a flag in the transaction. When
|
||||||
|
* the response for the transaction is received, the created CHILD_SA
|
||||||
|
* gets deleted afterwards.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param child_sa CHILD_SA to rekey
|
||||||
|
*/
|
||||||
|
void (*cancel) (create_child_sa_t* this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,4 +102,4 @@ struct create_child_sa_t {
|
|||||||
*/
|
*/
|
||||||
create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa, u_int32_t message_id);
|
create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa, u_int32_t message_id);
|
||||||
|
|
||||||
#endif /* CREATE_CHILD_SA_ */
|
#endif /* CREATE_CHILD_SA_H_ */
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <encoding/payloads/delete_payload.h>
|
#include <encoding/payloads/delete_payload.h>
|
||||||
|
#include <sa/transactions/create_child_sa.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct private_delete_child_sa_t private_delete_child_sa_t;
|
typedef struct private_delete_child_sa_t private_delete_child_sa_t;
|
||||||
@@ -151,7 +152,7 @@ static status_t process_delete(private_delete_child_sa_t *this, delete_payload_t
|
|||||||
protocol_id_t protocol;
|
protocol_id_t protocol;
|
||||||
u_int32_t spi;
|
u_int32_t spi;
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
delete_payload_t *delete_response;
|
delete_payload_t *delete_response = NULL;
|
||||||
|
|
||||||
/* get requested CHILD */
|
/* get requested CHILD */
|
||||||
protocol = delete_request->get_protocol_id(delete_request);
|
protocol = delete_request->get_protocol_id(delete_request);
|
||||||
@@ -178,9 +179,23 @@ static status_t process_delete(private_delete_child_sa_t *this, delete_payload_t
|
|||||||
|
|
||||||
if (child_sa != NULL)
|
if (child_sa != NULL)
|
||||||
{
|
{
|
||||||
|
create_child_sa_t *rekey;
|
||||||
|
|
||||||
this->logger->log(this->logger, CONTROL,
|
this->logger->log(this->logger, CONTROL,
|
||||||
"received DELETE for %s CHILD_SA with SPI 0x%x, deleting",
|
"received DELETE for %s CHILD_SA with SPI 0x%x, deleting",
|
||||||
mapping_find(protocol_id_m, protocol), ntohl(spi));
|
mapping_find(protocol_id_m, protocol), ntohl(spi));
|
||||||
|
|
||||||
|
rekey = child_sa->get_rekeying_transaction(child_sa);
|
||||||
|
if (rekey)
|
||||||
|
{
|
||||||
|
/* we have received a delete for an SA which we are still rekeying.
|
||||||
|
* this means we have lost the nonce comparison, and the rekeying
|
||||||
|
* will fail. We set a flag in the transaction for this special case.
|
||||||
|
*/
|
||||||
|
this->logger->log(this->logger, CONTROL,
|
||||||
|
"DELETE received while rekeying, rekeying cancelled");
|
||||||
|
rekey->cancel(rekey);
|
||||||
|
}
|
||||||
/* delete it, with inbound spi */
|
/* delete it, with inbound spi */
|
||||||
spi = child_sa->get_spi(child_sa, TRUE);
|
spi = child_sa->get_spi(child_sa, TRUE);
|
||||||
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
|
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
|
||||||
|
|||||||
@@ -23,12 +23,14 @@
|
|||||||
#ifndef TRANSACTION_H_
|
#ifndef TRANSACTION_H_
|
||||||
#define TRANSACTION_H_
|
#define TRANSACTION_H_
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct transaction_t transaction_t;
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <encoding/message.h>
|
#include <encoding/message.h>
|
||||||
#include <sa/ike_sa.h>
|
#include <sa/ike_sa.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct transaction_t transaction_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This interface represents a transaction an established IKE_SA can do.
|
* @brief This interface represents a transaction an established IKE_SA can do.
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -383,10 +384,7 @@ static status_t add_sa(private_kernel_interface_t *this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct xfrm_encap_tmpl* encap = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
|
struct xfrm_encap_tmpl* encap = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
|
||||||
/* UDP_ENCAP_ESPINUDP, see /usr/src/linux/include/linux/udp.h
|
encap->encap_type = UDP_ENCAP_ESPINUDP;
|
||||||
* we could probably use 3 here (as pluto does) although the
|
|
||||||
* result is eventually the same. */
|
|
||||||
encap->encap_type = 2;
|
|
||||||
encap->encap_sport = ntohs(natt->sport);
|
encap->encap_sport = ntohs(natt->sport);
|
||||||
encap->encap_dport = ntohs(natt->dport);
|
encap->encap_dport = ntohs(natt->dport);
|
||||||
memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
|
memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
|
||||||
@@ -440,9 +438,9 @@ static status_t update_sa_hosts(
|
|||||||
this->logger->log(this->logger, CONTROL|LEVEL2, "getting SA");
|
this->logger->log(this->logger, CONTROL|LEVEL2, "getting SA");
|
||||||
|
|
||||||
struct nlmsghdr *hdr = (struct nlmsghdr*)request;
|
struct nlmsghdr *hdr = (struct nlmsghdr*)request;
|
||||||
hdr->nlmsg_flags = NLM_F_REQUEST ;
|
hdr->nlmsg_flags = NLM_F_REQUEST;
|
||||||
hdr->nlmsg_type = XFRM_MSG_GETSA;
|
hdr->nlmsg_type = XFRM_MSG_GETSA;
|
||||||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
|
||||||
|
|
||||||
struct xfrm_usersa_id *sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
|
struct xfrm_usersa_id *sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
|
||||||
sa_id->daddr = dst->get_xfrm_addr(dst);
|
sa_id->daddr = dst->get_xfrm_addr(dst);
|
||||||
@@ -996,12 +994,11 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
/* public functions */
|
/* public functions */
|
||||||
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
|
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
|
||||||
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,bool))add_sa;
|
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,bool))add_sa;
|
||||||
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,protocol_id_t,u_int32_t))add_policy;
|
|
||||||
this->public.update_sa_hosts = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,int,int,u_int32_t,protocol_id_t))update_sa_hosts;
|
this->public.update_sa_hosts = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,int,int,u_int32_t,protocol_id_t))update_sa_hosts;
|
||||||
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
||||||
|
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,protocol_id_t,u_int32_t))add_policy;
|
||||||
this->public.query_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,time_t*))query_policy;
|
this->public.query_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,time_t*))query_policy;
|
||||||
this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy;
|
this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy;
|
||||||
|
|
||||||
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
||||||
|
|
||||||
/* private members */
|
/* private members */
|
||||||
|
|||||||
@@ -46,13 +46,6 @@ struct private_receiver_t {
|
|||||||
*/
|
*/
|
||||||
receiver_t public;
|
receiver_t public;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Thread function started at creation of the receiver object.
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
*/
|
|
||||||
void (*receive_packets) (private_receiver_t *this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigned thread.
|
* Assigned thread.
|
||||||
*/
|
*/
|
||||||
@@ -114,11 +107,10 @@ receiver_t * receiver_create()
|
|||||||
private_receiver_t *this = malloc_thing(private_receiver_t);
|
private_receiver_t *this = malloc_thing(private_receiver_t);
|
||||||
|
|
||||||
this->public.destroy = (void(*)(receiver_t*)) destroy;
|
this->public.destroy = (void(*)(receiver_t*)) destroy;
|
||||||
this->receive_packets = receive_packets;
|
|
||||||
|
|
||||||
this->logger = logger_manager->get_logger(logger_manager, RECEIVER);
|
this->logger = logger_manager->get_logger(logger_manager, RECEIVER);
|
||||||
|
|
||||||
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->receive_packets, this) != 0)
|
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))receive_packets, this) != 0)
|
||||||
{
|
{
|
||||||
this->logger->log(this->logger, ERROR, "Receiver thread could not be started");
|
this->logger->log(this->logger, ERROR, "Receiver thread could not be started");
|
||||||
free(this);
|
free(this);
|
||||||
|
|||||||
@@ -43,15 +43,6 @@ struct private_scheduler_t {
|
|||||||
*/
|
*/
|
||||||
scheduler_t public;
|
scheduler_t public;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get events from the event queue and add them to to job queue.
|
|
||||||
*
|
|
||||||
* Thread function started at creation of the scheduler object.
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
*/
|
|
||||||
void (*get_events) (private_scheduler_t *this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigned thread.
|
* Assigned thread.
|
||||||
*/
|
*/
|
||||||
@@ -75,7 +66,7 @@ static void get_events(private_scheduler_t * this)
|
|||||||
|
|
||||||
this->logger->log(this->logger, CONTROL, "scheduler thread running, thread_ID: %06u", (int)pthread_self());
|
this->logger->log(this->logger, CONTROL, "scheduler thread running, thread_ID: %06u", (int)pthread_self());
|
||||||
|
|
||||||
for (;;)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Waiting for next event...");
|
this->logger->log(this->logger, CONTROL|LEVEL2, "Waiting for next event...");
|
||||||
/* get a job, this block until one is available */
|
/* get a job, this block until one is available */
|
||||||
@@ -109,11 +100,10 @@ scheduler_t * scheduler_create()
|
|||||||
private_scheduler_t *this = malloc_thing(private_scheduler_t);
|
private_scheduler_t *this = malloc_thing(private_scheduler_t);
|
||||||
|
|
||||||
this->public.destroy = (void(*)(scheduler_t*)) destroy;
|
this->public.destroy = (void(*)(scheduler_t*)) destroy;
|
||||||
this->get_events = get_events;
|
|
||||||
|
|
||||||
this->logger = logger_manager->get_logger(logger_manager, SCHEDULER);
|
this->logger = logger_manager->get_logger(logger_manager, SCHEDULER);
|
||||||
|
|
||||||
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->get_events, this) != 0)
|
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))get_events, this) != 0)
|
||||||
{
|
{
|
||||||
/* thread could not be created */
|
/* thread could not be created */
|
||||||
this->logger->log(this->logger, ERROR, "Scheduler thread could not be created!");
|
this->logger->log(this->logger, ERROR, "Scheduler thread could not be created!");
|
||||||
|
|||||||
@@ -49,13 +49,6 @@ struct private_sender_t {
|
|||||||
*/
|
*/
|
||||||
pthread_t assigned_thread;
|
pthread_t assigned_thread;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The thread function, sends out packets.
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
*/
|
|
||||||
void (*send_packets) (private_sender_t * this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logger for this sender_t object.
|
* A logger for this sender_t object.
|
||||||
*/
|
*/
|
||||||
@@ -68,7 +61,7 @@ struct private_sender_t {
|
|||||||
*/
|
*/
|
||||||
static void send_packets(private_sender_t * this)
|
static void send_packets(private_sender_t * this)
|
||||||
{
|
{
|
||||||
packet_t * current_packet;
|
packet_t *current_packet;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
/* cancellation disabled by default */
|
/* cancellation disabled by default */
|
||||||
@@ -76,11 +69,11 @@ static void send_packets(private_sender_t * this)
|
|||||||
|
|
||||||
this->logger->log(this->logger, CONTROL, "sender thread running, thread_ID: %06u", (int)pthread_self());
|
this->logger->log(this->logger, CONTROL, "sender thread running, thread_ID: %06u", (int)pthread_self());
|
||||||
|
|
||||||
while (1)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
current_packet = charon->send_queue->get(charon->send_queue);
|
current_packet = charon->send_queue->get(charon->send_queue);
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL1, "Got a packet, sending it");
|
this->logger->log(this->logger, CONTROL|LEVEL1, "Got a packet, sending it");
|
||||||
status = charon->socket->send(charon->socket,current_packet);
|
status = charon->socket->send(charon->socket, current_packet);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
this->logger->log(this->logger, ERROR, "Sending failed, socket returned %s",
|
this->logger->log(this->logger, ERROR, "Sending failed, socket returned %s",
|
||||||
@@ -111,12 +104,11 @@ sender_t * sender_create()
|
|||||||
{
|
{
|
||||||
private_sender_t *this = malloc_thing(private_sender_t);
|
private_sender_t *this = malloc_thing(private_sender_t);
|
||||||
|
|
||||||
this->send_packets = send_packets;
|
|
||||||
this->public.destroy = (void(*)(sender_t*)) destroy;
|
this->public.destroy = (void(*)(sender_t*)) destroy;
|
||||||
|
|
||||||
this->logger = logger_manager->get_logger(logger_manager, SENDER);
|
this->logger = logger_manager->get_logger(logger_manager, SENDER);
|
||||||
|
|
||||||
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->send_packets, this) != 0)
|
if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))send_packets, this) != 0)
|
||||||
{
|
{
|
||||||
this->logger->log(this->logger, ERROR, "Sender thread could not be created");
|
this->logger->log(this->logger, ERROR, "Sender thread could not be created");
|
||||||
free(this);
|
free(this);
|
||||||
|
|||||||
@@ -57,12 +57,7 @@ struct private_thread_pool_t {
|
|||||||
/**
|
/**
|
||||||
* Logger of the thread pool.
|
* Logger of the thread pool.
|
||||||
*/
|
*/
|
||||||
logger_t *pool_logger;
|
logger_t *logger;
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger of the worker threads.
|
|
||||||
*/
|
|
||||||
logger_t *worker_logger;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +71,9 @@ static void process_jobs(private_thread_pool_t *this)
|
|||||||
/* cancellation disabled by default */
|
/* cancellation disabled by default */
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
|
||||||
this->worker_logger->log(this->worker_logger, CONTROL, "worker thread running, thread_ID: %06u", (int)pthread_self());
|
this->logger->log(this->logger, CONTROL,
|
||||||
|
"worker thread running, thread_ID: %06u",
|
||||||
|
(int)pthread_self());
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
@@ -107,7 +104,8 @@ static void destroy(private_thread_pool_t *this)
|
|||||||
int current;
|
int current;
|
||||||
/* flag thread for termination */
|
/* flag thread for termination */
|
||||||
for (current = 0; current < this->pool_size; current++) {
|
for (current = 0; current < this->pool_size; current++) {
|
||||||
this->pool_logger->log(this->pool_logger, CONTROL, "cancelling worker thread #%d", current+1);
|
this->logger->log(this->logger, CONTROL,
|
||||||
|
"cancelling worker thread #%d", current+1);
|
||||||
pthread_cancel(this->threads[current]);
|
pthread_cancel(this->threads[current]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +113,13 @@ static void destroy(private_thread_pool_t *this)
|
|||||||
for (current = 0; current < this->pool_size; current++) {
|
for (current = 0; current < this->pool_size; current++) {
|
||||||
if (pthread_join(this->threads[current], NULL) == 0)
|
if (pthread_join(this->threads[current], NULL) == 0)
|
||||||
{
|
{
|
||||||
this->pool_logger->log(this->pool_logger, CONTROL, "worker thread #%d terminated", current+1);
|
this->logger->log(this->logger, CONTROL,
|
||||||
|
"worker thread #%d terminated", current+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->pool_logger->log(this->pool_logger, ERROR, "could not terminate worker thread #%d", current+1);
|
this->logger->log(this->logger, ERROR,
|
||||||
|
"could not terminate worker thread #%d", current+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,28 +143,31 @@ thread_pool_t *thread_pool_create(size_t pool_size)
|
|||||||
/* initialize member */
|
/* initialize member */
|
||||||
this->pool_size = pool_size;
|
this->pool_size = pool_size;
|
||||||
this->threads = malloc(sizeof(pthread_t) * pool_size);
|
this->threads = malloc(sizeof(pthread_t) * pool_size);
|
||||||
this->pool_logger = logger_manager->get_logger(logger_manager, THREAD_POOL);
|
this->logger = logger_manager->get_logger(logger_manager, THREAD_POOL);
|
||||||
this->worker_logger = logger_manager->get_logger(logger_manager, WORKER);
|
|
||||||
|
|
||||||
/* try to create as many threads as possible, up to pool_size */
|
/* try to create as many threads as possible, up to pool_size */
|
||||||
for (current = 0; current < pool_size; current++)
|
for (current = 0; current < pool_size; current++)
|
||||||
{
|
{
|
||||||
if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))process_jobs, this) == 0)
|
if (pthread_create(&(this->threads[current]), NULL,
|
||||||
|
(void*(*)(void*))process_jobs, this) == 0)
|
||||||
{
|
{
|
||||||
this->pool_logger->log(this->pool_logger, CONTROL, "created worker thread #%d", current+1);
|
this->logger->log(this->logger, CONTROL,
|
||||||
|
"created worker thread #%d", current+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* creation failed, is it the first one? */
|
/* creation failed, is it the first one? */
|
||||||
if (current == 0)
|
if (current == 0)
|
||||||
{
|
{
|
||||||
this->pool_logger->log(this->pool_logger, ERROR, "Could not create any thread");
|
this->logger->log(this->logger, ERROR, "Could not create any thread");
|
||||||
free(this->threads);
|
free(this->threads);
|
||||||
free(this);
|
free(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* not all threads could be created, but at least one :-/ */
|
/* not all threads could be created, but at least one :-/ */
|
||||||
this->pool_logger->log(this->pool_logger, ERROR, "Could only create %d from requested %d threads!", current, pool_size);
|
this->logger->log(this->logger, ERROR,
|
||||||
|
"Could only create %d from requested %d threads!",
|
||||||
|
current, pool_size);
|
||||||
|
|
||||||
this->pool_size = current;
|
this->pool_size = current;
|
||||||
return (thread_pool_t*)this;
|
return (thread_pool_t*)this;
|
||||||
|
|||||||
Reference in New Issue
Block a user