diff options
Diffstat (limited to 'src/charon/processing')
28 files changed, 2864 insertions, 0 deletions
diff --git a/src/charon/processing/event_queue.c b/src/charon/processing/event_queue.c new file mode 100644 index 000000000..40bcb1ed8 --- /dev/null +++ b/src/charon/processing/event_queue.c @@ -0,0 +1,290 @@ +/** + * @file event_queue.c + * + * @brief Implementation of event_queue_t + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <pthread.h> +#include <stdlib.h> + +#include "event_queue.h" + +#include <library.h> +#include <utils/linked_list.h> + + + +typedef struct event_t event_t; + +/** + * Event containing a job and a schedule time + */ +struct event_t { + /** + * Time to fire the event. + */ + timeval_t time; + + /** + * Every event has its assigned job. + */ + job_t * job; +}; + +/** + * destroy an event and its job + */ +static void event_destroy(event_t *event) +{ + event->job->destroy(event->job); + free(event); +} + +typedef struct private_event_queue_t private_event_queue_t; + +/** + * Private Variables and Functions of event_queue_t class. + */ +struct private_event_queue_t { + /** + * Public part. + */ + event_queue_t public; + + /** + * The events are stored in a linked list of type linked_list_t. + */ + linked_list_t *list; + + /** + * Access to linked_list is locked through this mutex. + */ + pthread_mutex_t mutex; + + /** + * If the queue is empty or an event has not to be fired + * a thread has to wait. + * + * This condvar is used to wake up such a thread. + */ + pthread_cond_t condvar; +}; + +/** + * Returns the difference of to timeval structs in milliseconds + */ +static long time_difference(struct timeval *end_time, struct timeval *start_time) +{ + time_t s; + suseconds_t us; + + s = (end_time->tv_sec - start_time->tv_sec); + us = (end_time->tv_usec - start_time->tv_usec); + return ((s * 1000) + us/1000); +} + +/** + * Implements event_queue_t.get_count + */ +static int get_count(private_event_queue_t *this) +{ + int count; + pthread_mutex_lock(&(this->mutex)); + count = this->list->get_count(this->list); + pthread_mutex_unlock(&(this->mutex)); + return count; +} + +/** + * Implements event_queue_t.get + */ +static job_t *get(private_event_queue_t *this) +{ + timespec_t timeout; + timeval_t current_time; + event_t * next_event; + job_t *job; + int oldstate; + + pthread_mutex_lock(&(this->mutex)); + + while (TRUE) + { + while(this->list->get_count(this->list) == 0) + { + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + pthread_cond_wait( &(this->condvar), &(this->mutex)); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + + this->list->get_first(this->list, (void **)&next_event); + + gettimeofday(¤t_time, NULL); + long difference = time_difference(¤t_time,&(next_event->time)); + if (difference <= 0) + { + timeout.tv_sec = next_event->time.tv_sec; + timeout.tv_nsec = next_event->time.tv_usec * 1000; + + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + pthread_cond_timedwait(&(this->condvar), &(this->mutex), &timeout); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + else + { + /* event available */ + this->list->remove_first(this->list, (void **)&next_event); + job = next_event->job; + free(next_event); + break; + } + } + pthread_cond_signal( &(this->condvar)); + pthread_mutex_unlock(&(this->mutex)); + + return job; +} + +/** + * Implements function add_absolute of event_queue_t. + * See #event_queue_s.add_absolute for description. + */ +static void add_absolute(private_event_queue_t *this, job_t *job, timeval_t time) +{ + event_t *event; + event_t *current_event; + iterator_t *iterator; + + /* create event */ + event = malloc_thing(event_t); + event->time = time; + event->job = job; + + pthread_mutex_lock(&(this->mutex)); + + /* while just used to break out */ + while(TRUE) + { + if (this->list->get_count(this->list) == 0) + { + this->list->insert_first(this->list,event); + break; + } + + /* check last entry */ + this->list->get_last(this->list,(void **) ¤t_event); + + if (time_difference(&(event->time), &(current_event->time)) >= 0) + { + /* my event has to be fired after the last event in list */ + this->list->insert_last(this->list,event); + break; + } + + /* check first entry */ + this->list->get_first(this->list,(void **) ¤t_event); + + if (time_difference(&(event->time), &(current_event->time)) < 0) + { + /* my event has to be fired before the first event in list */ + this->list->insert_first(this->list,event); + break; + } + + iterator = this->list->create_iterator(this->list,TRUE); + iterator->iterate(iterator, (void**)¤t_event); + /* first element has not to be checked (already done) */ + while(iterator->iterate(iterator, (void**)¤t_event)) + { + if (time_difference(&(event->time), &(current_event->time)) <= 0) + { + /* my event has to be fired before the current event in list */ + iterator->insert_before(iterator,event); + break; + } + } + iterator->destroy(iterator); + break; + } + + pthread_cond_signal( &(this->condvar)); + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * Implements event_queue_t.add_relative. + */ +static void add_relative(event_queue_t *this, job_t *job, u_int32_t ms) +{ + timeval_t current_time; + timeval_t time; + + time_t s = ms / 1000; + suseconds_t us = (ms - s * 1000) * 1000; + + gettimeofday(¤t_time, NULL); + + time.tv_usec = (current_time.tv_usec + us) % 1000000; + time.tv_sec = current_time.tv_sec + (current_time.tv_usec + us)/1000000 + s; + + this->add_absolute(this, job, time); +} + + +/** + * Implements event_queue_t.destroy. + */ +static void event_queue_destroy(private_event_queue_t *this) +{ + this->list->destroy_function(this->list, (void*)event_destroy); + free(this); +} + +/* + * Documented in header + */ +event_queue_t *event_queue_create() +{ + private_event_queue_t *this = malloc_thing(private_event_queue_t); + + this->public.get_count = (int (*) (event_queue_t *event_queue)) get_count; + this->public.get = (job_t *(*) (event_queue_t *event_queue)) get; + this->public.add_absolute = (void (*) (event_queue_t *event_queue, job_t *job, timeval_t time)) add_absolute; + this->public.add_relative = (void (*) (event_queue_t *event_queue, job_t *job, u_int32_t ms)) add_relative; + this->public.destroy = (void (*) (event_queue_t *event_queue)) event_queue_destroy; + + this->list = linked_list_create(); + pthread_mutex_init(&(this->mutex), NULL); + pthread_cond_init(&(this->condvar), NULL); + + return (&this->public); +} diff --git a/src/charon/processing/event_queue.h b/src/charon/processing/event_queue.h new file mode 100644 index 000000000..c85286bf2 --- /dev/null +++ b/src/charon/processing/event_queue.h @@ -0,0 +1,118 @@ +/** + * @file event_queue.h + * + * @brief Interface of job_queue_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef EVENT_QUEUE_H_ +#define EVENT_QUEUE_H_ + +typedef struct event_queue_t event_queue_t; + +#include <sys/time.h> + +#include <library.h> +#include <processing/jobs/job.h> + +/** + * @brief Event-Queue used to store timed events. + * + * Added events are sorted. The get method blocks until + * the time is elapsed to process the next event. The get + * method is called from the scheduler_t thread, which + * will add the jobs to to job_queue_t for further processing. + * + * Although the event-queue is based on a linked_list_t + * all access functions are thread-save implemented. + * + * @b Constructors: + * - event_queue_create() + * + * @ingroup processing + */ +struct event_queue_t { + + /** + * @brief Returns number of events in queue. + * + * @param event_queue calling object + * @return number of events in queue + */ + int (*get_count) (event_queue_t *event_queue); + + /** + * @brief Get the next job from the event-queue. + * + * If no event is pending, this function blocks until a job can be returned. + * + * @param event_queue calling object + * @param[out] job pointer to a job pointer where to job is returned to + * @return next job + */ + job_t *(*get) (event_queue_t *event_queue); + + /** + * @brief Adds a event to the queue, using a relative time. + * + * This function is non blocking and adds a job_t at a specific time to the list. + * The specific job object has to get destroyed by the thread which + * removes the job. + * + * @param event_queue calling object + * @param[in] job job to add to the queue (job is not copied) + * @param[in] time relative time, when the event has to get fired + */ + void (*add_relative) (event_queue_t *event_queue, job_t *job, u_int32_t ms); + + /** + * @brief Adds a event to the queue, using an absolute time. + * + * This function is non blocking and adds a job_t at a specific time to the list. + * The specific job object has to get destroyed by the thread which + * removes the job. + * + * @param event_queue calling object + * @param[in] job job to add to the queue (job is not copied) + * @param[in] time absolute time, when the event has to get fired + */ + void (*add_absolute) (event_queue_t *event_queue, job_t *job, timeval_t time); + + /** + * @brief Destroys a event_queue object. + * + * @warning The caller of this function has to make sure + * that no thread is going to add or get an event from the event_queue + * after calling this function. + * + * @param event_queue calling object + */ + void (*destroy) (event_queue_t *event_queue); +}; + +/** + * @brief Creates an empty event_queue. + * + * @returns event_queue_t object + * + * @ingroup processing + */ +event_queue_t *event_queue_create(void); + +#endif /*EVENT_QUEUE_H_*/ diff --git a/src/charon/processing/job_queue.c b/src/charon/processing/job_queue.c new file mode 100644 index 000000000..2310ca6ff --- /dev/null +++ b/src/charon/processing/job_queue.c @@ -0,0 +1,139 @@ +/** + * @file job_queue.c + * + * @brief Implementation of job_queue_t + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <stdlib.h> +#include <pthread.h> + +#include "job_queue.h" + +#include <utils/linked_list.h> + + +typedef struct private_job_queue_t private_job_queue_t; + +/** + * @brief Private Variables and Functions of job_queue class + * + */ +struct private_job_queue_t { + + /** + * public members + */ + job_queue_t public; + + /** + * The jobs are stored in a linked list + */ + linked_list_t *list; + + /** + * access to linked_list is locked through this mutex + */ + pthread_mutex_t mutex; + + /** + * If the queue is empty a thread has to wait + * This condvar is used to wake up such a thread + */ + pthread_cond_t condvar; +}; + + +/** + * implements job_queue_t.get_count + */ +static int get_count(private_job_queue_t *this) +{ + int count; + pthread_mutex_lock(&(this->mutex)); + count = this->list->get_count(this->list); + pthread_mutex_unlock(&(this->mutex)); + return count; +} + +/** + * implements job_queue_t.get + */ +static job_t *get(private_job_queue_t *this) +{ + int oldstate; + job_t *job; + pthread_mutex_lock(&(this->mutex)); + /* go to wait while no jobs available */ + while(this->list->get_count(this->list) == 0) + { + /* add mutex unlock handler for cancellation, enable cancellation */ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + pthread_cond_wait( &(this->condvar), &(this->mutex)); + + /* reset cancellation, remove mutex-unlock handler (without executing) */ + pthread_setcancelstate(oldstate, NULL); + pthread_cleanup_pop(0); + } + this->list->remove_first(this->list, (void **)&job); + pthread_mutex_unlock(&(this->mutex)); + return job; +} + +/** + * implements function job_queue_t.add + */ +static void add(private_job_queue_t *this, job_t *job) +{ + pthread_mutex_lock(&(this->mutex)); + this->list->insert_last(this->list,job); + pthread_cond_signal( &(this->condvar)); + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * implements job_queue_t.destroy + */ +static void job_queue_destroy (private_job_queue_t *this) +{ + this->list->destroy_offset(this->list, offsetof(job_t, destroy)); + free(this); +} + +/* + * + * Documented in header + */ +job_queue_t *job_queue_create(void) +{ + private_job_queue_t *this = malloc_thing(private_job_queue_t); + + this->public.get_count = (int(*)(job_queue_t*))get_count; + this->public.get = (job_t*(*)(job_queue_t*))get; + this->public.add = (void(*)(job_queue_t*, job_t*))add; + this->public.destroy = (void(*)(job_queue_t*))job_queue_destroy; + + this->list = linked_list_create(); + pthread_mutex_init(&(this->mutex), NULL); + pthread_cond_init(&(this->condvar), NULL); + + return (&this->public); +} diff --git a/src/charon/processing/job_queue.h b/src/charon/processing/job_queue.h new file mode 100644 index 000000000..9b58588ae --- /dev/null +++ b/src/charon/processing/job_queue.h @@ -0,0 +1,100 @@ +/** + * @file job_queue.h + * + * @brief Interface of job_queue_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef JOB_QUEUE_H_ +#define JOB_QUEUE_H_ + +typedef struct job_queue_t job_queue_t; + +#include <library.h> +#include <processing/jobs/job.h> + +/** + * @brief The job queue stores jobs, which will be processed by the thread_pool_t. + * + * Jobs are added from various sources, from the threads and + * from the event_queue_t. + * Although the job-queue is based on a linked_list_t + * all access functions are thread-save implemented. + * + * @b Constructors: + * - job_queue_create() + * + * @ingroup processing + */ +struct job_queue_t { + + /** + * @brief Returns number of jobs in queue. + * + * @param job_queue_t calling object + * @returns number of items in queue + */ + int (*get_count) (job_queue_t *job_queue); + + /** + * @brief Get the next job from the queue. + * + * If the queue is empty, this function blocks until a job can be returned. + * After using, the returned job has to get destroyed by the caller. + * + * @param job_queue_t calling object + * @param[out] job pointer to a job pointer where to job is returned to + * @return next job + */ + job_t *(*get) (job_queue_t *job_queue); + + /** + * @brief Adds a job to the queue. + * + * This function is non blocking and adds a job_t to the list. + * The specific job object has to get destroyed by the thread which + * removes the job. + * + * @param job_queue_t calling object + * @param job job to add to the queue (job is not copied) + */ + void (*add) (job_queue_t *job_queue, job_t *job); + + /** + * @brief Destroys a job_queue object. + * + * @warning The caller of this function has to make sure + * that no thread is going to add or get a job from the job_queue + * after calling this function. + * + * @param job_queue_t calling object + */ + void (*destroy) (job_queue_t *job_queue); +}; + +/** + * @brief Creates an empty job_queue. + * + * @return job_queue_t object + * + * @ingroup processing + */ +job_queue_t *job_queue_create(void); + +#endif /*JOB_QUEUE_H_*/ diff --git a/src/charon/processing/jobs/acquire_job.c b/src/charon/processing/jobs/acquire_job.c new file mode 100644 index 000000000..b4ffb258d --- /dev/null +++ b/src/charon/processing/jobs/acquire_job.c @@ -0,0 +1,98 @@ +/** + * @file acquire_job.c + * + * @brief Implementation of acquire_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "acquire_job.h" + +#include <daemon.h> + + +typedef struct private_acquire_job_t private_acquire_job_t; + +/** + * Private data of an acquire_job_t object. + */ +struct private_acquire_job_t { + /** + * Public acquire_job_t interface. + */ + acquire_job_t public; + + /** + * reqid of the child to rekey + */ + u_int32_t reqid; +}; + +/** + * Implementation of job_t.get_type. + */ +static job_type_t get_type(private_acquire_job_t *this) +{ + return ACQUIRE; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_acquire_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + this->reqid, TRUE); + if (ike_sa == NULL) + { + DBG2(DBG_JOB, "CHILD_SA with reqid %d not found for acquiring", + this->reqid); + return DESTROY_ME; + } + ike_sa->acquire(ike_sa, this->reqid); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return DESTROY_ME; +} + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_acquire_job_t *this) +{ + free(this); +} + +/* + * Described in header + */ +acquire_job_t *acquire_job_create(u_int32_t reqid) +{ + private_acquire_job_t *this = malloc_thing(private_acquire_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + /* private variables */ + this->reqid = reqid; + + return &(this->public); +} diff --git a/src/charon/processing/jobs/acquire_job.h b/src/charon/processing/jobs/acquire_job.h new file mode 100644 index 000000000..226966215 --- /dev/null +++ b/src/charon/processing/jobs/acquire_job.h @@ -0,0 +1,60 @@ +/** + * @file acquire_job.h + * + * @brief Interface of acquire_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef ACQUIRE_JOB_H_ +#define ACQUIRE_JOB_H_ + +typedef struct acquire_job_t acquire_job_t; + +#include <library.h> +#include <processing/jobs/job.h> + +/** + * @brief Class representing an ACQUIRE Job. + * + * This job initiates a CHILD SA on kernel request. + * + * @b Constructors: + * - acquire_job_create() + * + * @ingroup jobs + */ +struct acquire_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type ACQUIRE. + * + * We use the reqid to find the routed CHILD_SA. + * + * @param reqid reqid of the CHILD_SA to acquire + * @return acquire_job_t object + * + * @ingroup jobs + */ +acquire_job_t *acquire_job_create(u_int32_t reqid); + +#endif /* REKEY_CHILD_SA_JOB_H_ */ diff --git a/src/charon/processing/jobs/delete_child_sa_job.c b/src/charon/processing/jobs/delete_child_sa_job.c new file mode 100644 index 000000000..f694696b0 --- /dev/null +++ b/src/charon/processing/jobs/delete_child_sa_job.c @@ -0,0 +1,113 @@ +/** + * @file delete_child_sa_job.c + * + * @brief Implementation of delete_child_sa_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "delete_child_sa_job.h" + +#include <daemon.h> + + +typedef struct private_delete_child_sa_job_t private_delete_child_sa_job_t; + +/** + * Private data of an delete_child_sa_job_t object. + */ +struct private_delete_child_sa_job_t { + /** + + * Public delete_child_sa_job_t interface. + */ + delete_child_sa_job_t public; + + /** + * reqid of the CHILD_SA + */ + u_int32_t reqid; + + /** + * protocol of the CHILD_SA (ESP/AH) + */ + protocol_id_t protocol; + + /** + * inbound SPI of the CHILD_SA + */ + u_int32_t spi; +}; + +/** + * Implementation of job_t.get_type. + */ +static job_type_t get_type(private_delete_child_sa_job_t *this) +{ + return DELETE_CHILD_SA; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_delete_child_sa_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + this->reqid, TRUE); + if (ike_sa == NULL) + { + DBG1(DBG_JOB, "CHILD_SA with reqid %d not found for delete", + this->reqid); + return DESTROY_ME; + } + ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return DESTROY_ME; +} + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_delete_child_sa_job_t *this) +{ + free(this); +} + +/* + * Described in header + */ +delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, + protocol_id_t protocol, + u_int32_t spi) +{ + private_delete_child_sa_job_t *this = malloc_thing(private_delete_child_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + /* private variables */ + this->reqid = reqid; + this->protocol = protocol; + this->spi = spi; + + return &(this->public); +} diff --git a/src/charon/processing/jobs/delete_child_sa_job.h b/src/charon/processing/jobs/delete_child_sa_job.h new file mode 100644 index 000000000..0b90e008d --- /dev/null +++ b/src/charon/processing/jobs/delete_child_sa_job.h @@ -0,0 +1,68 @@ +/** + * @file delete_child_sa_job.h + * + * @brief Interface of delete_child_sa_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DELETE_CHILD_SA_JOB_H_ +#define DELETE_CHILD_SA_JOB_H_ + +typedef struct delete_child_sa_job_t delete_child_sa_job_t; + +#include <library.h> +#include <sa/ike_sa_id.h> +#include <processing/jobs/job.h> +#include <config/proposal.h> + + +/** + * @brief Class representing an DELETE_CHILD_SA Job. + * + * This job initiates the delete of a CHILD SA. + * + * @b Constructors: + * - delete_child_sa_job_create() + * + * @ingroup jobs + */ +struct delete_child_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type DELETE_CHILD_SA. + * + * The CHILD_SA is identified by its reqid, protocol (AH/ESP) and its + * inbound SPI. + * + * @param reqid reqid of the CHILD_SA, as used in kernel + * @param protocol protocol of the CHILD_SA + * @param spi security parameter index of the CHILD_SA + * @return delete_child_sa_job_t object + * + * @ingroup jobs + */ +delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, + protocol_id_t protocol, + u_int32_t spi); + +#endif /* DELETE_CHILD_SA_JOB_H_ */ diff --git a/src/charon/processing/jobs/delete_ike_sa_job.c b/src/charon/processing/jobs/delete_ike_sa_job.c new file mode 100644 index 000000000..706155aa6 --- /dev/null +++ b/src/charon/processing/jobs/delete_ike_sa_job.c @@ -0,0 +1,126 @@ +/** + * @file delete_ike_sa_job.c + * + * @brief Implementation of delete_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "delete_ike_sa_job.h" + +#include <daemon.h> + +typedef struct private_delete_ike_sa_job_t private_delete_ike_sa_job_t; + +/** + * Private data of an delete_ike_sa_job_t Object + */ +struct private_delete_ike_sa_job_t { + /** + * public delete_ike_sa_job_t interface + */ + delete_ike_sa_job_t public; + + /** + * ID of the ike_sa to delete + */ + ike_sa_id_t *ike_sa_id; + + /** + * Should the IKE_SA be deleted if it is in ESTABLISHED state? + */ + bool delete_if_established; +}; + +/** + * Implements job_t.get_type. + */ +static job_type_t get_type(private_delete_ike_sa_job_t *this) +{ + return DELETE_IKE_SA; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_delete_ike_sa_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa) + { + if (this->delete_if_established) + { + if (ike_sa->delete(ike_sa) == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + else + { + /* destroy only if not ESTABLISHED */ + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED) + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { + DBG1(DBG_JOB, "deleting half open IKE_SA after timeout"); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } + } + } + return DESTROY_ME; +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_delete_ike_sa_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header + */ +delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id, + bool delete_if_established) +{ + private_delete_ike_sa_job_t *this = malloc_thing(private_delete_ike_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t *)) destroy;; + + /* private variables */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + this->delete_if_established = delete_if_established; + + return &(this->public); +} diff --git a/src/charon/processing/jobs/delete_ike_sa_job.h b/src/charon/processing/jobs/delete_ike_sa_job.h new file mode 100644 index 000000000..11bb46e73 --- /dev/null +++ b/src/charon/processing/jobs/delete_ike_sa_job.h @@ -0,0 +1,66 @@ +/** + * @file delete_ike_sa_job.h + * + * @brief Interface of delete_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DELETE_IKE_SA_JOB_H_ +#define DELETE_IKE_SA_JOB_H_ + +typedef struct delete_ike_sa_job_t delete_ike_sa_job_t; + +#include <library.h> +#include <sa/ike_sa_id.h> +#include <processing/jobs/job.h> + + +/** + * @brief Class representing an DELETE_IKE_SA Job. + * + * This job is responsible for deleting established or half open IKE_SAs. + * A half open IKE_SA is every IKE_SA which hasn't reache the SA_ESTABLISHED + * state. + * + * @b Constructors: + * - delete_ike_sa_job_create() + * + * @ingroup jobs + */ +struct delete_ike_sa_job_t { + + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type DELETE_IKE_SA. + * + * @param ike_sa_id id of the IKE_SA to delete + * @param delete_if_established should the IKE_SA be deleted if it is established? + * @return created delete_ike_sa_job_t object + * + * @ingroup jobs + */ +delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id, + bool delete_if_established); + +#endif /* DELETE_IKE_SA_JOB_H_ */ diff --git a/src/charon/processing/jobs/job.c b/src/charon/processing/jobs/job.c new file mode 100644 index 000000000..d32d1bc61 --- /dev/null +++ b/src/charon/processing/jobs/job.c @@ -0,0 +1,39 @@ +/** + * @file job.c + * + * @brief Interface additions to job_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include "job.h" + +ENUM(job_type_names, PROCESS_MESSAGE, SEND_DPD, + "PROCESS_MESSAGE", + "RETRANSMIT", + "INITIATE", + "ROUTE", + "ACQUIRE", + "DELETE_IKE_SA", + "DELETE_CHILD_SA", + "REKEY_CHILD_SA", + "REKEY_IKE_SA", + "SEND_KEEPALIVE", + "SEND_DPD", +); diff --git a/src/charon/processing/jobs/job.h b/src/charon/processing/jobs/job.h new file mode 100644 index 000000000..28632672d --- /dev/null +++ b/src/charon/processing/jobs/job.h @@ -0,0 +1,165 @@ +/** + * @file job.h + * + * @brief Interface job_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef JOB_H_ +#define JOB_H_ + +typedef enum job_type_t job_type_t; +typedef struct job_t job_t; + +#include <library.h> + +/** + * @brief Definition of the various job types. + * + * @ingroup jobs + */ +enum job_type_t { + /** + * Process an incoming IKEv2-Message. + * + * Job is implemented in class process_message_job_t + */ + PROCESS_MESSAGE, + + /** + * Retransmit an IKEv2-Message. + * + * Job is implemented in class retransmit_job_t + */ + RETRANSMIT, + + /** + * Set up a CHILD_SA, optional with an IKE_SA. + * + * Job is implemented in class initiate_job_t + */ + INITIATE, + + /** + * Install SPD entries. + * + * Job is implemented in class route_job_t + */ + ROUTE, + + /** + * React on a acquire message from the kernel (e.g. setup CHILD_SA) + * + * Job is implemented in class acquire_job_t + */ + ACQUIRE, + + /** + * Delete an IKE_SA. + * + * Job is implemented in class delete_ike_sa_job_t + */ + DELETE_IKE_SA, + + /** + * Delete a CHILD_SA. + * + * Job is implemented in class delete_child_sa_job_t + */ + DELETE_CHILD_SA, + + /** + * Rekey a CHILD_SA. + * + * Job is implemented in class rekey_child_sa_job_t + */ + REKEY_CHILD_SA, + + /** + * Rekey an IKE_SA. + * + * Job is implemented in class rekey_ike_sa_job_t + */ + REKEY_IKE_SA, + + /** + * Send a keepalive packet. + * + * Job is implemented in class type send_keepalive_job_t + */ + SEND_KEEPALIVE, + + /** + * Send a DPD packet. + * + * Job is implemented in class type send_dpd_job_t + */ + SEND_DPD +}; + +/** + * enum name for job_type_t + * + * @ingroup jobs + */ +extern enum_name_t *job_type_names; + + +/** + * @brief Job-Interface as it is stored in the job queue. + * + * A job consists of a job-type and one or more assigned values. + * + * @b Constructors: + * - None, use specific implementation of the interface. + * + * @ingroup jobs + */ +struct job_t { + + /** + * @brief get type of job. + * + * @param this calling object + * @return type of this job + */ + job_type_t (*get_type) (job_t *this); + + /** + * @brief Execute a job. + * + * Call the internall job routine to process the + * job. If this method returns DESTROY_ME, the job + * must be destroyed by the caller. + * + * @param this calling object + * @return status of job execution + */ + status_t (*execute) (job_t *this); + + /** + * @brief Destroys a job_t object + * + * @param job_t calling object + */ + void (*destroy) (job_t *job); +}; + + +#endif /* JOB_H_ */ diff --git a/src/charon/processing/jobs/process_message_job.c b/src/charon/processing/jobs/process_message_job.c new file mode 100644 index 000000000..ee7484bbd --- /dev/null +++ b/src/charon/processing/jobs/process_message_job.c @@ -0,0 +1,106 @@ +/** + * @file process_message_job.h + * + * @brief Implementation of process_message_job_t. + * + */ + +/* + * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include "process_message_job.h" + +#include <daemon.h> + +typedef struct private_process_message_job_t private_process_message_job_t; + +/** + * Private data of an process_message_job_t Object + */ +struct private_process_message_job_t { + /** + * public process_message_job_t interface + */ + process_message_job_t public; + + /** + * Message associated with this job + */ + message_t *message; +}; + +/** + * Implements job_t.get_type. + */ +static job_type_t get_type(private_process_message_job_t *this) +{ + return PROCESS_MESSAGE; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_process_message_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout_by_message(charon->ike_sa_manager, + this->message); + if (ike_sa) + { + DBG1(DBG_NET, "received packet: from %#H to %#H", + this->message->get_source(this->message), + this->message->get_destination(this->message)); + if (ike_sa->process_message(ike_sa, this->message) == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + return DESTROY_ME; +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_process_message_job_t *this) +{ + this->message->destroy(this->message); + free(this); +} + +/* + * Described in header + */ +process_message_job_t *process_message_job_create(message_t *message) +{ + private_process_message_job_t *this = malloc_thing(private_process_message_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void(*)(job_t*))destroy; + + /* private variables */ + this->message = message; + + return &(this->public); +} diff --git a/src/charon/processing/jobs/process_message_job.h b/src/charon/processing/jobs/process_message_job.h new file mode 100644 index 000000000..5bb18155a --- /dev/null +++ b/src/charon/processing/jobs/process_message_job.h @@ -0,0 +1,58 @@ +/** + * @file process_message_job.h + * + * @brief Interface of process_message_job_t. + * + */ + +/* + * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef PROCESS_MESSAGE_JOB_H_ +#define PROCESS_MESSAGE_JOB_H_ + +typedef struct process_message_job_t process_message_job_t; + +#include <library.h> +#include <encoding/message.h> +#include <processing/jobs/job.h> + +/** + * @brief Class representing an PROCESS_MESSAGE job. + * + * @b Constructors: + * - process_message_job_create() + * + * @ingroup jobs + */ +struct process_message_job_t { + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type PROCESS_MESSAGE. + * + * @param message message to process + * @return created process_message_job_t object + * + * @ingroup jobs + */ +process_message_job_t *process_message_job_create(message_t *message); + +#endif /*PROCESS_MESSAGE_JOB_H_*/ diff --git a/src/charon/processing/jobs/rekey_child_sa_job.c b/src/charon/processing/jobs/rekey_child_sa_job.c new file mode 100644 index 000000000..3422b614d --- /dev/null +++ b/src/charon/processing/jobs/rekey_child_sa_job.c @@ -0,0 +1,112 @@ +/** + * @file rekey_child_sa_job.c + * + * @brief Implementation of rekey_child_sa_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "rekey_child_sa_job.h" + +#include <daemon.h> + + +typedef struct private_rekey_child_sa_job_t private_rekey_child_sa_job_t; + +/** + * Private data of an rekey_child_sa_job_t object. + */ +struct private_rekey_child_sa_job_t { + /** + * Public rekey_child_sa_job_t interface. + */ + rekey_child_sa_job_t public; + + /** + * reqid of the child to rekey + */ + u_int32_t reqid; + + /** + * protocol of the CHILD_SA (ESP/AH) + */ + protocol_id_t protocol; + + /** + * inbound SPI of the CHILD_SA + */ + u_int32_t spi; +}; + +/** + * Implementation of job_t.get_type. + */ +static job_type_t get_type(private_rekey_child_sa_job_t *this) +{ + return REKEY_CHILD_SA; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_rekey_child_sa_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + this->reqid, TRUE); + if (ike_sa == NULL) + { + DBG2(DBG_JOB, "CHILD_SA with reqid %d not found for rekeying", + this->reqid); + return DESTROY_ME; + } + ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return DESTROY_ME; +} + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_rekey_child_sa_job_t *this) +{ + free(this); +} + +/* + * Described in header + */ +rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, + protocol_id_t protocol, + u_int32_t spi) +{ + private_rekey_child_sa_job_t *this = malloc_thing(private_rekey_child_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + /* private variables */ + this->reqid = reqid; + this->protocol = protocol; + this->spi = spi; + + return &(this->public); +} diff --git a/src/charon/processing/jobs/rekey_child_sa_job.h b/src/charon/processing/jobs/rekey_child_sa_job.h new file mode 100644 index 000000000..df86070bc --- /dev/null +++ b/src/charon/processing/jobs/rekey_child_sa_job.h @@ -0,0 +1,65 @@ +/** + * @file rekey_child_sa_job.h + * + * @brief Interface of rekey_child_sa_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef REKEY_CHILD_SA_JOB_H_ +#define REKEY_CHILD_SA_JOB_H_ + +typedef struct rekey_child_sa_job_t rekey_child_sa_job_t; + +#include <library.h> +#include <sa/ike_sa_id.h> +#include <processing/jobs/job.h> +#include <config/proposal.h> + +/** + * @brief Class representing an REKEY_CHILD_SA Job. + * + * This job initiates the rekeying of a CHILD SA. + * + * @b Constructors: + * - rekey_child_sa_job_create() + * + * @ingroup jobs + */ +struct rekey_child_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type REKEY_CHILD_SA. + * + * The CHILD_SA is identified by its protocol (AH/ESP) and its + * inbound SPI. + * + * @param reqid reqid of the CHILD_SA to rekey + * @param protocol protocol of the CHILD_SA + * @param spi security parameter index of the CHILD_SA + * @return rekey_child_sa_job_t object + * + * @ingroup jobs + */ +rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, protocol_id_t protocol, u_int32_t spi); + +#endif /* REKEY_CHILD_SA_JOB_H_ */ diff --git a/src/charon/processing/jobs/rekey_ike_sa_job.c b/src/charon/processing/jobs/rekey_ike_sa_job.c new file mode 100644 index 000000000..f6c058634 --- /dev/null +++ b/src/charon/processing/jobs/rekey_ike_sa_job.c @@ -0,0 +1,120 @@ +/** + * @file rekey_ike_sa_job.c + * + * @brief Implementation of rekey_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "rekey_ike_sa_job.h" + +#include <daemon.h> + + +typedef struct private_rekey_ike_sa_job_t private_rekey_ike_sa_job_t; + +/** + * Private data of an rekey_ike_sa_job_t object. + */ +struct private_rekey_ike_sa_job_t { + /** + * Public rekey_ike_sa_job_t interface. + */ + rekey_ike_sa_job_t public; + + /** + * ID of the IKE_SA to rekey + */ + ike_sa_id_t *ike_sa_id; + + /** + * force reauthentication of the peer (full IKE_SA setup) + */ + bool reauth; +}; + +/** + * Implementation of job_t.get_type. + */ +static job_type_t get_type(private_rekey_ike_sa_job_t *this) +{ + return REKEY_IKE_SA; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_rekey_ike_sa_job_t *this) +{ + ike_sa_t *ike_sa; + status_t status = SUCCESS; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa == NULL) + { + DBG2(DBG_JOB, "IKE_SA to rekey not found"); + return DESTROY_ME; + } + + if (this->reauth) + { + ike_sa->reestablish(ike_sa); + } + else + { + status = ike_sa->rekey(ike_sa); + } + + if (status == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + return DESTROY_ME; +} + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_rekey_ike_sa_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header + */ +rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth) +{ + private_rekey_ike_sa_job_t *this = malloc_thing(private_rekey_ike_sa_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + /* private variables */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + this->reauth = reauth; + + return &(this->public); +} diff --git a/src/charon/processing/jobs/rekey_ike_sa_job.h b/src/charon/processing/jobs/rekey_ike_sa_job.h new file mode 100644 index 000000000..4031b3813 --- /dev/null +++ b/src/charon/processing/jobs/rekey_ike_sa_job.h @@ -0,0 +1,60 @@ +/** + * @file rekey_ike_sa_job.h + * + * @brief Interface of rekey_ike_sa_job_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef REKEY_IKE_SA_JOB_H_ +#define REKEY_IKE_SA_JOB_H_ + +typedef struct rekey_ike_sa_job_t rekey_ike_sa_job_t; + +#include <library.h> +#include <sa/ike_sa_id.h> +#include <processing/jobs/job.h> + +/** + * @brief Class representing an REKEY_IKE_SA Job. + * + * This job initiates the rekeying of an IKE_SA. + * + * @b Constructors: + * - rekey_ike_sa_job_create() + * + * @ingroup jobs + */ +struct rekey_ike_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type REKEY_IKE_SA. + * + * @param ike_sa_id ID of the IKE_SA to rekey + * @param reauth TRUE to reauthenticate peer, FALSE for rekeying only + * @return rekey_ike_sa_job_t object + * + * @ingroup jobs + */ +rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth); + +#endif /* REKEY_IKE_SA_JOB_H_ */ diff --git a/src/charon/processing/jobs/retransmit_job.c b/src/charon/processing/jobs/retransmit_job.c new file mode 100644 index 000000000..5bfa20dfd --- /dev/null +++ b/src/charon/processing/jobs/retransmit_job.c @@ -0,0 +1,109 @@ +/** + * @file retransmit_job.c + * + * @brief Implementation of retransmit_job_t. + * + */ + +/* + * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "retransmit_job.h" + +#include <daemon.h> + +typedef struct private_retransmit_job_t private_retransmit_job_t; + +/** + * Private data of an retransmit_job_t Object. + */ +struct private_retransmit_job_t { + /** + * Public retransmit_job_t interface. + */ + retransmit_job_t public; + + /** + * Message ID of the request to resend. + */ + u_int32_t message_id; + + /** + * ID of the IKE_SA which the message belongs to. + */ + ike_sa_id_t *ike_sa_id; +}; + +/** + * Implements job_t.get_type. + */ +static job_type_t get_type(private_retransmit_job_t *this) +{ + return RETRANSMIT; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_retransmit_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa) + { + if (ike_sa->retransmit(ike_sa, this->message_id) == DESTROY_ME) + { + /* retransmitted to many times, giving up */ + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + return DESTROY_ME; +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_retransmit_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header. + */ +retransmit_job_t *retransmit_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id) +{ + private_retransmit_job_t *this = malloc_thing(private_retransmit_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + /* private variables */ + this->message_id = message_id; + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + return &this->public; +} diff --git a/src/charon/processing/jobs/retransmit_job.h b/src/charon/processing/jobs/retransmit_job.h new file mode 100644 index 000000000..93bb548e7 --- /dev/null +++ b/src/charon/processing/jobs/retransmit_job.h @@ -0,0 +1,64 @@ +/** + * @file retransmit_job.h + * + * @brief Interface of retransmit_job_t. + * + */ + +/* + * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef RETRANSMIT_JOB_H_ +#define RETRANSMIT_JOB_H_ + +typedef struct retransmit_job_t retransmit_job_t; + +#include <library.h> +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +/** + * @brief Class representing an retransmit Job. + * + * This job is scheduled every time a request is sent over the + * wire. If the response to the request is not received at schedule + * time, the retransmission will be initiated. + * + * @b Constructors: + * - retransmit_job_create() + * + * @ingroup jobs + */ +struct retransmit_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * @brief Creates a job of type retransmit. + * + * @param message_id message_id of the request to resend + * @param ike_sa_id identification of the ike_sa as ike_sa_id_t + * @return retransmit_job_t object + * + * @ingroup jobs + */ +retransmit_job_t *retransmit_job_create(u_int32_t message_id, + ike_sa_id_t *ike_sa_id); + +#endif /* RETRANSMIT_JOB_H_ */ diff --git a/src/charon/processing/jobs/send_dpd_job.c b/src/charon/processing/jobs/send_dpd_job.c new file mode 100644 index 000000000..7294d78d5 --- /dev/null +++ b/src/charon/processing/jobs/send_dpd_job.c @@ -0,0 +1,110 @@ +/** + * @file send_dpd_job.c + * + * @brief Implementation of send_dpd_job_t. + * + */ + +/* + * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include <stdlib.h> + +#include "send_dpd_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +typedef struct private_send_dpd_job_t private_send_dpd_job_t; + +/** + * Private data of an send_dpd_job_t Object + */ +struct private_send_dpd_job_t { + /** + * public send_dpd_job_t interface + */ + send_dpd_job_t public; + + /** + * ID of the IKE_SA which the message belongs to. + */ + ike_sa_id_t *ike_sa_id; +}; + +/** + * Implements send_dpd_job_t.get_type. + */ +static job_type_t get_type(private_send_dpd_job_t *this) +{ + return SEND_DPD; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_send_dpd_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa == NULL) + { + return DESTROY_ME; + } + + if (ike_sa->send_dpd(ike_sa) == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + return DESTROY_ME; +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_send_dpd_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header + */ +send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id) +{ + private_send_dpd_job_t *this = malloc_thing(private_send_dpd_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + + /* public functions */ + this->public.destroy = (void (*)(send_dpd_job_t *)) destroy; + + /* private variables */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + return &(this->public); +} diff --git a/src/charon/processing/jobs/send_dpd_job.h b/src/charon/processing/jobs/send_dpd_job.h new file mode 100644 index 000000000..26c9e2e81 --- /dev/null +++ b/src/charon/processing/jobs/send_dpd_job.h @@ -0,0 +1,67 @@ +/** + * @file send_dpd_job.h + * + * @brief Interface of send_dpd_job_t. + */ + +/* + * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SEND_DPD_JOB_H_ +#define SEND_DPD_JOB_H_ + +typedef struct send_dpd_job_t send_dpd_job_t; + +#include <library.h> +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +/** + * @brief Class representing a SEND_DPD Job. + * + * Job to periodically send a Dead Peer Detection (DPD) request, + * ie. an IKE request with no payloads other than the encrypted payload + * required by the syntax. + * + * @b Constructors: + * - send_dpd_job_create() + * + * @ingroup jobs + */ +struct send_dpd_job_t { + /** + * implements job_t interface + */ + job_t job_interface; + + /** + * @brief Destroys an send_dpd_job_t object. + * + * @param this send_dpd_job_t object to destroy + */ + void (*destroy) (send_dpd_job_t *this); +}; + +/** + * @brief Creates a job of type SEND_DPD. + * + * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) + * @return initiate_ike_sa_job_t object + * + * @ingroup jobs + */ +send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id); + +#endif /*SEND_DPD_JOB_H_*/ diff --git a/src/charon/processing/jobs/send_keepalive_job.c b/src/charon/processing/jobs/send_keepalive_job.c new file mode 100644 index 000000000..1c1cb288e --- /dev/null +++ b/src/charon/processing/jobs/send_keepalive_job.c @@ -0,0 +1,103 @@ +/** + * @file send_keepalive_job.c + * + * @brief Implementation of send_keepalive_job_t. + * + */ + +/* + * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include <stdlib.h> + +#include "send_keepalive_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +typedef struct private_send_keepalive_job_t private_send_keepalive_job_t; + +/** + * Private data of an send_keepalive_job_t Object + */ +struct private_send_keepalive_job_t { + /** + * public send_keepalive_job_t interface + */ + send_keepalive_job_t public; + + /** + * ID of the IKE_SA which the message belongs to. + */ + ike_sa_id_t *ike_sa_id; +}; + +/** + * Implements send_keepalive_job_t.get_type. + */ +static job_type_t get_type(private_send_keepalive_job_t *this) +{ + return SEND_KEEPALIVE; +} + +/** + * Implementation of job_t.execute. + */ +static status_t execute(private_send_keepalive_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa == NULL) + { + return DESTROY_ME; + } + ike_sa->send_keepalive(ike_sa); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return DESTROY_ME; +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_send_keepalive_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/* + * Described in header + */ +send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id) +{ + private_send_keepalive_job_t *this = malloc_thing(private_send_keepalive_job_t); + + /* interface functions */ + this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + this->public.job_interface.execute = (status_t (*) (job_t *)) execute; + + /* public functions */ + this->public.destroy = (void (*)(send_keepalive_job_t *)) destroy; + + /* private variables */ + this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + + return &(this->public); +} diff --git a/src/charon/processing/jobs/send_keepalive_job.h b/src/charon/processing/jobs/send_keepalive_job.h new file mode 100644 index 000000000..f7b38337e --- /dev/null +++ b/src/charon/processing/jobs/send_keepalive_job.h @@ -0,0 +1,66 @@ +/** + * @file send_keepalive_job.h + * + * @brief Interface of send_keepalive_job_t. + */ + +/* + * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SEND_KEEPALIVE_JOB_H_ +#define SEND_KEEPALIVE_JOB_H_ + +typedef struct send_keepalive_job_t send_keepalive_job_t; + +#include <library.h> +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +/** + * @brief Class representing a SEND_KEEPALIVE Job. + * + * This job will send a NAT keepalive packet if the IKE SA is still alive, + * and reinsert itself into the event queue. + * + * @b Constructors: + * - send_keepalive_job_create() + * + * @ingroup jobs + */ +struct send_keepalive_job_t { + /** + * implements job_t interface + */ + job_t job_interface; + + /** + * @brief Destroys an send_keepalive_job_t object. + * + * @param this send_keepalive_job_t object to destroy + */ + void (*destroy) (send_keepalive_job_t *this); +}; + +/** + * @brief Creates a job of type SEND_KEEPALIVE. + * + * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) + * @return initiate_ike_sa_job_t object + * + * @ingroup jobs + */ +send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id); + +#endif /*SEND_KEEPALIVE_JOB_H_*/ diff --git a/src/charon/processing/scheduler.c b/src/charon/processing/scheduler.c new file mode 100644 index 000000000..7249e43e6 --- /dev/null +++ b/src/charon/processing/scheduler.c @@ -0,0 +1,104 @@ +/** + * @file scheduler.c + * + * @brief Implementation of scheduler_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <stdlib.h> +#include <pthread.h> + +#include "scheduler.h" + +#include <daemon.h> +#include <processing/job_queue.h> + + +typedef struct private_scheduler_t private_scheduler_t; + +/** + * Private data of a scheduler_t object. + */ +struct private_scheduler_t { + /** + * Public part of a scheduler_t object. + */ + scheduler_t public; + + /** + * Assigned thread. + */ + pthread_t assigned_thread; +}; + +/** + * Implementation of private_scheduler_t.get_events. + */ +static void get_events(private_scheduler_t * this) +{ + job_t *current_job; + + /* cancellation disabled by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + DBG1(DBG_JOB, "scheduler thread running, thread_ID: %06u", + (int)pthread_self()); + + charon->drop_capabilities(charon, TRUE); + + while (TRUE) + { + DBG2(DBG_JOB, "waiting for next event..."); + /* get a job, this block until one is available */ + current_job = charon->event_queue->get(charon->event_queue); + /* queue the job in the job queue, workers will eat them */ + DBG2(DBG_JOB, "got event, adding job %N to job-queue", + job_type_names, current_job->get_type(current_job)); + charon->job_queue->add(charon->job_queue, current_job); + } +} + +/** + * Implementation of scheduler_t.destroy. + */ +static void destroy(private_scheduler_t *this) +{ + pthread_cancel(this->assigned_thread); + pthread_join(this->assigned_thread, NULL); + free(this); +} + +/* + * Described in header. + */ +scheduler_t * scheduler_create() +{ + private_scheduler_t *this = malloc_thing(private_scheduler_t); + + this->public.destroy = (void(*)(scheduler_t*)) destroy; + + if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))get_events, this) != 0) + { + /* thread could not be created */ + free(this); + charon->kill(charon, "unable to create scheduler thread"); + } + + return &(this->public); +} diff --git a/src/charon/processing/scheduler.h b/src/charon/processing/scheduler.h new file mode 100644 index 000000000..bea93e7c9 --- /dev/null +++ b/src/charon/processing/scheduler.h @@ -0,0 +1,68 @@ +/** + * @file scheduler.h + * + * @brief Interface of scheduler_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SCHEDULER_H_ +#define SCHEDULER_H_ + +typedef struct scheduler_t scheduler_t; + +#include <library.h> + +/** + * @brief The scheduler thread is responsible for timed events. + * + * The scheduler thread takes out jobs from the event-queue and adds them + * to the job-queue. + * + * Starts a thread which does the work, since event-queue is blocking. + * + * @b Constructors: + * - scheduler_create() + * + * @ingroup processing + */ +struct scheduler_t { + + /** + * @brief Destroys a scheduler object. + * + * @param scheduler calling object + */ + void (*destroy) (scheduler_t *scheduler); +}; + +/** + * @brief Create a scheduler with its associated thread. + * + * The thread will start to get jobs form the event queue + * and adds them to the job queue. + * + * @return + * - scheduler_t object + * - NULL if thread could not be started + * + * @ingroup processing + */ +scheduler_t * scheduler_create(void); + +#endif /*SCHEDULER_H_*/ diff --git a/src/charon/processing/thread_pool.c b/src/charon/processing/thread_pool.c new file mode 100644 index 000000000..a9891da15 --- /dev/null +++ b/src/charon/processing/thread_pool.c @@ -0,0 +1,183 @@ +/** + * @file thread_pool.c + * + * @brief Implementation of thread_pool_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <stdlib.h> +#include <pthread.h> +#include <string.h> +#include <errno.h> + +#include "thread_pool.h" + +#include <daemon.h> +#include <processing/job_queue.h> + + +typedef struct private_thread_pool_t private_thread_pool_t; + +/** + * @brief Private data of thread_pool_t class. + */ +struct private_thread_pool_t { + /** + * Public thread_pool_t interface. + */ + thread_pool_t public; + + /** + * Number of running threads. + */ + u_int pool_size; + + /** + * Number of threads waiting for work + */ + u_int idle_threads; + + /** + * Array of thread ids. + */ + pthread_t *threads; +}; + +/** + * Implementation of private_thread_pool_t.process_jobs. + */ +static void process_jobs(private_thread_pool_t *this) +{ + job_t *job; + status_t status; + + /* cancellation disabled by default */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + DBG1(DBG_JOB, "worker thread running, thread_ID: %06u", + (int)pthread_self()); + + charon->drop_capabilities(charon, TRUE); + + while (TRUE) + { + /* TODO: should be atomic, but is not mission critical */ + this->idle_threads++; + job = charon->job_queue->get(charon->job_queue); + this->idle_threads--; + + status = job->execute(job); + + if (status == DESTROY_ME) + { + job->destroy(job); + } + } +} + +/** + * Implementation of thread_pool_t.get_pool_size. + */ +static u_int get_pool_size(private_thread_pool_t *this) +{ + return this->pool_size; +} + +/** + * Implementation of thread_pool_t.get_idle_threads. + */ +static u_int get_idle_threads(private_thread_pool_t *this) +{ + return this->idle_threads; +} + +/** + * Implementation of thread_pool_t.destroy. + */ +static void destroy(private_thread_pool_t *this) +{ + int current; + /* flag thread for termination */ + for (current = 0; current < this->pool_size; current++) + { + DBG1(DBG_JOB, "cancelling worker thread #%d", current+1); + pthread_cancel(this->threads[current]); + } + + /* wait for all threads */ + for (current = 0; current < this->pool_size; current++) { + if (pthread_join(this->threads[current], NULL) == 0) + { + DBG1(DBG_JOB, "worker thread #%d terminated", current+1); + } + else + { + DBG1(DBG_JOB, "could not terminate worker thread #%d", current+1); + } + } + + /* free mem */ + free(this->threads); + free(this); +} + +/* + * Described in header. + */ +thread_pool_t *thread_pool_create(size_t pool_size) +{ + int current; + private_thread_pool_t *this = malloc_thing(private_thread_pool_t); + + /* fill in public fields */ + this->public.destroy = (void(*)(thread_pool_t*))destroy; + this->public.get_pool_size = (u_int(*)(thread_pool_t*))get_pool_size; + this->public.get_idle_threads = (u_int(*)(thread_pool_t*))get_idle_threads; + + /* initialize member */ + this->pool_size = pool_size; + this->idle_threads = 0; + this->threads = malloc(sizeof(pthread_t) * pool_size); + + /* try to create as many threads as possible, up to pool_size */ + for (current = 0; current < pool_size; current++) + { + if (pthread_create(&(this->threads[current]), NULL, + (void*(*)(void*))process_jobs, this) == 0) + { + DBG1(DBG_JOB, "created worker thread #%d", current+1); + } + else + { + /* creation failed, is it the first one? */ + if (current == 0) + { + free(this->threads); + free(this); + charon->kill(charon, "could not create any worker threads"); + } + /* not all threads could be created, but at least one :-/ */ + DBG1(DBG_JOB, "could only create %d from requested %d threads!", + current, pool_size); + this->pool_size = current; + break; + } + } + return (thread_pool_t*)this; +} diff --git a/src/charon/processing/thread_pool.h b/src/charon/processing/thread_pool.h new file mode 100644 index 000000000..09a6312a8 --- /dev/null +++ b/src/charon/processing/thread_pool.h @@ -0,0 +1,87 @@ +/** + * @file thread_pool.h + * + * @brief Interface of thread_pool_t. + * + */ + +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef THREAD_POOL_H_ +#define THREAD_POOL_H_ + +typedef struct thread_pool_t thread_pool_t; + +#include <stdlib.h> + +#include <library.h> + +/** + * @brief A thread_pool consists of a pool of threads processing jobs from the job queue. + * + * Current implementation uses as many threads as specified in constructor. + * A more improved version would dynamically increase thread count if necessary. + * + * @b Constructors: + * - thread_pool_create() + * + * @todo Add support for dynamic thread handling + * + * @ingroup processing + */ +struct thread_pool_t { + + /** + * @brief Return currently instanciated thread count. + * + * @param thread_pool calling object + * @return size of thread pool + */ + u_int (*get_pool_size) (thread_pool_t *thread_pool); + + /** + * @brief Get the number of threads currently waiting for work. + * + * @param thread_pool calling object + * @return number of idle threads + */ + u_int (*get_idle_threads) (thread_pool_t *thread_pool); + + /** + * @brief Destroy a thread_pool_t object. + * + * Sends cancellation request to all threads and AWAITS their termination. + * + * @param thread_pool calling object + */ + void (*destroy) (thread_pool_t *thread_pool); +}; + +/** + * @brief Create the thread pool using using pool_size of threads. + * + * @param pool_size desired pool size + * @return + * - thread_pool_t object if one ore more threads could be started, or + * - NULL if no threads could be created + * + * @ingroup processing + */ +thread_pool_t *thread_pool_create(size_t pool_size); + + +#endif /*THREAD_POOL_H_*/ |