diff options
-rw-r--r-- | src/libipsec/Android.mk | 2 | ||||
-rw-r--r-- | src/libipsec/Makefile.am | 2 | ||||
-rw-r--r-- | src/libipsec/ipsec.c | 2 | ||||
-rw-r--r-- | src/libipsec/ipsec.h | 6 | ||||
-rw-r--r-- | src/libipsec/ipsec_event_listener.h | 48 | ||||
-rw-r--r-- | src/libipsec/ipsec_event_relay.c | 193 | ||||
-rw-r--r-- | src/libipsec/ipsec_event_relay.h | 79 |
7 files changed, 332 insertions, 0 deletions
diff --git a/src/libipsec/Android.mk b/src/libipsec/Android.mk index a5d93dfc3..024810997 100644 --- a/src/libipsec/Android.mk +++ b/src/libipsec/Android.mk @@ -6,6 +6,8 @@ LOCAL_SRC_FILES := \ ipsec.c ipsec.h \ esp_context.c esp_context.h \ esp_packet.c esp_packet.h \ +ipsec_event_listener.h \ +ipsec_event_relay.c ipsec_event_relay.h \ ipsec_sa.c ipsec_sa.h \ ipsec_sa_mgr.c ipsec_sa_mgr.h diff --git a/src/libipsec/Makefile.am b/src/libipsec/Makefile.am index 3de8f82bc..c1024930d 100644 --- a/src/libipsec/Makefile.am +++ b/src/libipsec/Makefile.am @@ -4,6 +4,8 @@ libipsec_la_SOURCES = \ ipsec.c ipsec.h \ esp_context.c esp_context.h \ esp_packet.c esp_packet.h \ +ipsec_event_listener.h \ +ipsec_event_relay.c ipsec_event_relay.h \ ipsec_sa.c ipsec_sa.h \ ipsec_sa_mgr.c ipsec_sa_mgr.h diff --git a/src/libipsec/ipsec.c b/src/libipsec/ipsec.c index 5ae6c74aa..49773abc9 100644 --- a/src/libipsec/ipsec.c +++ b/src/libipsec/ipsec.c @@ -43,6 +43,7 @@ ipsec_t *ipsec; void libipsec_deinit() { private_ipsec_t *this = (private_ipsec_t*)ipsec; + DESTROY_IF(this->public.events); DESTROY_IF(this->public.sas); free(this); ipsec = NULL; @@ -66,6 +67,7 @@ bool libipsec_init() } this->public.sas = ipsec_sa_mgr_create(); + this->public.events = ipsec_event_relay_create(); return TRUE; } diff --git a/src/libipsec/ipsec.h b/src/libipsec/ipsec.h index e4055a8bd..304738170 100644 --- a/src/libipsec/ipsec.h +++ b/src/libipsec/ipsec.h @@ -26,6 +26,7 @@ #define IPSEC_H_ #include "ipsec_sa_mgr.h" +#include "ipsec_event_relay.h" #include <library.h> @@ -41,6 +42,11 @@ struct ipsec_t { */ ipsec_sa_mgr_t *sas; + /** + * Event relay instance + */ + ipsec_event_relay_t *events; + }; /** diff --git a/src/libipsec/ipsec_event_listener.h b/src/libipsec/ipsec_event_listener.h new file mode 100644 index 000000000..c5c39b0f1 --- /dev/null +++ b/src/libipsec/ipsec_event_listener.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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 ipsec_event_listener ipsec_event_listener + * @{ @ingroup libipsec + */ + +#ifndef IPSEC_EVENT_LISTENER_H_ +#define IPSEC_EVENT_LISTENER_H_ + +typedef struct ipsec_event_listener_t ipsec_event_listener_t; + +#include <library.h> + +/** + * Listener interface for IPsec events + * + * All methods are optional. + */ +struct ipsec_event_listener_t { + + /** + * Called when the lifetime of an IPsec SA expired + * + * @param reqid reqid of the expired SA + * @param protocol protocol of the expired SA + * @param spi spi of the expired SA + * @param hard TRUE if this is a hard expire, FALSE otherwise + */ + void (*expire)(u_int32_t reqid, u_int8_t protocol, u_int32_t spi, + bool hard); + +}; + +#endif /** IPSEC_EVENT_LISTENER_H_ @}*/ diff --git a/src/libipsec/ipsec_event_relay.c b/src/libipsec/ipsec_event_relay.c new file mode 100644 index 000000000..34222258c --- /dev/null +++ b/src/libipsec/ipsec_event_relay.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012 Giuliano Grassi + * Copyright (C) 2012 Ralf Sager + * 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 "ipsec_event_relay.h" + +#include <library.h> +#include <debug.h> +#include <threading/rwlock.h> +#include <utils/linked_list.h> +#include <utils/blocking_queue.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_ipsec_event_relay_t private_ipsec_event_relay_t; + +/** + * Private additions to ipsec_event_relay_t. + */ +struct private_ipsec_event_relay_t { + + /** + * Public members + */ + ipsec_event_relay_t public; + + /** + * Registered listeners + */ + linked_list_t *listeners; + + /** + * Lock to safely access the list of listeners + */ + rwlock_t *lock; + + /** + * Blocking queue for events + */ + blocking_queue_t *queue; +}; + +/** + * Helper struct used to manage events in a queue + */ +typedef struct { + + /** + * Type of the event + */ + enum { + IPSEC_EVENT_EXPIRE, + } type; + + /** + * Reqid of the SA, if any + */ + u_int32_t reqid; + + /** + * SPI of the SA, if any + */ + u_int32_t spi; + + /** + * Additional data for specific event types + */ + union { + + struct { + /** Protocol of the SA */ + u_int8_t protocol; + /** TRUE in case of a hard expire */ + bool hard; + } expire; + + } data; + +} ipsec_event_t; + +/** + * Dequeue events and relay them to listeners + */ +static job_requeue_t handle_events(private_ipsec_event_relay_t *this) +{ + enumerator_t *enumerator; + ipsec_event_listener_t *current; + ipsec_event_t *event; + + event = this->queue->dequeue(this->queue); + + this->lock->read_lock(this->lock); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, (void**)¤t)) + { + switch (event->type) + { + case IPSEC_EVENT_EXPIRE: + if (current->expire) + { + current->expire(event->reqid, event->data.expire.protocol, + event->spi, event->data.expire.hard); + } + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + return JOB_REQUEUE_DIRECT; +} + +METHOD(ipsec_event_relay_t, expire, void, + private_ipsec_event_relay_t *this, u_int32_t reqid, u_int8_t protocol, + u_int32_t spi, bool hard) +{ + ipsec_event_t *event; + + INIT(event, + .type = IPSEC_EVENT_EXPIRE, + .reqid = reqid, + .spi = spi, + .data = { + .expire = { + .protocol = protocol, + .hard = hard, + }, + }, + ); + this->queue->enqueue(this->queue, event); +} + +METHOD(ipsec_event_relay_t, register_listener, void, + private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener) +{ + this->lock->write_lock(this->lock); + this->listeners->insert_last(this->listeners, listener); + this->lock->unlock(this->lock); +} + +METHOD(ipsec_event_relay_t, unregister_listener, void, + private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener) +{ + this->lock->write_lock(this->lock); + this->listeners->remove(this->listeners, listener, NULL); + this->lock->unlock(this->lock); +} + +METHOD(ipsec_event_relay_t, destroy, void, + private_ipsec_event_relay_t *this) +{ + this->queue->destroy_function(this->queue, free); + this->listeners->destroy(this->listeners); + this->lock->destroy(this->lock); + free(this); +} + +/** + * Described in header. + */ +ipsec_event_relay_t *ipsec_event_relay_create() +{ + private_ipsec_event_relay_t *this; + + INIT(this, + .public = { + .expire = _expire, + .register_listener = _register_listener, + .unregister_listener = _unregister_listener, + .destroy = _destroy, + }, + .listeners = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .queue = blocking_queue_create(), + ); + + lib->processor->queue_job(lib->processor, + (job_t*)callback_job_create((callback_job_cb_t)handle_events, this, + NULL, (callback_job_cancel_t)return_false)); + + return &this->public; +} diff --git a/src/libipsec/ipsec_event_relay.h b/src/libipsec/ipsec_event_relay.h new file mode 100644 index 000000000..c6935d546 --- /dev/null +++ b/src/libipsec/ipsec_event_relay.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Giuliano Grassi + * Copyright (C) 2012 Ralf Sager + * 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 ipsec_event_relay ipsec_event_relay + * @{ @ingroup libipsec + */ + +#ifndef IPSEC_EVENT_RELAY_H_ +#define IPSEC_EVENT_RELAY_H_ + +#include "ipsec_event_listener.h" + +#include <library.h> + +typedef struct ipsec_event_relay_t ipsec_event_relay_t; + +/** + * Event relay manager. + * + * Used to notify upper layers about changes + */ +struct ipsec_event_relay_t { + + /** + * Raise an expire event. + * + * @param reqid reqid of the expired IPsec SA + * @param protocol protocol (e.g ESP) of the expired SA + * @param spi SPI of the expired SA + * @param hard TRUE for a hard expire, FALSE otherwise + */ + void (*expire)(ipsec_event_relay_t *this, u_int32_t reqid, + u_int8_t protocol, u_int32_t spi, bool hard); + + /** + * Register a listener to events raised by this manager + * + * @param listener the listener to register + */ + void (*register_listener)(ipsec_event_relay_t *this, + ipsec_event_listener_t *listener); + + /** + * Unregister a listener + * + * @param listener the listener to unregister + */ + void (*unregister_listener)(ipsec_event_relay_t *this, + ipsec_event_listener_t *listener); + + /** + * Destroy an ipsec_event_relay_t + */ + void (*destroy)(ipsec_event_relay_t *this); + +}; + +/** + * Create an ipsec_event_relay_t instance + * + * @return IPsec event relay instance + */ +ipsec_event_relay_t *ipsec_event_relay_create(); + +#endif /** IPSEC_EVENT_RELAY_H_ @}*/ |