diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-12-05 16:44:41 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-12-05 16:44:41 +0000 |
commit | 2db1ef4ac8928944958712923b9c89c263a337d2 (patch) | |
tree | 700043d9d97b7e7ba344b448918728af0a8be8d1 /src/charon/bus/bus.c | |
parent | 5dc75410286b0e3a16845b44dd696ba0f40df573 (diff) | |
download | vyos-strongswan-2db1ef4ac8928944958712923b9c89c263a337d2.tar.gz vyos-strongswan-2db1ef4ac8928944958712923b9c89c263a337d2.zip |
- Updated to new upstream.
Diffstat (limited to 'src/charon/bus/bus.c')
-rw-r--r-- | src/charon/bus/bus.c | 335 |
1 files changed, 255 insertions, 80 deletions
diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c index a102a3984..504947465 100644 --- a/src/charon/bus/bus.c +++ b/src/charon/bus/bus.c @@ -12,20 +12,18 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: bus.c 4198 2008-07-21 14:23:43Z martin $ + * $Id: bus.c 4622 2008-11-11 10:52:37Z martin $ */ #include "bus.h" #include <pthread.h> +#include <stdint.h> #include <daemon.h> #include <utils/mutex.h> -ENUM(signal_names, SIG_ANY, SIG_MAX, - /** should not get printed */ - "SIG_ANY", - /** debugging message types */ +ENUM(debug_names, DBG_DMN, DBG_LIB, "DMN", "MGR", "IKE", @@ -36,19 +34,19 @@ ENUM(signal_names, SIG_ANY, SIG_MAX, "NET", "ENC", "LIB", - /** should not get printed */ - "SIG_DBG_MAX", - /** all level0 signals are AUDIT signals */ - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - "AUD", "AUD", "AUD", - /** should not get printed */ - "SIG_MAX", +); + +ENUM(debug_lower_names, DBG_DMN, DBG_LIB, + "dmn", + "mgr", + "ike", + "chd", + "job", + "cfg", + "knl", + "net", + "enc", + "lib", ); typedef struct private_bus_t private_bus_t; @@ -93,7 +91,7 @@ struct entry_t { /** * registered listener interface */ - bus_listener_t *listener; + listener_t *listener; /** * is this a active listen() call with a blocking thread @@ -103,7 +101,7 @@ struct entry_t { /** * are we currently calling this listener */ - bool calling; + int calling; /** * condvar where active listeners wait @@ -114,13 +112,13 @@ struct entry_t { /** * create a listener entry */ -static entry_t *entry_create(bus_listener_t *listener, bool blocker) +static entry_t *entry_create(listener_t *listener, bool blocker) { entry_t *this = malloc_thing(entry_t); this->listener = listener; this->blocker = blocker; - this->calling = FALSE; + this->calling = 0; this->condvar = condvar_create(CONDVAR_DEFAULT); return this; @@ -140,12 +138,12 @@ static void entry_destroy(entry_t *entry) * pthread_self returns large and ugly numbers, use this function * for logging; these numbers are incremental starting at 1 */ -static int get_thread_number(private_bus_t *this) +static u_int get_thread_number(private_bus_t *this) { - static long current_num = 0; - long stored_num; + static uintptr_t current_num = 0; + uintptr_t stored_num; - stored_num = (long)pthread_getspecific(this->thread_id); + stored_num = (uintptr_t)pthread_getspecific(this->thread_id); if (stored_num == 0) { /* first call of current thread */ pthread_setspecific(this->thread_id, (void*)++current_num); @@ -160,7 +158,7 @@ static int get_thread_number(private_bus_t *this) /** * Implementation of bus_t.add_listener. */ -static void add_listener(private_bus_t *this, bus_listener_t *listener) +static void add_listener(private_bus_t *this, listener_t *listener) { this->mutex->lock(this->mutex); this->listeners->insert_last(this->listeners, entry_create(listener, FALSE)); @@ -170,23 +168,23 @@ static void add_listener(private_bus_t *this, bus_listener_t *listener) /** * Implementation of bus_t.remove_listener. */ -static void remove_listener(private_bus_t *this, bus_listener_t *listener) +static void remove_listener(private_bus_t *this, listener_t *listener) { - iterator_t *iterator; + enumerator_t *enumerator; entry_t *entry; this->mutex->lock(this->mutex); - iterator = this->listeners->create_iterator(this->listeners, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) { if (entry->listener == listener) { - iterator->remove(iterator); + this->listeners->remove_at(this->listeners, enumerator); entry_destroy(entry); break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); this->mutex->unlock(this->mutex); } @@ -207,26 +205,14 @@ struct cleanup_data_t { */ static void listener_cleanup(cleanup_data_t *data) { - iterator_t *iterator; - entry_t *entry; - - iterator = data->this->listeners->create_iterator(data->this->listeners, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) - { - if (entry == data->entry) - { - iterator->remove(iterator); - entry_destroy(entry); - break; - } - } - iterator->destroy(iterator); + data->this->listeners->remove(data->this->listeners, data->entry, NULL); + entry_destroy(data->entry); } /** * Implementation of bus_t.listen. */ -static void listen_(private_bus_t *this, bus_listener_t *listener, job_t *job) +static void listen_(private_bus_t *this, listener_t *listener, job_t *job) { int old; cleanup_data_t data; @@ -267,33 +253,31 @@ typedef struct { ike_sa_t *ike_sa; /** invoking thread */ long thread; - /** signal type */ - signal_t signal; - /** signal level */ + /** debug group */ + debug_t group; + /** debug level */ level_t level; - /** signal specific user data */ - void *user; /** format string */ char *format; /** argument list */ va_list args; -} signal_data_t; +} log_data_t; /** - * listener invocation as a list remove callback + * listener->log() invocation as a list remove callback */ -static bool signal_cb(entry_t *entry, signal_data_t *data) +static bool log_cb(entry_t *entry, log_data_t *data) { va_list args; - if (entry->calling) + if (entry->calling || !entry->listener->log) { /* avoid recursive calls */ return FALSE; } - entry->calling = TRUE; + entry->calling++; va_copy(args, data->args); - if (!entry->listener->signal(entry->listener, data->signal, data->level, - data->thread, data->ike_sa, data->user, data->format, args)) + if (!entry->listener->log(entry->listener, data->group, data->level, + data->thread, data->ike_sa, data->format, args)) { if (entry->blocker) { @@ -305,52 +289,238 @@ static bool signal_cb(entry_t *entry, signal_data_t *data) entry_destroy(entry); } va_end(args); - entry->calling = FALSE; + entry->calling--; return TRUE; } va_end(args); - entry->calling = FALSE; + entry->calling--; return FALSE; } /** - * Implementation of bus_t.vsignal. + * Implementation of bus_t.vlog. */ -static void vsignal(private_bus_t *this, signal_t signal, level_t level, - void *user, char* format, va_list args) +static void vlog(private_bus_t *this, debug_t group, level_t level, + char* format, va_list args) { - signal_data_t data; + log_data_t data; data.ike_sa = pthread_getspecific(this->thread_sa); data.thread = get_thread_number(this); - data.signal = signal; + data.group = group; data.level = level; - data.user = user; data.format = format; va_copy(data.args, args); this->mutex->lock(this->mutex); - /* we use the remove() method to invoke all listeners with small overhead */ - this->listeners->remove(this->listeners, &data, (void*)signal_cb); + /* We use the remove() method to invoke all listeners. This is cheap and + * does not require an allocation for this performance critical function. */ + this->listeners->remove(this->listeners, &data, (void*)log_cb); this->mutex->unlock(this->mutex); va_end(data.args); } /** - * Implementation of bus_t.signal. + * Implementation of bus_t.log. */ -static void signal_(private_bus_t *this, signal_t signal, level_t level, - void* data, char* format, ...) +static void log_(private_bus_t *this, debug_t group, level_t level, + char* format, ...) { va_list args; va_start(args, format); - vsignal(this, signal, level, data, format, args); + vlog(this, group, level, format, args); va_end(args); } /** + * unregister a listener + */ +static void unregister_listener(private_bus_t *this, entry_t *entry, + enumerator_t *enumerator) +{ + if (entry->blocker) + { + entry->blocker = FALSE; + entry->condvar->signal(entry->condvar); + } + else + { + entry_destroy(entry); + } + this->listeners->remove_at(this->listeners, enumerator); +} + +/** + * Implementation of bus_t.ike_state_change + */ +static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa, + ike_sa_state_t state) +{ + enumerator_t *enumerator; + entry_t *entry; + bool keep; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->ike_state_change) + { + continue; + } + entry->calling++; + keep = entry->listener->ike_state_change(entry->listener, ike_sa, state); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of bus_t.child_state_change + */ +static void child_state_change(private_bus_t *this, child_sa_t *child_sa, + child_sa_state_t state) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + entry_t *entry; + bool keep; + + ike_sa = pthread_getspecific(this->thread_sa); + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->child_state_change) + { + continue; + } + entry->calling++; + keep = entry->listener->child_state_change(entry->listener, ike_sa, + child_sa, state); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of bus_t.message + */ +static void message(private_bus_t *this, message_t *message, bool incoming) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + entry_t *entry; + bool keep; + + ike_sa = pthread_getspecific(this->thread_sa); + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->message) + { + continue; + } + entry->calling++; + keep = entry->listener->message(entry->listener, ike_sa, + message, incoming); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of bus_t.ike_keys + */ +static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa, + diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, + ike_sa_t *rekey) +{ + enumerator_t *enumerator; + entry_t *entry; + bool keep; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->ike_keys) + { + continue; + } + entry->calling++; + keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, + nonce_i, nonce_r, rekey); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of bus_t.child_keys + */ +static void child_keys(private_bus_t *this, child_sa_t *child_sa, + diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + entry_t *entry; + bool keep; + + ike_sa = pthread_getspecific(this->thread_sa); + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->child_keys) + { + continue; + } + entry->calling++; + keep = entry->listener->child_keys(entry->listener, ike_sa, child_sa, + dh, nonce_i, nonce_r); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** * Implementation of bus_t.destroy. */ static void destroy(private_bus_t *this) @@ -367,16 +537,21 @@ bus_t *bus_create() { private_bus_t *this = malloc_thing(private_bus_t); - this->public.add_listener = (void(*)(bus_t*,bus_listener_t*))add_listener; - this->public.remove_listener = (void(*)(bus_t*,bus_listener_t*))remove_listener; - this->public.listen = (void(*)(bus_t*, bus_listener_t *listener, job_t *job))listen_; + this->public.add_listener = (void(*)(bus_t*,listener_t*))add_listener; + this->public.remove_listener = (void(*)(bus_t*,listener_t*))remove_listener; + this->public.listen = (void(*)(bus_t*, listener_t *listener, job_t *job))listen_; this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa; - this->public.signal = (void(*)(bus_t*,signal_t,level_t,void*,char*,...))signal_; - this->public.vsignal = (void(*)(bus_t*,signal_t,level_t,void*,char*,va_list))vsignal; + this->public.log = (void(*)(bus_t*,debug_t,level_t,char*,...))log_; + this->public.vlog = (void(*)(bus_t*,debug_t,level_t,char*,va_list))vlog; + this->public.ike_state_change = (void(*)(bus_t*,ike_sa_t*,ike_sa_state_t))ike_state_change; + this->public.child_state_change = (void(*)(bus_t*,child_sa_t*,child_sa_state_t))child_state_change; + this->public.message = (void(*)(bus_t*, message_t *message, bool incoming))message; + this->public.ike_keys = (void(*)(bus_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys; + this->public.child_keys = (void(*)(bus_t*, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys; this->public.destroy = (void(*)(bus_t*)) destroy; this->listeners = linked_list_create(); - this->mutex = mutex_create(MUTEX_DEFAULT); + this->mutex = mutex_create(MUTEX_RECURSIVE); pthread_key_create(&this->thread_id, NULL); pthread_key_create(&this->thread_sa, NULL); |