diff options
author | Martin Willi <martin@strongswan.org> | 2009-04-24 14:13:52 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2009-04-24 14:13:52 +0000 |
commit | 7f56b494616fca022b157eff393a0bfa19cf5e2b (patch) | |
tree | e2fd93668cbfab29b25fcf8a5498bc0bda4f73c6 /src | |
parent | da17b0169ab4d6eee644b7a612ecbd58be7ae4a7 (diff) | |
download | strongswan-7f56b494616fca022b157eff393a0bfa19cf5e2b.tar.bz2 strongswan-7f56b494616fca022b157eff393a0bfa19cf5e2b.tar.xz |
attribute_manager supports attribute_handler's to handle configuration attributes via plugins
moved resolv.conf editing to a separate plugin (resolv_conf)
extended attribute_provider interface to hand out arbitrary attributes
moved strongswan.conf based dns/nbns configuration to a plugin (attr)
Diffstat (limited to 'src')
20 files changed, 1095 insertions, 377 deletions
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 037f81956..ef62bff15 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -12,6 +12,7 @@ config/proposal.c config/proposal.h config/proposal_keywords.c config/proposal_k config/auth_cfg.c config/auth_cfg.h \ config/traffic_selector.c config/traffic_selector.h \ config/attributes/attribute_provider.h \ +config/attributes/attribute_handler.h \ config/attributes/attribute_manager.c config/attributes/attribute_manager.h \ control/controller.c control/controller.h \ daemon.c daemon.h \ @@ -105,7 +106,6 @@ AM_CFLAGS = -rdynamic \ -DIPSEC_PIDDIR=\"${piddir}\" \ -DIPSEC_PLUGINDIR=\"${plugindir}\" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ - -DRESOLV_CONF=\"${resolv_conf}\" \ -Wformat=0 charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lm -ldl @@ -193,6 +193,16 @@ if USE_UPDOWN PLUGINS += updown endif +if USE_ATTR + SUBDIRS += plugins/attr + PLUGINS += attr +endif + +if USE_RESOLV_CONF + SUBDIRS += plugins/resolv_conf + PLUGINS += resolv-conf +endif + if USE_EAP_IDENTITY SUBDIRS += plugins/eap_identity PLUGINS += eapidentity diff --git a/src/charon/config/attributes/attribute_handler.h b/src/charon/config/attributes/attribute_handler.h new file mode 100644 index 000000000..c92c7a451 --- /dev/null +++ b/src/charon/config/attributes/attribute_handler.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +/** + * @defgroup attribute_handler attribute_handler + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_HANDLER_H_ +#define ATTRIBUTE_HANDLER_H_ + +#include <sa/ike_sa.h> +#include <encoding/payloads/configuration_attribute.h> + +typedef struct attribute_handler_t attribute_handler_t; + +/** + * Interface to handle configuration payload attributes. + */ +struct attribute_handler_t { + + /** + * Handle a configuration attribute. + * + * After receiving a configuration attriubte, it is passed to each + * attribute handler until it is handled. + * + * @param type type of configuration attribute to handle + * @param data associated attribute data + * @return TRUE if attribute handled + */ + bool (*handle)(attribute_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data); + + /** + * Release an attribute handled during handle(). + * + * A handler that handle()d an attribute gets a call to release() when the + * IKE_SA gets closed. Depending on the implementation, this is required + * to remove the attribute. + */ + void (*release)(attribute_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data); +}; + +#endif /* ATTRIBUTE_HANDLER_ @}*/ diff --git a/src/charon/config/attributes/attribute_manager.c b/src/charon/config/attributes/attribute_manager.c index f0ae4ffa0..5e6efe724 100644 --- a/src/charon/config/attributes/attribute_manager.c +++ b/src/charon/config/attributes/attribute_manager.c @@ -39,6 +39,11 @@ struct private_attribute_manager_t { linked_list_t *providers; /** + * list of registered handlers + */ + linked_list_t *handlers; + + /** * rwlock provider list */ rwlock_t *lock; @@ -105,6 +110,29 @@ static void release_address(private_attribute_manager_t *this, } /** + * inner enumerator constructor for attributes + */ +static enumerator_t *attrib_enum_create(attribute_provider_t *provider, + identification_t *id) +{ + return provider->create_attribute_enumerator(provider, id); +} + +/** + * Implementation of attribute_manager_t.create_attribute_enumerator + */ +static enumerator_t* create_attribute_enumerator( + private_attribute_manager_t *this, identification_t *id) +{ + this->lock->read_lock(this->lock); + return enumerator_create_cleaner( + enumerator_create_nested( + this->providers->create_enumerator(this->providers), + (void*)attrib_enum_create, id, NULL), + (void*)this->lock->unlock, this->lock); +} + +/** * Implementation of attribute_manager_t.add_provider. */ static void add_provider(private_attribute_manager_t *this, @@ -127,11 +155,89 @@ static void remove_provider(private_attribute_manager_t *this, } /** + * Implementation of attribute_manager_t.handle + */ +static attribute_handler_t* handle(private_attribute_manager_t *this, + ike_sa_t *ike_sa, configuration_attribute_type_t type, + chunk_t data) +{ + enumerator_t *enumerator; + attribute_handler_t *current, *handled = NULL; + + this->lock->read_lock(this->lock); + enumerator = this->handlers->create_enumerator(this->handlers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->handle(current, ike_sa, type, data)) + { + handled = current; + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + if (!handled) + { + DBG1(DBG_CFG, "handling %N attribute failed", + configuration_attribute_type_names, type); + } + return handled; +} + +/** + * Implementation of attribute_manager_t.release + */ +static void release(private_attribute_manager_t *this, + attribute_handler_t *handler, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + enumerator_t *enumerator; + attribute_handler_t *current; + + this->lock->read_lock(this->lock); + enumerator = this->handlers->create_enumerator(this->handlers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current == handler) + { + current->release(current, ike_sa, type, data); + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + +/** + * Implementation of attribute_manager_t.add_handler + */ +static void add_handler(private_attribute_manager_t *this, + attribute_handler_t *handler) +{ + this->lock->write_lock(this->lock); + this->handlers->insert_last(this->handlers, handler); + this->lock->unlock(this->lock); +} + +/** + * Implementation of attribute_manager_t.remove_handler + */ +static void remove_handler(private_attribute_manager_t *this, + attribute_handler_t *handler) +{ + this->lock->write_lock(this->lock); + this->handlers->remove(this->handlers, handler, NULL); + this->lock->unlock(this->lock); +} + +/** * Implementation of attribute_manager_t.destroy */ static void destroy(private_attribute_manager_t *this) { this->providers->destroy(this->providers); + this->handlers->destroy(this->handlers); this->lock->destroy(this->lock); free(this); } @@ -145,11 +251,17 @@ attribute_manager_t *attribute_manager_create() this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address; this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address; + this->public.create_attribute_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t *id))create_attribute_enumerator; this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider; this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider; + this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data))handle; + this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t *handler, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data))release; + this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t *handler))add_handler; + this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t *handler))remove_handler; this->public.destroy = (void(*)(attribute_manager_t*))destroy; this->providers = linked_list_create(); + this->handlers = linked_list_create(); this->lock = rwlock_create(RWLOCK_DEFAULT); return &this->public; diff --git a/src/charon/config/attributes/attribute_manager.h b/src/charon/config/attributes/attribute_manager.h index 750f83c58..ff6db0cf9 100644 --- a/src/charon/config/attributes/attribute_manager.h +++ b/src/charon/config/attributes/attribute_manager.h @@ -24,14 +24,20 @@ #define ATTRIBUTE_MANAGER_H_ #include <config/attributes/attribute_provider.h> +#include <config/attributes/attribute_handler.h> typedef struct attribute_manager_t attribute_manager_t; /** - * Provide configuration attributes to include in CFG Payloads. + * The attribute manager hands out attributes or handles them. + * + * The attribute manager manages both, attribute providers and attribute + * handlers. Attribute providers are responsible to hand out attributes if + * a connecting peer requests them. Handlers handle such attributes if they + * are received on the requesting peer. */ struct attribute_manager_t { - + /** * Acquire a virtual IP address to assign to a peer. * @@ -55,6 +61,15 @@ struct attribute_manager_t { char *pool, host_t *address, identification_t *id); /** + * Create an enumerator over attributes to hand out to a peer. + * + * @param id peer identity to hand out attributes to + * @return enumerator (configuration_attribute_type_t, chunk_t) + */ + enumerator_t* (*create_attribute_enumerator)(attribute_manager_t *this, + identification_t *id); + + /** * Register an attribute provider to the manager. * * @param provider attribute provider to register @@ -68,6 +83,46 @@ struct attribute_manager_t { */ void (*remove_provider)(attribute_manager_t *this, attribute_provider_t *provider); + + /** + * Handle a configuration attribute by passing them to the handlers. + * + * @param ike_sa IKE_SA where attribute was received + * @param type type of configuration attribute + * @param data associated attribute data + * @return handler which handled this attribute, NULL if none + */ + attribute_handler_t* (*handle)(attribute_manager_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data); + + /** + * Release an attribute previously handle()d by a handler. + * + * @param handler handler returned by handle() for this attribute + * @param ike_sa IKE_SA owning the attribute + * @param type type of attribute to release + * @param data associated attribute data + */ + void (*release)(attribute_manager_t *this, attribute_handler_t *handler, + ike_sa_t *ike_sa, configuration_attribute_type_t type, + chunk_t data); + + /** + * Register an attribute handler to the manager. + * + * @param handler attribute handler to register + */ + void (*add_handler)(attribute_manager_t *this, + attribute_handler_t *handler); + + /** + * Unregister an attribute handler from the manager. + * + * @param handler attribute handler to unregister + */ + void (*remove_handler)(attribute_manager_t *this, + attribute_handler_t *handler); + /** * Destroy a attribute_manager instance. */ diff --git a/src/charon/config/attributes/attribute_provider.h b/src/charon/config/attributes/attribute_provider.h index cbd0075ad..2b0efdeae 100644 --- a/src/charon/config/attributes/attribute_provider.h +++ b/src/charon/config/attributes/attribute_provider.h @@ -54,6 +54,15 @@ struct attribute_provider_t { */ bool (*release_address)(attribute_provider_t *this, char *pool, host_t *address, identification_t *id); + + /** + * Create an enumerator over attributes to hand out to a peer. + * + * @param id peer ID + * @return enumerator (configuration_attribute_type_t, chunk_t) + */ + enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this, + identification_t *id); }; #endif /** ATTRIBUTE_PROVIDER_H_ @}*/ diff --git a/src/charon/plugins/attr/Makefile.am b/src/charon/plugins/attr/Makefile.am new file mode 100644 index 000000000..d5eb99d9f --- /dev/null +++ b/src/charon/plugins/attr/Makefile.am @@ -0,0 +1,9 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-attr.la +libstrongswan_attr_la_SOURCES = attr_plugin.h attr_plugin.c \ + attr_provider.h attr_provider.c +libstrongswan_attr_la_LDFLAGS = -module diff --git a/src/charon/plugins/attr/attr_plugin.c b/src/charon/plugins/attr/attr_plugin.c new file mode 100644 index 000000000..fd6619852 --- /dev/null +++ b/src/charon/plugins/attr/attr_plugin.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +#include "attr_plugin.h" +#include "attr_provider.h" + +#include <daemon.h> + +typedef struct private_attr_plugin_t private_attr_plugin_t; + +/** + * private data of attr plugin + */ +struct private_attr_plugin_t { + + /** + * implements plugin interface + */ + attr_plugin_t public; + + /** + * CFG attributes provider + */ + attr_provider_t *provider; +}; + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_attr_plugin_t *this) +{ + charon->attributes->remove_provider(charon->attributes, &this->provider->provider); + this->provider->destroy(this->provider); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_attr_plugin_t *this = malloc_thing(private_attr_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->provider = attr_provider_create(); + charon->attributes->add_provider(charon->attributes, &this->provider->provider); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/attr/attr_plugin.h b/src/charon/plugins/attr/attr_plugin.h new file mode 100644 index 000000000..36e8daa37 --- /dev/null +++ b/src/charon/plugins/attr/attr_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +/** + * @defgroup attr attr + * @ingroup cplugins + * + * @defgroup attr_plugin attr_plugin + * @{ @ingroup attr + */ + +#ifndef ATTR_PLUGIN_H_ +#define ATTR_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct attr_plugin_t attr_plugin_t; + +/** + * Plugin providing configuration attribute through strongswan.conf. + */ +struct attr_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a attr_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /** ATTR_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/attr/attr_provider.c b/src/charon/plugins/attr/attr_provider.c new file mode 100644 index 000000000..8893262a8 --- /dev/null +++ b/src/charon/plugins/attr/attr_provider.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +#include "attr_provider.h" + +#include <time.h> + +#include <daemon.h> + +#define SERVER_MAX 2 + +typedef struct private_attr_provider_t private_attr_provider_t; +typedef struct attribute_entry_t attribute_entry_t; + +/** + * private data of attr_provider + */ +struct private_attr_provider_t { + + /** + * public functions + */ + attr_provider_t public; + + /** + * List of attributes, attribute_entry_t + */ + linked_list_t *attributes; +}; + +struct attribute_entry_t { + /** type of attribute */ + configuration_attribute_type_t type; + /** attribute value */ + chunk_t value; +}; + +/** + * convert enumerator value from attribute_entry + */ +static bool attr_enum_filter(void *null, attribute_entry_t **in, + configuration_attribute_type_t *type, void* none, chunk_t *value) +{ + *type = (*in)->type; + *value = (*in)->value; + return TRUE; +} + +/** + * Implementation of attribute_provider_t.create_attribute_enumerator + */ +static enumerator_t* create_attribute_enumerator( + private_attr_provider_t *this, identification_t *id) +{ + return enumerator_create_filter( + this->attributes->create_enumerator(this->attributes), + (void*)attr_enum_filter, NULL, NULL); +} + +/** + * Implementation of attr_provider_t.destroy + */ +static void destroy(private_attr_provider_t *this) +{ + attribute_entry_t *entry; + + while (this->attributes->remove_last(this->attributes, + (void**)&entry) == SUCCESS) + { + free(entry->value.ptr); + free(entry); + } + this->attributes->destroy(this->attributes); + free(this); +} + +/** + * Add an attribute entry to the list + */ +static void add_entry(private_attr_provider_t *this, char *key, int nr, + configuration_attribute_type_t type) +{ + attribute_entry_t *entry; + host_t *host; + char *str; + + str = lib->settings->get_str(lib->settings, "charon.%s%d", NULL, key, nr); + if (str) + { + host = host_create_from_string(str, 0); + if (host) + { + entry = malloc_thing(attribute_entry_t); + + if (host->get_family(host) == AF_INET6) + { + switch (type) + { + case INTERNAL_IP4_DNS: + type = INTERNAL_IP6_DNS; + break; + case INTERNAL_IP4_NBNS: + type = INTERNAL_IP6_NBNS; + break; + default: + break; + } + } + entry->type = type; + entry->value = chunk_clone(host->get_address(host)); + host->destroy(host); + this->attributes->insert_last(this->attributes, entry); + } + } +} + +/* + * see header file + */ +attr_provider_t *attr_provider_create(database_t *db) +{ + private_attr_provider_t *this; + int i; + + this = malloc_thing(private_attr_provider_t); + + this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null; + this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false; + this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id))create_attribute_enumerator; + this->public.destroy = (void(*)(attr_provider_t*))destroy; + + this->attributes = linked_list_create(); + + for (i = 1; i <= SERVER_MAX; i++) + { + add_entry(this, "dns", i, INTERNAL_IP4_DNS); + add_entry(this, "nbns", i, INTERNAL_IP4_NBNS); + } + + return &this->public; +} + diff --git a/src/charon/plugins/attr/attr_provider.h b/src/charon/plugins/attr/attr_provider.h new file mode 100644 index 000000000..103e2c742 --- /dev/null +++ b/src/charon/plugins/attr/attr_provider.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +/** + * @defgroup attr_provider attr_provider + * @{ @ingroup attr + */ + +#ifndef ATTR_PROVIDER_H_ +#define ATTR_PROVIDER_H_ + +#include <config/attributes/attribute_provider.h> + +typedef struct attr_provider_t attr_provider_t; + +/** + * Provide configuration attributes through static strongswan.conf definition. + */ +struct attr_provider_t { + + /** + * Implements attribute provider interface + */ + attribute_provider_t provider; + + /** + * Destroy a attr_provider instance. + */ + void (*destroy)(attr_provider_t *this); +}; + +/** + * Create a attr_provider instance. + */ +attr_provider_t *attr_provider_create(); + +#endif /** ATTR_PROVIDER @}*/ diff --git a/src/charon/plugins/resolv_conf/Makefile.am b/src/charon/plugins/resolv_conf/Makefile.am new file mode 100644 index 000000000..917964f93 --- /dev/null +++ b/src/charon/plugins/resolv_conf/Makefile.am @@ -0,0 +1,13 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic \ + -DRESOLV_CONF=\"${resolv_conf}\" + +plugin_LTLIBRARIES = libstrongswan-resolv-conf.la +libstrongswan_resolv_conf_la_SOURCES = \ + resolv_conf_plugin.h resolv_conf_plugin.c \ + resolv_conf_handler.h resolv_conf_handler.c +libstrongswan_resolv_conf_la_LDFLAGS = -module + + diff --git a/src/charon/plugins/resolv_conf/resolv_conf_handler.c b/src/charon/plugins/resolv_conf/resolv_conf_handler.c new file mode 100644 index 000000000..c76222f28 --- /dev/null +++ b/src/charon/plugins/resolv_conf/resolv_conf_handler.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +#include "resolv_conf_handler.h" + +#include <unistd.h> + +#include <daemon.h> +#include <utils/mutex.h> + +typedef struct private_resolv_conf_handler_t private_resolv_conf_handler_t; + +/** + * Private data of an resolv_conf_handler_t object. + */ +struct private_resolv_conf_handler_t { + + /** + * Public resolv_conf_handler_t interface. + */ + resolv_conf_handler_t public; + + /** + * resolv.conf file to use + */ + char *file; + + /** + * Mutex to access file exclusively + */ + mutex_t *mutex; +}; + +/** + * Implementation of attribute_handler_t.handle + */ +static bool handle(private_resolv_conf_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + FILE *in, *out; + char buf[1024]; + host_t *addr; + int family; + size_t len; + bool handled = FALSE; + + switch (type) + { + case INTERNAL_IP4_DNS: + family = AF_INET; + break; + case INTERNAL_IP6_DNS: + family = AF_INET6; + break; + default: + return FALSE; + } + + this->mutex->lock(this->mutex); + + in = fopen(this->file, "r"); + /* allows us to stream from in to out */ + unlink(this->file); + out = fopen(this->file, "w"); + if (out) + { + addr = host_create_from_chunk(family, data, 0); + fprintf(out, "nameserver %H # by strongSwan, from %D\n", + addr, ike_sa->get_other_id(ike_sa)); + DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file); + addr->destroy(addr); + handled = TRUE; + + /* copy rest of the file */ + if (in) + { + while ((len = fread(buf, 1, sizeof(buf), in))) + { + ignore_result(fwrite(buf, 1, len, out)); + } + fclose(in); + } + fclose(out); + } + + if (!handled) + { + DBG1(DBG_IKE, "adding DNS server failed", this->file); + } + this->mutex->unlock(this->mutex); + return handled; +} + +/** + * Implementation of attribute_handler_t.release + */ +static void release(private_resolv_conf_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + FILE *in, *out; + char line[1024], matcher[512], *pos; + host_t *addr; + int family; + + switch (type) + { + case INTERNAL_IP4_DNS: + family = AF_INET; + break; + case INTERNAL_IP6_DNS: + family = AF_INET6; + break; + default: + return; + } + + this->mutex->lock(this->mutex); + + in = fopen(this->file, "r"); + if (in) + { + /* allows us to stream from in to out */ + unlink(this->file); + out = fopen(this->file, "w"); + if (out) + { + addr = host_create_from_chunk(family, data, 0); + snprintf(matcher, sizeof(matcher), + "nameserver %H # by strongSwan, from %D\n", + addr, ike_sa->get_other_id(ike_sa)); + + /* copy all, but matching line */ + while ((pos = fgets(line, sizeof(line), in))) + { + if (strneq(line, matcher, strlen(matcher))) + { + DBG1(DBG_IKE, "removing DNS server %H from %s", + addr, this->file); + } + else + { + fputs(line, out); + } + } + addr->destroy(addr); + fclose(out); + } + fclose(in); + } + + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of resolv_conf_handler_t.destroy. + */ +static void destroy(private_resolv_conf_handler_t *this) +{ + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +resolv_conf_handler_t *resolv_conf_handler_create() +{ + private_resolv_conf_handler_t *this = malloc_thing(private_resolv_conf_handler_t); + + this->public.handler.handle = (bool(*)(attribute_handler_t*, ike_sa_t*, configuration_attribute_type_t, chunk_t))handle; + this->public.handler.release = (void(*)(attribute_handler_t*, ike_sa_t*, configuration_attribute_type_t, chunk_t))release; + this->public.destroy = (void(*)(resolv_conf_handler_t*))destroy; + + this->mutex = mutex_create(MUTEX_DEFAULT); + this->file = lib->settings->get_str(lib->settings, + "charon.plugins.resolv-conf.file", RESOLV_CONF); + + return &this->public; +} + diff --git a/src/charon/plugins/resolv_conf/resolv_conf_handler.h b/src/charon/plugins/resolv_conf/resolv_conf_handler.h new file mode 100644 index 000000000..c5608b726 --- /dev/null +++ b/src/charon/plugins/resolv_conf/resolv_conf_handler.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +/** + * @defgroup resolv_conf_handler resolv_conf_handler + * @{ @ingroup resolv_conf + */ + +#ifndef RESOLV_CONF_HANDLER_H_ +#define RESOLV_CONF_HANDLER_H_ + +#include <config/attributes/attribute_handler.h> + +typedef struct resolv_conf_handler_t resolv_conf_handler_t; + +/** + * Handle DNS configuration attributes by mangling a resolv.conf file. + */ +struct resolv_conf_handler_t { + + /** + * Implements the attribute_handler_t interface + */ + attribute_handler_t handler; + + /** + * Destroy a resolv_conf_handler_t. + */ + void (*destroy)(resolv_conf_handler_t *this); +}; + +/** + * Create a resolv_conf_handler instance. + */ +resolv_conf_handler_t *resolv_conf_handler_create(); + +#endif /* RESOLV_CONF_HANDLER_ @}*/ diff --git a/src/charon/plugins/resolv_conf/resolv_conf_plugin.c b/src/charon/plugins/resolv_conf/resolv_conf_plugin.c new file mode 100644 index 000000000..855f4dad4 --- /dev/null +++ b/src/charon/plugins/resolv_conf/resolv_conf_plugin.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +#include "resolv_conf_plugin.h" +#include "resolv_conf_handler.h" + +#include <daemon.h> + +typedef struct private_resolv_conf_plugin_t private_resolv_conf_plugin_t; + +/** + * private data of resolv_conf plugin + */ +struct private_resolv_conf_plugin_t { + + /** + * implements plugin interface + */ + resolv_conf_plugin_t public; + + /** + * The registerd DNS attribute handler + */ + resolv_conf_handler_t *handler; +}; + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_resolv_conf_plugin_t *this) +{ + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); + this->handler->destroy(this->handler); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_resolv_conf_plugin_t *this = malloc_thing(private_resolv_conf_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->handler = resolv_conf_handler_create(); + charon->attributes->add_handler(charon->attributes, &this->handler->handler); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/resolv_conf/resolv_conf_plugin.h b/src/charon/plugins/resolv_conf/resolv_conf_plugin.h new file mode 100644 index 000000000..1a93bfcdf --- /dev/null +++ b/src/charon/plugins/resolv_conf/resolv_conf_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 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. + * + * $Id$ + */ + +/** + * @defgroup resolv_conf resolv_conf + * @ingroup cplugins + * + * @defgroup resolv_conf_plugin resolv_conf_plugin + * @{ @ingroup resolv_conf + */ + +#ifndef RESOLV_CONF_PLUGIN_H_ +#define RESOLV_CONF_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct resolv_conf_plugin_t resolv_conf_plugin_t; + +/** + * Plugin that writes received DNS servers in a resolv.conf file. + */ +struct resolv_conf_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a resolv_conf_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /** RESOLV_CONF_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/sql/sql_attribute.c b/src/charon/plugins/sql/sql_attribute.c index 484085d11..4510645e1 100644 --- a/src/charon/plugins/sql/sql_attribute.c +++ b/src/charon/plugins/sql/sql_attribute.c @@ -265,6 +265,7 @@ sql_attribute_t *sql_attribute_create(database_t *db) this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address; this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address; + this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id))enumerator_create_empty; this->public.destroy = (void(*)(sql_attribute_t*))destroy; this->db = db; diff --git a/src/charon/plugins/stroke/stroke_attribute.c b/src/charon/plugins/stroke/stroke_attribute.c index 0ebc367fa..a3beb3a62 100644 --- a/src/charon/plugins/stroke/stroke_attribute.c +++ b/src/charon/plugins/stroke/stroke_attribute.c @@ -532,6 +532,7 @@ stroke_attribute_t *stroke_attribute_create() this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,host_t *))acquire_address; this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address; + this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id))enumerator_create_empty; this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool; this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool; this->public.create_pool_enumerator = (enumerator_t*(*)(stroke_attribute_t*))create_pool_enumerator; diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index fd70e9941..4a14da580 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -57,10 +57,6 @@ #include <processing/jobs/initiate_mediation_job.h> #endif -#ifndef RESOLV_CONF -#define RESOLV_CONF "/etc/resolv.conf" -#endif - ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING, "CREATED", "CONNECTING", @@ -72,17 +68,18 @@ ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING, ); typedef struct private_ike_sa_t private_ike_sa_t; +typedef struct attribute_entry_t attribute_entry_t; /** * Private data of an ike_sa_t object. */ struct private_ike_sa_t { - + /** * Public members */ ike_sa_t public; - + /** * Identifier for the current IKE_SA. */ @@ -96,7 +93,7 @@ struct private_ike_sa_t { /** * Current state of the IKE_SA */ - ike_sa_state_t state; + ike_sa_state_t state; /** * IKE configuration used to set up this IKE_SA @@ -179,7 +176,7 @@ struct private_ike_sa_t { * set of condition flags currently enabled for this IKE_SA */ ike_condition_t conditions; - + /** * Linked List containing the child sa's of the current IKE_SA. */ @@ -201,9 +198,9 @@ struct private_ike_sa_t { host_t *other_virtual_ip; /** - * List of DNS servers installed by us + * List of configuration attributes (attribute_entry_t) */ - linked_list_t *dns_servers; + linked_list_t *attributes; /** * list of peers additional addresses, transmitted via MOBIKE @@ -219,7 +216,7 @@ struct private_ike_sa_t { * number pending UPDATE_SA_ADDRESS (MOBIKE) */ u_int32_t pending_updates; - + /** * NAT keep alive interval */ @@ -234,12 +231,12 @@ struct private_ike_sa_t { * how many times we have retried so far (keyingtries) */ u_int32_t keyingtry; - + /** * local host address to be used for IKE, set via MIGRATE kernel message */ host_t *local_host; - + /** * remote host address to be used for IKE, set via MIGRATE kernel message */ @@ -247,6 +244,18 @@ struct private_ike_sa_t { }; /** + * Entry to maintain install configuration attributes during IKE_SA lifetime + */ +struct attribute_entry_t { + /** handler used to install this attribute */ + attribute_handler_t *handler; + /** attribute type */ + configuration_attribute_type_t type; + /** attribute data */ + chunk_t data; +}; + +/** * get the time of the latest traffic processed by the kernel */ static time_t get_use_time(private_ike_sa_t* this, bool inbound) @@ -1996,12 +2005,34 @@ static status_t roam(private_ike_sa_t *this, bool address) } /** + * Implementation of ike_sa_t.add_configuration_attribute + */ +static void add_configuration_attribute(private_ike_sa_t *this, + configuration_attribute_type_t type, chunk_t data) +{ + attribute_entry_t *entry; + attribute_handler_t *handler; + + handler = charon->attributes->handle(charon->attributes, + &this->public, type, data); + if (handler) + { + entry = malloc_thing(attribute_entry_t); + entry->handler = handler; + entry->type = type; + entry->data = chunk_clone(data); + + this->attributes->insert_last(this->attributes, entry); + } +} + +/** * Implementation of ike_sa_t.inherit. */ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) { child_sa_t *child_sa; - host_t *ip; + attribute_entry_t *entry; /* apply hosts and ids */ this->my_host->destroy(this->my_host); @@ -2025,11 +2056,11 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) other->other_virtual_ip = NULL; } - /* ... and DNS servers */ - while (other->dns_servers->remove_last(other->dns_servers, - (void**)&ip) == SUCCESS) + /* ... and configuration attributes */ + while (other->attributes->remove_last(other->attributes, + (void**)&entry) == SUCCESS) { - this->dns_servers->insert_first(this->dns_servers, ip); + this->attributes->insert_first(this->attributes, entry); } /* inherit all conditions */ @@ -2082,147 +2113,27 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) } /** - * Implementation of ike_sa_t.remove_dns_server - */ -static void remove_dns_servers(private_ike_sa_t *this) -{ - FILE *file; - struct stat stats; - chunk_t contents, line, orig_line, token; - char string[INET6_ADDRSTRLEN]; - host_t *ip; - iterator_t *iterator; - - if (this->dns_servers->get_count(this->dns_servers) == 0) - { - /* don't touch anything if we have no nameservers installed */ - return; - } - - file = fopen(RESOLV_CONF, "r"); - if (file == NULL || stat(RESOLV_CONF, &stats) != 0) - { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", - RESOLV_CONF, strerror(errno)); - return; - } - - contents = chunk_alloca((size_t)stats.st_size); - - if (fread(contents.ptr, 1, contents.len, file) != contents.len) - { - DBG1(DBG_IKE, "unable to read DNS configuration file: %s", strerror(errno)); - fclose(file); - return; - } - - fclose(file); - file = fopen(RESOLV_CONF, "w"); - if (file == NULL) - { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", - RESOLV_CONF, strerror(errno)); - return; - } - - iterator = this->dns_servers->create_iterator(this->dns_servers, TRUE); - while (fetchline(&contents, &line)) - { - bool found = FALSE; - orig_line = line; - if (extract_token(&token, ' ', &line) && - strncasecmp(token.ptr, "nameserver", token.len) == 0) - { - if (!extract_token(&token, ' ', &line)) - { - token = line; - } - iterator->reset(iterator); - while (iterator->iterate(iterator, (void**)&ip)) - { - snprintf(string, sizeof(string), "%H", ip); - if (strlen(string) == token.len && - strncmp(token.ptr, string, token.len) == 0) - { - iterator->remove(iterator); - ip->destroy(ip); - found = TRUE; - break; - } - } - } - - if (!found) - { - /* write line untouched back to file */ - ignore_result(fwrite(orig_line.ptr, orig_line.len, 1, file)); - fprintf(file, "\n"); - } - } - iterator->destroy(iterator); - fclose(file); -} - -/** - * Implementation of ike_sa_t.add_dns_server - */ -static void add_dns_server(private_ike_sa_t *this, host_t *dns) -{ - FILE *file; - struct stat stats; - chunk_t contents; - - DBG1(DBG_IKE, "installing DNS server %H", dns); - - file = fopen(RESOLV_CONF, "a+"); - if (file == NULL || stat(RESOLV_CONF, &stats) != 0) - { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", - RESOLV_CONF, strerror(errno)); - return; - } - - contents = chunk_alloca(stats.st_size); - - if (fread(contents.ptr, 1, contents.len, file) != contents.len) - { - DBG1(DBG_IKE, "unable to read DNS configuration file: %s", strerror(errno)); - fclose(file); - return; - } - - fclose(file); - file = fopen(RESOLV_CONF, "w"); - if (file == NULL) - { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", - RESOLV_CONF, strerror(errno)); - return; - } - - if (fprintf(file, "nameserver %H # added by strongSwan, assigned by %D\n", - dns, this->other_id) < 0) - { - DBG1(DBG_IKE, "unable to write DNS configuration: %s", strerror(errno)); - } - else - { - this->dns_servers->insert_last(this->dns_servers, dns->clone(dns)); - } - ignore_result(fwrite(contents.ptr, contents.len, 1, file)); - - fclose(file); -} - -/** * Implementation of ike_sa_t.destroy. */ static void destroy(private_ike_sa_t *this) { + attribute_entry_t *entry; + charon->bus->set_sa(charon->bus, &this->public); set_state(this, IKE_DESTROYING); + /* remove attributes first, as we pass the IKE_SA to the handler */ + while (this->attributes->remove_last(this->attributes, + (void**)&entry) == SUCCESS) + { + charon->attributes->release(charon->attributes, entry->handler, + &this->public, entry->type, entry->data); + free(entry->data.ptr); + free(entry); + } + this->attributes->destroy(this->attributes); + this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy)); /* unset SA after here to avoid usage by the listeners */ @@ -2247,10 +2158,6 @@ static void destroy(private_ike_sa_t *this) } this->other_virtual_ip->destroy(this->other_virtual_ip); } - - remove_dns_servers(this); - this->dns_servers->destroy_offset(this->dns_servers, - offsetof(host_t, destroy)); this->additional_addresses->destroy_offset(this->additional_addresses, offsetof(host_t, destroy)); #ifdef ME @@ -2351,7 +2258,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id; this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip; this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip; - this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server; + this->public.add_configuration_attribute = (void(*)(ike_sa_t*, configuration_attribute_type_t type, chunk_t data))add_configuration_attribute; this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress; #ifdef ME this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server; @@ -2391,8 +2298,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->unique_id = ++unique_id; this->my_virtual_ip = NULL; this->other_virtual_ip = NULL; - this->dns_servers = linked_list_create(); this->additional_addresses = linked_list_create(); + this->attributes = linked_list_create(); this->nat_detection_dest = chunk_empty; this->pending_updates = 0; this->keyingtry = 0; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index c9d3b97f3..e17175bf1 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -35,6 +35,7 @@ typedef struct ike_sa_t ike_sa_t; #include <library.h> #include <encoding/message.h> #include <encoding/payloads/proposal_substructure.h> +#include <encoding/payloads/configuration_attribute.h> #include <sa/ike_sa_id.h> #include <sa/child_sa.h> #include <sa/tasks/task.h> @@ -868,14 +869,18 @@ struct ike_sa_t { host_t* (*get_virtual_ip) (ike_sa_t *this, bool local); /** - * Add a DNS server to the system. + * Register a configuration attribute to the IKE_SA. * - * An IRAS may send a DNS server. To use it, it is installed on the - * system. The DNS entry has a lifetime until the IKE_SA gets closed. + * If an IRAS sends a configuration attribute it is installed and + * registered at the IKE_SA. Attributes are inherit()ed and get released + * when the IKE_SA is closed. * - * @param dns DNS server to install on the system + * @param handler handler installed the attribute, use for release() + * @param type configuration attribute type + * @param data associated attribute data */ - void (*add_dns_server) (ike_sa_t *this, host_t *dns); + void (*add_configuration_attribute)(ike_sa_t *this, + configuration_attribute_type_t type, chunk_t data); /** * Set local and remote host addresses to be used for IKE. @@ -887,7 +892,7 @@ struct ike_sa_t { * @param remote remote kmaddress */ void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote); - + /** * Inherit all attributes of other to this after rekeying. * diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c index cb769f9b4..2e2696722 100644 --- a/src/charon/sa/tasks/ike_config.c +++ b/src/charon/sa/tasks/ike_config.c @@ -50,54 +50,34 @@ struct private_ike_config_t { * virtual ip */ host_t *virtual_ip; - - /** - * list of DNS servers - */ - linked_list_t *dns; - - /** - * list of WINS servers - */ - linked_list_t *nbns; }; /** - * build configuration payloads and attributes + * build INTERNAL_IPV4/6_ADDRESS from virtual ip */ -static void build_payloads(private_ike_config_t *this, message_t *message, - config_type_t type) +static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp) { - cp_payload_t *cp; configuration_attribute_t *ca; chunk_t chunk, prefix; - if (!this->virtual_ip) - { - return; - } - - cp = cp_payload_create(); - cp->set_config_type(cp, type); - ca = configuration_attribute_create(); - if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET) + if (vip->get_family(vip) == AF_INET) { ca->set_type(ca, INTERNAL_IP4_ADDRESS); - if (this->virtual_ip->is_anyaddr(this->virtual_ip)) + if (vip->is_anyaddr(vip)) { chunk = chunk_empty; } else { - chunk = this->virtual_ip->get_address(this->virtual_ip); + chunk = vip->get_address(vip); } } else { ca->set_type(ca, INTERNAL_IP6_ADDRESS); - if (this->virtual_ip->is_anyaddr(this->virtual_ip)) + if (vip->is_anyaddr(vip)) { chunk = chunk_empty; } @@ -105,71 +85,12 @@ static void build_payloads(private_ike_config_t *this, message_t *message, { prefix = chunk_alloca(1); *prefix.ptr = 64; - chunk = this->virtual_ip->get_address(this->virtual_ip); + chunk = vip->get_address(vip); chunk = chunk_cata("cc", chunk, prefix); } } ca->set_value(ca, chunk); cp->add_configuration_attribute(cp, ca); - - /* we currently always add a DNS request if we request an IP */ - if (this->initiator) - { - ca = configuration_attribute_create(); - if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET) - { - ca->set_type(ca, INTERNAL_IP4_DNS); - } - else - { - ca->set_type(ca, INTERNAL_IP6_DNS); - } - cp->add_configuration_attribute(cp, ca); - } - else - { - host_t *ip; - iterator_t *iterator; - - /* Add internal DNS servers */ - iterator = this->dns->create_iterator(this->dns, TRUE); - while (iterator->iterate(iterator, (void**)&ip)) - { - ca = configuration_attribute_create(); - if (ip->get_family(ip) == AF_INET) - { - ca->set_type(ca, INTERNAL_IP4_DNS); - } - else - { - ca->set_type(ca, INTERNAL_IP6_DNS); - } - chunk = ip->get_address(ip); - ca->set_value(ca, chunk); - cp->add_configuration_attribute(cp, ca); - } - iterator->destroy(iterator); - - /* Add internal WINS servers */ - iterator = this->nbns->create_iterator(this->nbns, TRUE); - while (iterator->iterate(iterator, (void**)&ip)) - { - ca = configuration_attribute_create(); - if (ip->get_family(ip) == AF_INET) - { - ca->set_type(ca, INTERNAL_IP4_NBNS); - } - else - { - ca->set_type(ca, INTERNAL_IP6_NBNS); - } - chunk = ip->get_address(ip); - ca->set_value(ca, chunk); - cp->add_configuration_attribute(cp, ca); - } - iterator->destroy(iterator); - } - message->add_payload(message, (payload_t*)cp); } /** @@ -203,55 +124,23 @@ static void process_attribute(private_ike_config_t *this, } ip = host_create_from_chunk(family, addr, 0); } - if (ip && !this->virtual_ip) - { - this->virtual_ip = ip; - } - break; - } - case INTERNAL_IP4_DNS: - family = AF_INET; - /* fall */ - case INTERNAL_IP6_DNS: - { - addr = ca->get_value(ca); - if (addr.len == 0) - { - ip = host_create_any(family); - } - else - { - ip = host_create_from_chunk(family, addr, 0); - } if (ip) { - this->dns->insert_last(this->dns, ip); + DESTROY_IF(this->virtual_ip); + this->virtual_ip = ip; } break; } - case INTERNAL_IP4_NBNS: - case INTERNAL_IP6_NBNS: - { - addr = ca->get_value(ca); - if (addr.len == 0) + default: + if (this->initiator) { - ip = host_create_any(family); + this->ike_sa->add_configuration_attribute(this->ike_sa, + ca->get_type(ca), ca->get_value(ca)); } else { - ip = host_create_from_chunk(family, addr, 0); + /* we do not handle attribute requests other than for VIPs */ } - if (ip) - { - this->nbns->insert_last(this->nbns, ip); - } - break; - } - default: - DBG1(DBG_IKE, "ignoring %N config attribute", - configuration_attribute_type_names, - ca->get_type(ca)); - break; } } @@ -313,12 +202,28 @@ static status_t build_i(private_ike_config_t *this, message_t *message) } if (vip) { - this->virtual_ip = vip->clone(vip); + configuration_attribute_t *ca; + cp_payload_t *cp; + + cp = cp_payload_create(); + cp->set_config_type(cp, CFG_REQUEST); + + build_vip(this, vip, cp); + + /* we currently always add a DNS request if we request an IP */ + ca = configuration_attribute_create(); + if (vip->get_family(vip) == AF_INET) + { + ca->set_type(ca, INTERNAL_IP4_DNS); + } + else + { + ca->set_type(ca, INTERNAL_IP6_DNS); + } + cp->add_configuration_attribute(cp, ca); + message->add_payload(message, (payload_t*)cp); } - - build_payloads(this, message, CFG_REQUEST); } - return NEED_MORE; } @@ -345,17 +250,22 @@ static status_t build_r(private_ike_config_t *this, message_t *message) if (config && this->virtual_ip) { - host_t *ip = NULL; + enumerator_t *enumerator; + configuration_attribute_type_t type; + configuration_attribute_t *ca; + chunk_t value; + cp_payload_t *cp; + host_t *vip = NULL; DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip); if (config->get_pool(config)) { - ip = charon->attributes->acquire_address(charon->attributes, + vip = charon->attributes->acquire_address(charon->attributes, config->get_pool(config), this->ike_sa->get_other_id(this->ike_sa), this->virtual_ip); } - if (ip == NULL) + if (vip == NULL) { DBG1(DBG_IKE, "no virtual IP found, sending %N", notify_type_names, INTERNAL_ADDRESS_FAILURE); @@ -363,13 +273,27 @@ static status_t build_r(private_ike_config_t *this, message_t *message) chunk_empty); return SUCCESS; } - DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip); - this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, ip); + DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip); + this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip); + + cp = cp_payload_create(); + cp->set_config_type(cp, CFG_REQUEST); - this->virtual_ip->destroy(this->virtual_ip); - this->virtual_ip = ip; + build_vip(this, vip, cp); - build_payloads(this, message, CFG_REPLY); + /* if we add an IP, we also look for other attributes */ + enumerator = charon->attributes->create_attribute_enumerator( + charon->attributes, this->ike_sa->get_other_id(this->ike_sa)); + while (enumerator->enumerate(enumerator, &type, &value)) + { + ca = configuration_attribute_create(); + ca->set_type(ca, type); + ca->set_value(ca, value); + cp->add_configuration_attribute(cp, ca); + } + enumerator->destroy(enumerator); + + message->add_payload(message, (payload_t*)cp); } return SUCCESS; } @@ -383,36 +307,12 @@ static status_t process_i(private_ike_config_t *this, message_t *message) { if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED) { /* in last IKE_AUTH exchange */ - host_t *ip; - peer_cfg_t *config; - DESTROY_IF(this->virtual_ip); - this->virtual_ip = NULL; - process_payloads(this, message); - if (this->virtual_ip == NULL) - { /* force a configured virtual IP, even if server didn't return one */ - config = this->ike_sa->get_peer_cfg(this->ike_sa); - this->virtual_ip = config->get_virtual_ip(config); - if (this->virtual_ip) - { - this->virtual_ip = this->virtual_ip->clone(this->virtual_ip); - } - } - - if (this->virtual_ip && !this->virtual_ip->is_anyaddr(this->virtual_ip)) + if (this->virtual_ip) { this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip); - - while (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS) - { - if (!ip->is_anyaddr(ip)) - { - this->ike_sa->add_dns_server(this->ike_sa, ip); - } - ip->destroy(ip); - } } return SUCCESS; } @@ -433,11 +333,9 @@ static task_type_t get_type(private_ike_config_t *this) static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa) { DESTROY_IF(this->virtual_ip); - this->dns->destroy_offset(this->dns, offsetof(host_t, destroy)); this->ike_sa = ike_sa; this->virtual_ip = NULL; - this->dns = linked_list_create(); } /** @@ -446,8 +344,6 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa) static void destroy(private_ike_config_t *this) { DESTROY_IF(this->virtual_ip); - this->dns->destroy_offset(this->dns, offsetof(host_t, destroy)); - this->nbns->destroy_offset(this->nbns, offsetof(host_t, destroy)); free(this); } @@ -457,7 +353,7 @@ static void destroy(private_ike_config_t *this) ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator) { private_ike_config_t *this = malloc_thing(private_ike_config_t); - + this->public.task.get_type = (task_type_t(*)(task_t*))get_type; this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; this->public.task.destroy = (void(*)(task_t*))destroy; @@ -465,9 +361,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator) this->initiator = initiator; this->ike_sa = ike_sa; this->virtual_ip = NULL; - this->dns = linked_list_create(); - this->nbns = linked_list_create(); - + if (initiator) { this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; @@ -475,49 +369,10 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator) } else { - int i; - - /* assign DNS servers */ - for (i = 1; i <= DNS_SERVER_MAX; i++) - { - char dns_key[16], *dns_str; - - snprintf(dns_key, sizeof(dns_key), "charon.dns%d", i); - dns_str = lib->settings->get_str(lib->settings, dns_key, NULL); - if (dns_str) - { - host_t *dns = host_create_from_string(dns_str, 0); - - if (dns) - { - DBG2(DBG_CFG, "assigning DNS server %H to peer", dns); - this->dns->insert_last(this->dns, dns); - } - } - } - - /* assign WINS servers */ - for (i = 1; i <= NBNS_SERVER_MAX; i++) - { - char nbns_key[16], *nbns_str; - - snprintf(nbns_key, sizeof(nbns_key), "charon.nbns%d", i); - nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL); - if (nbns_str) - { - host_t *nbns = host_create_from_string(nbns_str, 0); - - if (nbns) - { - DBG2(DBG_CFG, "assigning NBNS server %H to peer", nbns); - this->nbns->insert_last(this->nbns, nbns); - } - } - } - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; } - + return &this->public; } + |