diff options
Diffstat (limited to 'src/libcharon/processing/jobs')
33 files changed, 3118 insertions, 0 deletions
diff --git a/src/libcharon/processing/jobs/acquire_job.c b/src/libcharon/processing/jobs/acquire_job.c new file mode 100644 index 000000000..45ace9312 --- /dev/null +++ b/src/libcharon/processing/jobs/acquire_job.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2006-2009 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; + + /** + * acquired source traffic selector + */ + traffic_selector_t *src_ts; + + /** + * acquired destination traffic selector + */ + traffic_selector_t *dst_ts; +}; + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_acquire_job_t *this) +{ + DESTROY_IF(this->src_ts); + DESTROY_IF(this->dst_ts); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_acquire_job_t *this) +{ + charon->traps->acquire(charon->traps, this->reqid, + this->src_ts, this->dst_ts); + destroy(this); +} + +/* + * Described in header + */ +acquire_job_t *acquire_job_create(u_int32_t reqid, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts) +{ + private_acquire_job_t *this = malloc_thing(private_acquire_job_t); + + this->public.job_interface.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + this->reqid = reqid; + this->src_ts = src_ts; + this->dst_ts = dst_ts; + + return &this->public; +} + diff --git a/src/libcharon/processing/jobs/acquire_job.h b/src/libcharon/processing/jobs/acquire_job.h new file mode 100644 index 000000000..eff79a9b0 --- /dev/null +++ b/src/libcharon/processing/jobs/acquire_job.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +/** + * @defgroup acquire_job acquire_job + * @{ @ingroup jobs + */ + +#ifndef ACQUIRE_JOB_H_ +#define ACQUIRE_JOB_H_ + +typedef struct acquire_job_t acquire_job_t; + +#include <library.h> +#include <selectors/traffic_selector.h> +#include <processing/jobs/job.h> + +/** + * Class representing an ACQUIRE Job. + * + * This job initiates a CHILD SA on kernel request. + */ +struct acquire_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * Creates a job of type ACQUIRE. + * + * @param reqid reqid of the trapped CHILD_SA to acquire + * @param src_ts source traffic selector + * @param dst_ts destination traffic selector + * @return acquire_job_t object + */ +acquire_job_t *acquire_job_create(u_int32_t reqid, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts); + +#endif /** REKEY_CHILD_SA_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/callback_job.c b/src/libcharon/processing/jobs/callback_job.c new file mode 100644 index 000000000..45e49112e --- /dev/null +++ b/src/libcharon/processing/jobs/callback_job.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2009 Tobias Brunner + * Copyright (C) 2007 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 "callback_job.h" + +#include <semaphore.h> + +#include <daemon.h> +#include <threading/thread.h> +#include <threading/condvar.h> +#include <threading/mutex.h> + +typedef struct private_callback_job_t private_callback_job_t; + +/** + * Private data of an callback_job_t Object. + */ +struct private_callback_job_t { + /** + * Public callback_job_t interface. + */ + callback_job_t public; + + /** + * Callback to call on execution + */ + callback_job_cb_t callback; + + /** + * parameter to supply to callback + */ + void *data; + + /** + * cleanup function for data + */ + callback_job_cleanup_t cleanup; + + /** + * thread of the job, if running + */ + thread_t *thread; + + /** + * mutex to access jobs interna + */ + mutex_t *mutex; + + /** + * list of asociated child jobs + */ + linked_list_t *children; + + /** + * parent of this job, or NULL + */ + private_callback_job_t *parent; + + /** + * TRUE if the job got cancelled + */ + bool cancelled; + + /** + * condvar to synchronize the cancellation/destruction of the job + */ + condvar_t *destroyable; + + /** + * semaphore to synchronize the termination of the assigned thread. + * + * separately allocated during cancellation, so that we can wait on it + * without risking that it gets freed too early during destruction. + */ + sem_t *terminated; +}; + +/** + * unregister a child from its parent, if any. + * note: this->mutex has to be locked + */ +static void unregister(private_callback_job_t *this) +{ + if (this->parent) + { + this->parent->mutex->lock(this->parent->mutex); + if (this->parent->cancelled && !this->cancelled) + { + /* if the parent has been cancelled but we have not yet, we do not + * unregister until we got cancelled by the parent. */ + this->parent->mutex->unlock(this->parent->mutex); + this->destroyable->wait(this->destroyable, this->mutex); + this->parent->mutex->lock(this->parent->mutex); + } + this->parent->children->remove(this->parent->children, this, NULL); + this->parent->mutex->unlock(this->parent->mutex); + this->parent = NULL; + } +} + +/** + * Implements job_t.destroy. + */ +static void destroy(private_callback_job_t *this) +{ + this->mutex->lock(this->mutex); + unregister(this); + if (this->cleanup) + { + this->cleanup(this->data); + } + if (this->terminated) + { + sem_post(this->terminated); + } + this->children->destroy(this->children); + this->destroyable->destroy(this->destroyable); + this->mutex->unlock(this->mutex); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * Implementation of callback_job_t.cancel. + */ +static void cancel(private_callback_job_t *this) +{ + callback_job_t *child; + sem_t *terminated = NULL; + + this->mutex->lock(this->mutex); + this->cancelled = TRUE; + /* terminate children */ + while (this->children->get_first(this->children, (void**)&child) == SUCCESS) + { + this->mutex->unlock(this->mutex); + child->cancel(child); + this->mutex->lock(this->mutex); + } + if (this->thread) + { + /* terminate the thread, if there is currently one executing the job. + * we wait for its termination using a semaphore */ + this->thread->cancel(this->thread); + terminated = this->terminated = malloc_thing(sem_t); + sem_init(terminated, 0, 0); + } + else + { + /* if the job is currently queued, it gets terminated later. + * we can't wait, because it might not get executed at all. + * we also unregister the queued job manually from its parent (the + * others get unregistered during destruction) */ + unregister(this); + } + this->destroyable->signal(this->destroyable); + this->mutex->unlock(this->mutex); + + if (terminated) + { + sem_wait(terminated); + sem_destroy(terminated); + free(terminated); + } +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_callback_job_t *this) +{ + bool cleanup = FALSE, requeue = FALSE; + + thread_cleanup_push((thread_cleanup_t)destroy, this); + + this->mutex->lock(this->mutex); + this->thread = thread_current(); + this->mutex->unlock(this->mutex); + + while (TRUE) + { + this->mutex->lock(this->mutex); + if (this->cancelled) + { + this->mutex->unlock(this->mutex); + cleanup = TRUE; + break; + } + this->mutex->unlock(this->mutex); + switch (this->callback(this->data)) + { + case JOB_REQUEUE_DIRECT: + continue; + case JOB_REQUEUE_FAIR: + { + requeue = TRUE; + break; + } + case JOB_REQUEUE_NONE: + default: + { + cleanup = TRUE; + break; + } + } + break; + } + this->mutex->lock(this->mutex); + this->thread = NULL; + this->mutex->unlock(this->mutex); + /* manually create a cancellation point to avoid that a cancelled thread + * goes back into the thread pool */ + thread_cancellation_point(); + if (requeue) + { + charon->processor->queue_job(charon->processor, + &this->public.job_interface); + } + thread_cleanup_pop(cleanup); +} + +/* + * Described in header. + */ +callback_job_t *callback_job_create(callback_job_cb_t cb, void *data, + callback_job_cleanup_t cleanup, + callback_job_t *parent) +{ + private_callback_job_t *this = malloc_thing(private_callback_job_t); + + /* interface functions */ + this->public.job_interface.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + this->public.cancel = (void(*)(callback_job_t*))cancel; + + /* private variables */ + this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); + this->callback = cb; + this->data = data; + this->cleanup = cleanup; + this->thread = 0; + this->children = linked_list_create(); + this->parent = (private_callback_job_t*)parent; + this->cancelled = FALSE; + this->destroyable = condvar_create(CONDVAR_TYPE_DEFAULT); + this->terminated = NULL; + + /* register us at parent */ + if (parent) + { + this->parent->mutex->lock(this->parent->mutex); + this->parent->children->insert_last(this->parent->children, this); + this->parent->mutex->unlock(this->parent->mutex); + } + + return &this->public; +} + diff --git a/src/libcharon/processing/jobs/callback_job.h b/src/libcharon/processing/jobs/callback_job.h new file mode 100644 index 000000000..62da1edd1 --- /dev/null +++ b/src/libcharon/processing/jobs/callback_job.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2007 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. + */ + +/** + * @defgroup callback_job callback_job + * @{ @ingroup jobs + */ + +#ifndef CALLBACK_JOB_H_ +#define CALLBACK_JOB_H_ + +typedef struct callback_job_t callback_job_t; + +#include <library.h> +#include <processing/jobs/job.h> + + +typedef enum job_requeue_t job_requeue_t; + +/** + * Job requeueing policy + * + * The job requeueing policy defines how a job is handled when the callback + * function returns. + */ +enum job_requeue_t { + + /** + * Do not requeue job, destroy it + */ + JOB_REQUEUE_NONE, + + /** + * Reque the job fairly, meaning it has to requeue as any other job + */ + JOB_REQUEUE_FAIR, + + /** + * Reexecute the job directly, without the need of requeueing it + */ + JOB_REQUEUE_DIRECT, +}; + +/** + * The callback function to use for the callback job. + * + * This is the function to use as callback for a callback job. It receives + * a parameter supplied to the callback jobs constructor. + * + * @param data param supplied to job + * @return requeing policy how to requeue the job + */ +typedef job_requeue_t (*callback_job_cb_t)(void *data); + +/** + * Cleanup function to use for data cleanup. + * + * The callback has an optional user argument which receives data. However, + * this data may be cleaned up if it is allocated. This is the function + * to supply to the constructor. + * + * @param data param supplied to job + * @return requeing policy how to requeue the job + */ +typedef void (*callback_job_cleanup_t)(void *data); + +/** + * Class representing an callback Job. + * + * This is a special job which allows a simple callback function to + * be executed by a thread of the thread pool. This allows simple execution + * of asynchronous methods, without to manage threads. + */ +struct callback_job_t { + /** + * The job_t interface. + */ + job_t job_interface; + + /** + * Cancel the job's thread and wait for its termination. This only works + * reliably for jobs that always use JOB_REQUEUE_FAIR or JOB_REQUEUE_DIRECT, + * otherwise the job may already be destroyed when cancel is called. */ + void (*cancel)(callback_job_t *this); +}; + +/** + * Creates a callback job. + * + * The cleanup function is called when the job gets destroyed to destroy + * the associated data. + * If parent is not NULL, the specified job gets an association. Whenever + * the parent gets cancelled (or runs out), all of its children are cancelled, + * too. + * + * @param cb callback to call from the processor + * @param data user data to supply to callback + * @param cleanup destructor for data on destruction, or NULL + * @param parent parent of this job + * @return callback_job_t object + */ +callback_job_t *callback_job_create(callback_job_cb_t cb, void *data, + callback_job_cleanup_t cleanup, + callback_job_t *parent); + +#endif /** CALLBACK_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c new file mode 100644 index 000000000..ca55721f2 --- /dev/null +++ b/src/libcharon/processing/jobs/delete_child_sa_job.c @@ -0,0 +1,100 @@ +/* + * 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.destroy. + */ +static void destroy(private_delete_child_sa_job_t *this) +{ + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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); + } + else + { + ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + destroy(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.execute = (void (*) (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/libcharon/processing/jobs/delete_child_sa_job.h b/src/libcharon/processing/jobs/delete_child_sa_job.h new file mode 100644 index 000000000..662a7b7c7 --- /dev/null +++ b/src/libcharon/processing/jobs/delete_child_sa_job.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/** + * @defgroup delete_child_sa_job delete_child_sa_job + * @{ @ingroup jobs + */ + +#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> + + +/** + * Class representing an DELETE_CHILD_SA Job. + * + * This job initiates the delete of a CHILD SA. + */ +struct delete_child_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * 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 + */ +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/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c new file mode 100644 index 000000000..dffd08ba3 --- /dev/null +++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c @@ -0,0 +1,116 @@ +/* + * 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.destroy. + */ +static void destroy(private_delete_ike_sa_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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 (ike_sa->get_state(ike_sa) == IKE_PASSIVE) + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return destroy(this); + } + 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); + } + } + } + destroy(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.execute = (void (*) (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/libcharon/processing/jobs/delete_ike_sa_job.h b/src/libcharon/processing/jobs/delete_ike_sa_job.h new file mode 100644 index 000000000..f641deea3 --- /dev/null +++ b/src/libcharon/processing/jobs/delete_ike_sa_job.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +/** + * @defgroup delete_child_sa_job delete_child_sa_job + * @{ @ingroup jobs + */ + +#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> + + +/** + * 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. + */ +struct delete_ike_sa_job_t { + + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * 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 + */ +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/libcharon/processing/jobs/inactivity_job.c b/src/libcharon/processing/jobs/inactivity_job.c new file mode 100644 index 000000000..13fc5e3d0 --- /dev/null +++ b/src/libcharon/processing/jobs/inactivity_job.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2010 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 "inactivity_job.h" + +#include <daemon.h> + +typedef struct private_inactivity_job_t private_inactivity_job_t; + +/** + * Private data of an inactivity_job_t object. + */ +struct private_inactivity_job_t { + + /** + * Public inactivity_job_t interface. + */ + inactivity_job_t public; + + /** + * Reqid of CHILD_SA to check + */ + u_int32_t reqid; + + /** + * Inactivity timeout + */ + u_int32_t timeout; + + /** + * Close IKE_SA if last remaining CHILD inactive? + */ + bool close_ike; +}; + +METHOD(job_t, destroy, void, + private_inactivity_job_t *this) +{ + free(this); +} + +METHOD(job_t, execute, void, + private_inactivity_job_t *this) +{ + ike_sa_t *ike_sa; + bool rescheduled = FALSE; + + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + this->reqid, TRUE); + if (ike_sa) + { + iterator_t *iterator; + child_sa_t *child_sa; + u_int32_t delete = 0; + protocol_id_t proto = 0; + int children = 0; + status_t status = SUCCESS; + + iterator = ike_sa->create_child_sa_iterator(ike_sa); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + if (child_sa->get_reqid(child_sa) == this->reqid) + { + time_t in, out, diff; + + child_sa->get_usestats(child_sa, TRUE, &in, NULL); + child_sa->get_usestats(child_sa, FALSE, &out, NULL); + + diff = time_monotonic(NULL) - max(in, out); + + if (diff >= this->timeout) + { + delete = child_sa->get_spi(child_sa, TRUE); + proto = child_sa->get_protocol(child_sa); + } + else + { + charon->scheduler->schedule_job(charon->scheduler, + &this->public.job_interface, this->timeout - diff); + rescheduled = TRUE; + } + } + children++; + } + iterator->destroy(iterator); + + if (delete) + { + if (children == 1 && this->close_ike) + { + DBG1(DBG_JOB, "deleting IKE_SA after %d seconds " + "of CHILD_SA inactivity", this->timeout); + status = ike_sa->delete(ike_sa); + } + else + { + DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds " + "of inactivity", this->timeout); + status = ike_sa->delete_child_sa(ike_sa, proto, delete); + } + } + 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); + } + } + if (!rescheduled) + { + destroy(this); + } +} + +/** + * See header + */ +inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout, + bool close_ike) +{ + private_inactivity_job_t *this; + + INIT(this, + .public.job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + .reqid = reqid, + .timeout = timeout, + .close_ike = close_ike, + ); + + return &this->public; +} + diff --git a/src/libcharon/processing/jobs/inactivity_job.h b/src/libcharon/processing/jobs/inactivity_job.h new file mode 100644 index 000000000..9c9daced8 --- /dev/null +++ b/src/libcharon/processing/jobs/inactivity_job.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup inactivity_job inactivity_job + * @{ @ingroup jobs + */ + +#ifndef INACTIVITY_JOB_H_ +#define INACTIVITY_JOB_H_ + +#include <library.h> +#include <processing/jobs/job.h> + +typedef struct inactivity_job_t inactivity_job_t; + +/** + * Job checking for inactivity of CHILD_SA to close them. + * + * The inactivity job reschedules itself to check CHILD_SAs prediodically. + */ +struct inactivity_job_t { + + /** + * Implements job_t. + */ + job_t job_interface; +}; + +/** + * Create a inactivity_job instance. + * + * @param reqid reqid of CHILD_SA to check for inactivity + * @param timeout inactivity timeout in s + * @param close_ike close IKE_SA if the last remaining CHILD_SA is inactive? + * @return inactivity checking job + */ +inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout, + bool close_ike); + +#endif /** INACTIVITY_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c new file mode 100644 index 000000000..ffe8755e2 --- /dev/null +++ b/src/libcharon/processing/jobs/initiate_mediation_job.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2007-2008 Tobias Brunner + * 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 "initiate_mediation_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +typedef struct private_initiate_mediation_job_t private_initiate_mediation_job_t; + +/** + * Private data of an initiate_mediation_job_t Object + */ +struct private_initiate_mediation_job_t { + /** + * public initiate_mediation_job_t interface + */ + initiate_mediation_job_t public; + + /** + * ID of the IKE_SA of the mediated connection. + */ + ike_sa_id_t *mediated_sa_id; + + /** + * ID of the IKE_SA of the mediation connection. + */ + ike_sa_id_t *mediation_sa_id; +}; + +/** + * Implements job_t.destroy. + */ +static void destroy(private_initiate_mediation_job_t *this) +{ + DESTROY_IF(this->mediation_sa_id); + DESTROY_IF(this->mediated_sa_id); + free(this); +} + +/** + * Callback to handle initiation of mediation connection + */ +static bool initiate_callback(private_initiate_mediation_job_t *this, + debug_t group, level_t level, ike_sa_t *ike_sa, + char *format, va_list args) +{ + if (ike_sa && !this->mediation_sa_id) + { + this->mediation_sa_id = ike_sa->get_id(ike_sa); + this->mediation_sa_id = this->mediation_sa_id->clone(this->mediation_sa_id); + } + return TRUE; +} + +/** + * Implementation of job_t.execute. + */ +static void initiate(private_initiate_mediation_job_t *this) +{ + ike_sa_t *mediated_sa, *mediation_sa; + peer_cfg_t *mediated_cfg, *mediation_cfg; + enumerator_t *enumerator; + auth_cfg_t *auth_cfg; + + mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->mediated_sa_id); + if (mediated_sa) + { + DBG1(DBG_IKE, "initiating mediation connection"); + mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa); + mediated_cfg->get_ref(mediated_cfg); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa); + + mediation_cfg = mediated_cfg->get_mediated_by(mediated_cfg); + mediation_cfg->get_ref(mediation_cfg); + + enumerator = mediation_cfg->create_auth_cfg_enumerator(mediation_cfg, + TRUE); + if (!enumerator->enumerate(enumerator, &auth_cfg) || + auth_cfg->get(auth_cfg, AUTH_RULE_IDENTITY) == NULL) + { + mediated_cfg->destroy(mediated_cfg); + mediation_cfg->destroy(mediation_cfg); + enumerator->destroy(enumerator); + destroy(this); + return; + } + enumerator->destroy(enumerator); + + if (charon->connect_manager->check_and_register(charon->connect_manager, + auth_cfg->get(auth_cfg, AUTH_RULE_IDENTITY), + mediated_cfg->get_peer_id(mediated_cfg), + this->mediated_sa_id)) + { + mediated_cfg->destroy(mediated_cfg); + mediation_cfg->destroy(mediation_cfg); + + mediated_sa = charon->ike_sa_manager->checkout( + charon->ike_sa_manager, this->mediated_sa_id); + if (mediated_sa) + { + DBG1(DBG_IKE, "mediation with the same peer is already in " + "progress, queued"); + charon->ike_sa_manager->checkin( + charon->ike_sa_manager, mediated_sa); + } + destroy(this); + return; + } + /* we need an additional reference because initiate consumes one */ + mediation_cfg->get_ref(mediation_cfg); + + if (charon->controller->initiate(charon->controller, mediation_cfg, + NULL, (controller_cb_t)initiate_callback, this) != SUCCESS) + { + mediation_cfg->destroy(mediation_cfg); + mediated_cfg->destroy(mediated_cfg); + mediated_sa = charon->ike_sa_manager->checkout( + charon->ike_sa_manager, this->mediated_sa_id); + if (mediated_sa) + { + DBG1(DBG_IKE, "initiating mediation connection failed"); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, mediated_sa); + } + destroy(this); + return; + } + mediation_cfg->destroy(mediation_cfg); + + mediation_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->mediation_sa_id); + if (mediation_sa) + { + if (mediation_sa->initiate_mediation(mediation_sa, + mediated_cfg) != SUCCESS) + { + mediated_cfg->destroy(mediated_cfg); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, mediation_sa); + mediated_sa = charon->ike_sa_manager->checkout( + charon->ike_sa_manager, this->mediated_sa_id); + if (mediated_sa) + { + DBG1(DBG_IKE, "establishing mediation connection failed"); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, mediated_sa); + } + destroy(this); + return; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, + mediation_sa); + } + mediated_cfg->destroy(mediated_cfg); + } + destroy(this); +} + +/** + * Implementation of job_t.execute. + */ +static void reinitiate(private_initiate_mediation_job_t *this) +{ + ike_sa_t *mediated_sa, *mediation_sa; + peer_cfg_t *mediated_cfg; + + mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->mediated_sa_id); + if (mediated_sa) + { + mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa); + mediated_cfg->get_ref(mediated_cfg); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa); + + mediation_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->mediation_sa_id); + if (mediation_sa) + { + if (mediation_sa->initiate_mediation(mediation_sa, + mediated_cfg) != SUCCESS) + { + DBG1(DBG_JOB, "initiating mediated connection '%s' failed", + mediated_cfg->get_name(mediated_cfg)); + mediated_cfg->destroy(mediated_cfg); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, + mediation_sa); + mediated_sa = charon->ike_sa_manager->checkout( + charon->ike_sa_manager, + this->mediated_sa_id); + if (mediated_sa) + { + DBG1(DBG_IKE, "establishing mediation connection failed"); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, + mediated_sa); + } + destroy(this); + return; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, + mediation_sa); + } + + mediated_cfg->destroy(mediated_cfg); + } + destroy(this); +} + +/** + * Creates an empty job + */ +static private_initiate_mediation_job_t *initiate_mediation_job_create_empty() +{ + private_initiate_mediation_job_t *this = malloc_thing(private_initiate_mediation_job_t); + + /* interface functions */ + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + /* private variables */ + this->mediation_sa_id = NULL; + this->mediated_sa_id = NULL; + + return this; +} + +/* + * Described in header + */ +initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id) +{ + private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty(); + + this->public.job_interface.execute = (void (*) (job_t *)) initiate; + + this->mediated_sa_id = ike_sa_id->clone(ike_sa_id); + + return &this->public; +} + +/* + * Described in header + */ +initiate_mediation_job_t *reinitiate_mediation_job_create(ike_sa_id_t *mediation_sa_id, + ike_sa_id_t *mediated_sa_id) +{ + private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty(); + + this->public.job_interface.execute = (void (*) (job_t *)) reinitiate; + + this->mediation_sa_id = mediation_sa_id->clone(mediation_sa_id); + this->mediated_sa_id = mediated_sa_id->clone(mediated_sa_id); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.h b/src/libcharon/processing/jobs/initiate_mediation_job.h new file mode 100644 index 000000000..fddb1dd7b --- /dev/null +++ b/src/libcharon/processing/jobs/initiate_mediation_job.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2008 Tobias Brunner + * 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. + */ + +/** + * @defgroup initiate_mediation_job initiate_mediation_job + * @{ @ingroup jobs + */ + +#ifndef INITIATE_MEDIATION_JOB_H_ +#define INITIATE_MEDIATION_JOB_H_ + +typedef struct initiate_mediation_job_t initiate_mediation_job_t; + +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +/** + * Class representing a INITIATE_MEDIATION Job. + * + * This job will initiate a mediation on behalf of a mediated connection. + * If required the mediation connection is established. + */ +struct initiate_mediation_job_t { + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a job of type INITIATE_MEDIATION. + * + * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) + * @return job object + */ +initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id); + +/** + * Creates a special job of type INITIATE_MEDIATION that reinitiates a + * specific connection. + * + * @param mediation_sa_id identification of the mediation sa (gets cloned) + * @param mediated_sa_id identification of the mediated sa (gets cloned) + * @return job object + */ +initiate_mediation_job_t *reinitiate_mediation_job_create( + ike_sa_id_t *mediation_sa_id, + ike_sa_id_t *mediated_sa_id); + +#endif /** INITIATE_MEDIATION_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/job.h b/src/libcharon/processing/jobs/job.h new file mode 100644 index 000000000..0f1c16ebe --- /dev/null +++ b/src/libcharon/processing/jobs/job.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/** + * @defgroup job job + * @{ @ingroup jobs + */ + +#ifndef JOB_H_ +#define JOB_H_ + +typedef struct job_t job_t; + +#include <library.h> + +/** + * Job-Interface as it is stored in the job queue. + */ +struct job_t { + + /** + * Execute a job. + * + * The processing facility executes a job using this method. Jobs are + * one-shot, they destroy themself after execution, so don't use a job + * once it has been executed. + */ + void (*execute) (job_t *this); + + /** + * Destroy a job. + * + * Is only called whenever a job was not executed (e.g. due daemon shutdown). + * After execution, jobs destroy themself. + */ + void (*destroy) (job_t *job); +}; + +#endif /** JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/mediation_job.c b/src/libcharon/processing/jobs/mediation_job.c new file mode 100644 index 000000000..b5b8af3b3 --- /dev/null +++ b/src/libcharon/processing/jobs/mediation_job.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2007 Tobias Brunner + * 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 "mediation_job.h" + +#include <encoding/payloads/endpoint_notify.h> +#include <daemon.h> + + +typedef struct private_mediation_job_t private_mediation_job_t; + +/** + * Private data of an mediation_job_t Object + */ +struct private_mediation_job_t { + /** + * public mediation_job_t interface + */ + mediation_job_t public; + + /** + * ID of target peer. + */ + identification_t *target; + + /** + * ID of the source peer. + */ + identification_t *source; + + /** + * ME_CONNECTID + */ + chunk_t connect_id; + + /** + * ME_CONNECTKEY + */ + chunk_t connect_key; + + /** + * Submitted endpoints + */ + linked_list_t *endpoints; + + /** + * Is this a callback job? + */ + bool callback; + + /** + * Is this a response? + */ + bool response; +}; + +/** + * Implements job_t.destroy. + */ +static void destroy(private_mediation_job_t *this) +{ + DESTROY_IF(this->target); + DESTROY_IF(this->source); + chunk_free(&this->connect_id); + chunk_free(&this->connect_key); + DESTROY_OFFSET_IF(this->endpoints, offsetof(endpoint_notify_t, destroy)); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_mediation_job_t *this) +{ + ike_sa_id_t *target_sa_id; + + target_sa_id = charon->mediation_manager->check(charon->mediation_manager, this->target); + + if (target_sa_id) + { + ike_sa_t *target_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + target_sa_id); + if (target_sa) + { + if (this->callback) + { + /* send callback to a peer */ + if (target_sa->callback(target_sa, this->source) != SUCCESS) + { + DBG1(DBG_JOB, "callback for '%Y' to '%Y' failed", + this->source, this->target); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa); + destroy(this); + return; + } + } + else + { + /* normal mediation between two peers */ + if (target_sa->relay(target_sa, this->source, this->connect_id, + this->connect_key, this->endpoints, this->response) != SUCCESS) + { + DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed", + this->source, this->target); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa); + /* FIXME: notify the initiator */ + destroy(this); + return; + } + } + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa); + } + else + { + DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: " + "SA not found", this->source, this->target); + } + } + else + { + DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: " + "peer is not online anymore", this->source, this->target); + } + destroy(this); +} + +/** + * Creates an empty mediation job + */ +static private_mediation_job_t *mediation_job_create_empty() +{ + private_mediation_job_t *this = malloc_thing(private_mediation_job_t); + + /* interface functions */ + this->public.job_interface.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + /* private variables */ + this->target = NULL; + this->source = NULL; + this->callback = FALSE; + this->connect_id = chunk_empty; + this->connect_key = chunk_empty; + this->endpoints = NULL; + this->response = FALSE; + + return this; +} + +/* + * Described in header + */ +mediation_job_t *mediation_job_create(identification_t *peer_id, + identification_t *requester, chunk_t connect_id, chunk_t connect_key, + linked_list_t *endpoints, bool response) +{ + private_mediation_job_t *this = mediation_job_create_empty(); + + this->target = peer_id->clone(peer_id); + this->source = requester->clone(requester); + this->connect_id = chunk_clone(connect_id); + this->connect_key = chunk_clone(connect_key); + this->endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone)); + this->response = response; + + return &this->public; +} + +/* + * Described in header + */ +mediation_job_t *mediation_callback_job_create(identification_t *requester, + identification_t *peer_id) +{ + private_mediation_job_t *this = mediation_job_create_empty(); + + this->target = requester->clone(requester); + this->source = peer_id->clone(peer_id); + this->callback = TRUE; + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/mediation_job.h b/src/libcharon/processing/jobs/mediation_job.h new file mode 100644 index 000000000..0574c65eb --- /dev/null +++ b/src/libcharon/processing/jobs/mediation_job.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007 Tobias Brunner + * 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. + */ + +/** + * @defgroup mediation_job mediation_job + * @{ @ingroup jobs + */ + +#ifndef MEDIATION_JOB_H_ +#define MEDIATION_JOB_H_ + +typedef struct mediation_job_t mediation_job_t; + +#include <library.h> +#include <processing/jobs/job.h> +#include <utils/identification.h> +#include <utils/linked_list.h> + +/** + * Class representing a MEDIATION Job. + * + * This job handles the mediation on the mediation server. + */ +struct mediation_job_t { + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a job of type MEDIATION. + * + * Parameters get cloned. + * + * @param peer_id ID of the requested peer + * @param requester ID of the requesting peer + * @param connect_id content of ME_CONNECTID (could be NULL) + * @param connect_key content of ME_CONNECTKEY + * @param endpoints list of submitted endpoints + * @param response TRUE if this is a response + * @return job object + */ +mediation_job_t *mediation_job_create(identification_t *peer_id, + identification_t *requester, chunk_t connect_id, chunk_t connect_key, + linked_list_t *endpoints, bool response); + + +/** + * Creates a special job of type MEDIATION that is used to send a callback + * notification to a peer. + * + * Parameters get cloned. + * + * @param requester ID of the waiting peer + * @param peer_id ID of the requested peer + * @return job object + */ +mediation_job_t *mediation_callback_job_create(identification_t *requester, + identification_t *peer_id); + +#endif /** MEDIATION_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c new file mode 100644 index 000000000..05f47340c --- /dev/null +++ b/src/libcharon/processing/jobs/migrate_job.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2008 Andreas Steffen + * 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 "migrate_job.h" + +#include <daemon.h> + +#include <config/child_cfg.h> + + +typedef struct private_migrate_job_t private_migrate_job_t; + +/** + * Private data of a migrate_job_t object. + */ +struct private_migrate_job_t { + /** + * Public migrate_job_t interface. + */ + migrate_job_t public; + + /** + * reqid of the CHILD_SA if it already exists + */ + u_int32_t reqid; + + /** + * source traffic selector + */ + traffic_selector_t *src_ts; + + /** + * destination traffic selector + */ + traffic_selector_t *dst_ts; + + /** + * local host address to be used for IKE + */ + host_t *local; + + /** + * remote host address to be used for IKE + */ + host_t *remote; +}; + +/** + * Implementation of job_t.destroy. + */ +static void destroy(private_migrate_job_t *this) +{ + DESTROY_IF(this->src_ts); + DESTROY_IF(this->dst_ts); + DESTROY_IF(this->local); + DESTROY_IF(this->remote); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_migrate_job_t *this) +{ + ike_sa_t *ike_sa = NULL; + + if (this->reqid) + { + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + this->reqid, TRUE); + } + if (ike_sa) + { + iterator_t *children; + child_sa_t *child_sa; + host_t *host; + + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if (child_sa->get_reqid(child_sa) == this->reqid) + { + break; + } + } + children->destroy(children); + DBG2(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid); + + ike_sa->set_kmaddress(ike_sa, this->local, this->remote); + + host = this->local->clone(this->local); + host->set_port(host, IKEV2_UDP_PORT); + ike_sa->set_my_host(ike_sa, host); + + host = this->remote->clone(this->remote); + host->set_port(host, IKEV2_UDP_PORT); + ike_sa->set_other_host(ike_sa, host); + + if (child_sa->update(child_sa, this->local, this->remote, + ike_sa->get_virtual_ip(ike_sa, TRUE), + ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED) + { + ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { + DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid); + } + destroy(this); +} + +/* + * Described in header + */ +migrate_job_t *migrate_job_create(u_int32_t reqid, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t dir, + host_t *local, host_t *remote) +{ + private_migrate_job_t *this = malloc_thing(private_migrate_job_t); + + /* interface functions */ + this->public.job_interface.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + + /* private variables */ + this->reqid = reqid; + this->src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts; + this->dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts; + this->local = local; + this->remote = remote; + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/migrate_job.h b/src/libcharon/processing/jobs/migrate_job.h new file mode 100644 index 000000000..de313d517 --- /dev/null +++ b/src/libcharon/processing/jobs/migrate_job.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 Andreas Steffen + * 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. + */ + +/** + * @defgroup migrate_job migrate_job + * @{ @ingroup jobs + */ + +#ifndef MIGRATE_JOB_H_ +#define MIGRATE_JOB_H_ + +typedef struct migrate_job_t migrate_job_t; + +#include <library.h> +#include <utils/host.h> +#include <selectors/traffic_selector.h> +#include <kernel/kernel_ipsec.h> +#include <processing/jobs/job.h> + +/** + * Class representing a MIGRATE Job. + * + * This job sets a routed CHILD_SA for an existing IPsec policy. + */ +struct migrate_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * Creates a job of type MIGRATE. + * + * We use the reqid or the traffic selectors to find a matching CHILD_SA. + * + * @param reqid reqid of the CHILD_SA to acquire + * @param src_ts source traffic selector to be used in the policy + * @param dst_ts destination traffic selector to be used in the policy + * @param dir direction of the policy (in|out) + * @param local local host address to be used in the IKE_SA + * @param remote remote host address to be used in the IKE_SA + * @return migrate_job_t object + */ +migrate_job_t *migrate_job_create(u_int32_t reqid, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t dir, host_t *local, host_t *remote); + +#endif /** MIGRATE_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c new file mode 100644 index 000000000..a47d48e38 --- /dev/null +++ b/src/libcharon/processing/jobs/process_message_job.c @@ -0,0 +1,106 @@ +/* + * 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.destroy. + */ +static void destroy(private_process_message_job_t *this) +{ + this->message->destroy(this->message); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_process_message_job_t *this) +{ + ike_sa_t *ike_sa; + +#ifdef ME + /* if this is an unencrypted INFORMATIONAL exchange it is likely a + * connectivity check. */ + if (this->message->get_exchange_type(this->message) == INFORMATIONAL && + this->message->get_first_payload_type(this->message) != ENCRYPTED) + { + /* theoretically this could also be an error message + * see RFC 4306, section 1.5. */ + DBG1(DBG_NET, "received unencrypted informational: from %#H to %#H", + this->message->get_source(this->message), + this->message->get_destination(this->message)); + charon->connect_manager->process_check(charon->connect_manager, this->message); + destroy(this); + return; + } +#endif /* ME */ + + 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); + } + } + destroy(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.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void(*)(job_t*))destroy; + + /* private variables */ + this->message = message; + + return &(this->public); +} diff --git a/src/libcharon/processing/jobs/process_message_job.h b/src/libcharon/processing/jobs/process_message_job.h new file mode 100644 index 000000000..5e3f44d1f --- /dev/null +++ b/src/libcharon/processing/jobs/process_message_job.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +/** + * @defgroup process_message_job process_message_job + * @{ @ingroup jobs + */ + +#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> + +/** + * Class representing an PROCESS_MESSAGE job. + */ +struct process_message_job_t { + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a job of type PROCESS_MESSAGE. + * + * @param message message to process + * @return created process_message_job_t object + */ +process_message_job_t *process_message_job_create(message_t *message); + +#endif /** PROCESS_MESSAGE_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c new file mode 100644 index 000000000..b797d181e --- /dev/null +++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c @@ -0,0 +1,97 @@ +/* + * 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.destroy. + */ +static void destroy(private_rekey_child_sa_job_t *this) +{ + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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); + } + else + { + ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + destroy(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.execute = (void (*) (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/libcharon/processing/jobs/rekey_child_sa_job.h b/src/libcharon/processing/jobs/rekey_child_sa_job.h new file mode 100644 index 000000000..62887d6b9 --- /dev/null +++ b/src/libcharon/processing/jobs/rekey_child_sa_job.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +/** + * @defgroup rekey_child_sa_job rekey_child_sa_job + * @{ @ingroup jobs + */ + +#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> + +/** + * Class representing an REKEY_CHILD_SA Job. + * + * This job initiates the rekeying of a CHILD SA. + */ +struct rekey_child_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * 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 + */ +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/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c new file mode 100644 index 000000000..5ec0b1b88 --- /dev/null +++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c @@ -0,0 +1,104 @@ +/* + * 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.destroy. + */ +static void destroy(private_rekey_ike_sa_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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"); + } + else + { + if (this->reauth) + { + status = ike_sa->reauth(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); + } + } + destroy(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.execute = (void (*) (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/libcharon/processing/jobs/rekey_ike_sa_job.h b/src/libcharon/processing/jobs/rekey_ike_sa_job.h new file mode 100644 index 000000000..a5c1028aa --- /dev/null +++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/** + * @defgroup rekey_ike_sa_job rekey_ike_sa_job + * @{ @ingroup jobs + */ + +#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> + +/** + * Class representing an REKEY_IKE_SA Job. + * + * This job initiates the rekeying of an IKE_SA. + */ +struct rekey_ike_sa_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * 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 + */ +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/libcharon/processing/jobs/retransmit_job.c b/src/libcharon/processing/jobs/retransmit_job.c new file mode 100644 index 000000000..fc787f208 --- /dev/null +++ b/src/libcharon/processing/jobs/retransmit_job.c @@ -0,0 +1,93 @@ +/* + * 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.destroy. + */ +static void destroy(private_retransmit_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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); + } + } + destroy(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.execute = (void (*) (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/libcharon/processing/jobs/retransmit_job.h b/src/libcharon/processing/jobs/retransmit_job.h new file mode 100644 index 000000000..c8c13479b --- /dev/null +++ b/src/libcharon/processing/jobs/retransmit_job.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +/** + * @defgroup retransmit_job retransmit_job + * @{ @ingroup jobs + */ + +#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> + +/** + * 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. + */ +struct retransmit_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * 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 + */ +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/libcharon/processing/jobs/roam_job.c b/src/libcharon/processing/jobs/roam_job.c new file mode 100644 index 000000000..adc884a8a --- /dev/null +++ b/src/libcharon/processing/jobs/roam_job.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2007 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 <stdlib.h> + +#include "roam_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +typedef struct private_roam_job_t private_roam_job_t; + +/** + * Private data of an roam_job_t Object + */ +struct private_roam_job_t { + /** + * public roam_job_t interface + */ + roam_job_t public; + + /** + * has the address list changed, or the routing only? + */ + bool address; +}; + +/** + * Implements job_t.destroy. + */ +static void destroy(private_roam_job_t *this) +{ + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_roam_job_t *this) +{ + ike_sa_t *ike_sa; + linked_list_t *list; + ike_sa_id_t *id; + enumerator_t *enumerator; + + /* enumerator over all IKE_SAs gives us no way to checkin_and_destroy + * after a DESTROY_ME, so we check out each available IKE_SA by hand. */ + list = linked_list_create(); + enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + id = ike_sa->get_id(ike_sa); + list->insert_last(list, id->clone(id)); + } + enumerator->destroy(enumerator); + + while (list->remove_last(list, (void**)&id) == SUCCESS) + { + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + if (ike_sa) + { + if (ike_sa->roam(ike_sa, this->address) == 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); + } + } + id->destroy(id); + } + list->destroy(list); + + destroy(this); +} + +/* + * Described in header + */ +roam_job_t *roam_job_create(bool address) +{ + private_roam_job_t *this = malloc_thing(private_roam_job_t); + + this->public.job_interface.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + this->address = address; + + return &this->public; +} + diff --git a/src/libcharon/processing/jobs/roam_job.h b/src/libcharon/processing/jobs/roam_job.h new file mode 100644 index 000000000..55bdf2b28 --- /dev/null +++ b/src/libcharon/processing/jobs/roam_job.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007 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. + */ + +/** + * @defgroup roam_job roam_job + * @{ @ingroup jobs + */ + +#ifndef ROAM_JOB_H_ +#define ROAM_JOB_H_ + +typedef struct roam_job_t roam_job_t; + +#include <library.h> +#include <sa/ike_sa_id.h> +#include <processing/jobs/job.h> + +/** + * A job to inform IKE_SAs about changed local address setup. + * + * If a local address appears or disappears, the kernel fires this job to + * update all IKE_SAs. + */ +struct roam_job_t { + + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a job to inform IKE_SAs about an updated address list. + * + * @param address TRUE if address list changed, FALSE if routing changed + * @return initiate_ike_sa_job_t object + */ +roam_job_t *roam_job_create(bool address); + +#endif /** ROAM_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/send_dpd_job.c b/src/libcharon/processing/jobs/send_dpd_job.c new file mode 100644 index 000000000..1c2da52b8 --- /dev/null +++ b/src/libcharon/processing/jobs/send_dpd_job.c @@ -0,0 +1,88 @@ +/* + * 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 job_t.destroy. + */ +static void destroy(private_send_dpd_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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) + { + 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); + } + } + destroy(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.execute = (void (*) (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); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/send_dpd_job.h b/src/libcharon/processing/jobs/send_dpd_job.h new file mode 100644 index 000000000..8078a38bc --- /dev/null +++ b/src/libcharon/processing/jobs/send_dpd_job.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/** + * @defgroup send_dpd_job send_dpd_job + * @{ @ingroup jobs + */ + +#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> + +/** + * 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. + */ +struct send_dpd_job_t { + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * 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 + */ +send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id); + +#endif /** SEND_DPD_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c new file mode 100644 index 000000000..3d02cea2e --- /dev/null +++ b/src/libcharon/processing/jobs/send_keepalive_job.c @@ -0,0 +1,82 @@ +/* + * 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 job_t.destroy. + */ +static void destroy(private_send_keepalive_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void 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) + { + ike_sa->send_keepalive(ike_sa); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + destroy(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.execute = (void (*) (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); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/send_keepalive_job.h b/src/libcharon/processing/jobs/send_keepalive_job.h new file mode 100644 index 000000000..cda83cd7e --- /dev/null +++ b/src/libcharon/processing/jobs/send_keepalive_job.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/** + * @defgroup send_keepalive_job send_keepalive_job + * @{ @ingroup jobs + */ + +#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> + +/** + * 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. + */ +struct send_keepalive_job_t { + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * 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 + */ +send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id); + +#endif /** SEND_KEEPALIVE_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c new file mode 100644 index 000000000..17dce2548 --- /dev/null +++ b/src/libcharon/processing/jobs/update_sa_job.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 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 <stdlib.h> + +#include "update_sa_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +typedef struct private_update_sa_job_t private_update_sa_job_t; + +/** + * Private data of an update_sa_job_t Object + */ +struct private_update_sa_job_t { + /** + * public update_sa_job_t interface + */ + update_sa_job_t public; + + /** + * reqid of the CHILD_SA + */ + u_int32_t reqid; + + /** + * New SA address and port + */ + host_t *new; +}; + +/** + * Implements job_t.destroy. + */ +static void destroy(private_update_sa_job_t *this) +{ + this->new->destroy(this->new); + free(this); +} + +/** + * Implementation of job_t.execute. + */ +static void execute(private_update_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 update", this->reqid); + } + else + { + /* we update only if other host is NATed, but not our */ + if (ike_sa->has_condition(ike_sa, COND_NAT_THERE) && + !ike_sa->has_condition(ike_sa, COND_NAT_HERE)) + { + ike_sa->update_hosts(ike_sa, NULL, this->new); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + destroy(this); +} + +/* + * Described in header + */ +update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new) +{ + private_update_sa_job_t *this = malloc_thing(private_update_sa_job_t); + + this->public.job_interface.execute = (void (*) (job_t *)) execute; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + + this->reqid = reqid; + this->new = new; + + return &this->public; +} + diff --git a/src/libcharon/processing/jobs/update_sa_job.h b/src/libcharon/processing/jobs/update_sa_job.h new file mode 100644 index 000000000..11d1ac9b6 --- /dev/null +++ b/src/libcharon/processing/jobs/update_sa_job.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 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. + */ + +/** + * @defgroup update_sa_job update_sa_job + * @{ @ingroup jobs + */ + +#ifndef UPDATE_SA_JOB_H_ +#define UPDATE_SA_JOB_H_ + +typedef struct update_sa_job_t update_sa_job_t; + +#include <library.h> +#include <utils/host.h> +#include <processing/jobs/job.h> + +/** + * Update the addresses of an IKE and its CHILD_SAs. + */ +struct update_sa_job_t { + + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a job to update IKE and CHILD_SA addresses. + * + * @param reqid reqid of the CHILD_SA + * @param new new address and port + * @return update_sa_job_t object + */ +update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new); + +#endif /** UPDATE_SA_JOB_H_ @}*/ |