From: Tobias Brunner Date: Mon, 20 Apr 2015 12:38:17 +0000 (+0200) Subject: redirect-manager: Add manager for redirect providers X-Git-Tag: 5.4.0dr8~12^2~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a6e054122fb2c7047e1186e72e14d8e40586d9e;p=thirdparty%2Fstrongswan.git redirect-manager: Add manager for redirect providers --- diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index ca9466692a..6fe682e499 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -84,7 +84,7 @@ sa/child_sa_manager.c sa/child_sa_manager.h \ sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h \ sa/trap_manager.c sa/trap_manager.h \ -sa/redirect_provider.h \ +sa/redirect_provider.h sa/redirect_manager.c sa/redirect_manager.h \ sa/task.c sa/task.h libcharon_la_SOURCES += \ diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 2edf92a7a7..34587677fa 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -83,7 +83,7 @@ sa/child_sa_manager.c sa/child_sa_manager.h \ sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h \ sa/trap_manager.c sa/trap_manager.h \ -sa/redirect_provider.h \ +sa/redirect_provider.h sa/redirect_manager.c sa/redirect_manager.h \ sa/task.c sa/task.h if USE_IKEV2 diff --git a/src/libcharon/sa/redirect_manager.c b/src/libcharon/sa/redirect_manager.c new file mode 100644 index 0000000000..dfc71e1065 --- /dev/null +++ b/src/libcharon/sa/redirect_manager.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015 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 . + * + * 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 "redirect_manager.h" + +#include +#include + +typedef struct private_redirect_manager_t private_redirect_manager_t; + +/** + * Private data + */ +struct private_redirect_manager_t { + + /** + * Public interface + */ + redirect_manager_t public; + + /** + * Registered providers + */ + linked_list_t *providers; + + /** + * Lock to access list of providers + */ + rwlock_t *lock; +}; + +METHOD(redirect_manager_t, add_provider, void, + private_redirect_manager_t *this, redirect_provider_t *provider) +{ + this->lock->write_lock(this->lock); + this->providers->insert_last(this->providers, provider); + this->lock->unlock(this->lock); +} + +METHOD(redirect_manager_t, remove_provider, void, + private_redirect_manager_t *this, redirect_provider_t *provider) +{ + this->lock->write_lock(this->lock); + this->providers->remove(this->providers, provider, NULL); + this->lock->unlock(this->lock); +} + +/** + * Determine whether a client should be redirected using the callback with the + * given offset into the redirect_provider_t interface. + */ +static bool should_redirect(private_redirect_manager_t *this, ike_sa_t *ike_sa, + identification_t **gateway, size_t offset) +{ + enumerator_t *enumerator; + void *provider; + bool redirect = FALSE; + + this->lock->read_lock(this->lock); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + bool (**method)(void*,ike_sa_t*,identification_t**) = provider + offset; + if (*method && (*method)(provider, ike_sa, gateway)) + { + redirect = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + return redirect; +} + +METHOD(redirect_manager_t, redirect_on_init, bool, + private_redirect_manager_t *this, ike_sa_t *ike_sa, + identification_t **gateway) +{ + return should_redirect(this, ike_sa, gateway, + offsetof(redirect_provider_t, redirect_on_init)); +} + +METHOD(redirect_manager_t, redirect_on_auth, bool, + private_redirect_manager_t *this, ike_sa_t *ike_sa, + identification_t **gateway) +{ + return should_redirect(this, ike_sa, gateway, + offsetof(redirect_provider_t, redirect_on_auth)); +} + +METHOD(redirect_manager_t, destroy, void, + private_redirect_manager_t *this) +{ + this->providers->destroy(this->providers); + this->lock->destroy(this->lock); + free(this); +} + +/* + * Described in header + */ +redirect_manager_t *redirect_manager_create() +{ + private_redirect_manager_t *this; + + INIT(this, + .public = { + .add_provider = _add_provider, + .remove_provider = _remove_provider, + .redirect_on_init = _redirect_on_init, + .redirect_on_auth = _redirect_on_auth, + .destroy = _destroy, + }, + .providers = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} diff --git a/src/libcharon/sa/redirect_manager.h b/src/libcharon/sa/redirect_manager.h new file mode 100644 index 0000000000..a74cfa3b47 --- /dev/null +++ b/src/libcharon/sa/redirect_manager.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015 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 . + * + * 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 redirect_manager redirect_manager + * @{ @ingroup sa + */ + +#ifndef REDIRECT_MANAGER_H_ +#define REDIRECT_MANAGER_H_ + +typedef struct redirect_manager_t redirect_manager_t; + +#include + +/** + * Manages redirect providers. + */ +struct redirect_manager_t { + + /** + * Add a redirect provider. + * + * All registered providers are queried until one of them decides to + * redirect a client. + * + * A provider may be called concurrently for different IKE_SAs. + * + * @param provider provider to register + */ + void (*add_provider)(redirect_manager_t *this, + redirect_provider_t *provider); + + /** + * Remove a redirect provider. + * + * @param provider provider to unregister + */ + void (*remove_provider)(redirect_manager_t *this, + redirect_provider_t *provider); + + /** + * Determine whether a client should be redirected upon receipt of the + * IKE_SA_INIT message. + * + * @param ike_sa IKE_SA for which this is called + * @param gateway[out] new IKE gateway (IP or FQDN) + * @return TRUE if client should be redirected, FALSE otherwise + */ + bool (*redirect_on_init)(redirect_manager_t *this, ike_sa_t *ike_sa, + identification_t **gateway); + + /** + * Determine whether a client should be redirected after the IKE_AUTH has + * been handled. Should be called after the client is authenticated and + * when the server authenticates itself. + * + * @param ike_sa IKE_SA for which this is called + * @param gateway[out] new IKE gateway (IP or FQDN) + * @return TRUE if client should be redirected, FALSE otherwise + */ + bool (*redirect_on_auth)(redirect_manager_t *this, ike_sa_t *ike_sa, + identification_t **gateway); + + /** + * Destroy this instance. + */ + void (*destroy)(redirect_manager_t *this); +}; + +/** + * Create a redirect manager instance. + * + * @return manager instance + */ +redirect_manager_t *redirect_manager_create(); + +#endif /** REDIRECT_MANAGER_H_ @}*/