From 270e425b2460989bdd9f9e7580ff98bc4d7861f6 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 14:41:12 +0200 Subject: [PATCH 01/43] Socket plugins soft depend on the kernel-ipsec plugin feature On most platforms calls to methods to bypass the IKE sockets and enabling UDP decapsulation are required. --- src/libcharon/plugins/socket_default/socket_default_plugin.c | 1 + src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcharon/plugins/socket_default/socket_default_plugin.c b/src/libcharon/plugins/socket_default/socket_default_plugin.c index 01d9473bf..e89b74279 100644 --- a/src/libcharon/plugins/socket_default/socket_default_plugin.c +++ b/src/libcharon/plugins/socket_default/socket_default_plugin.c @@ -52,6 +52,7 @@ METHOD(plugin_t, get_features, int, static plugin_feature_t f[] = { PLUGIN_CALLBACK(socket_register, socket_default_socket_create), PLUGIN_PROVIDE(CUSTOM, "socket"), + PLUGIN_SDEPEND(CUSTOM, "kernel-ipsec"), }; *features = f; return countof(f); diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c index c21d5240e..fdc9a7cf9 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c @@ -40,6 +40,7 @@ METHOD(plugin_t, get_features, int, static plugin_feature_t f[] = { PLUGIN_CALLBACK(socket_register, socket_dynamic_socket_create), PLUGIN_PROVIDE(CUSTOM, "socket"), + PLUGIN_SDEPEND(CUSTOM, "kernel-ipsec"), }; *features = f; return countof(f); From 8a6cc1e35f95d58ea72d2b07065d93d586e2d19c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 14:44:52 +0200 Subject: [PATCH 02/43] plugin-feature: Function added to exactly compare plugin features --- src/libstrongswan/plugins/plugin_feature.c | 51 +++++++++++++++++++++- src/libstrongswan/plugins/plugin_feature.h | 15 ++++++- src/libstrongswan/plugins/plugin_loader.c | 4 +- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c index 6c954f76d..1ee726a42 100644 --- a/src/libstrongswan/plugins/plugin_feature.c +++ b/src/libstrongswan/plugins/plugin_feature.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Hochschule fuer Technik Rapperswil * * Copyright (C) 2011 Martin Willi @@ -169,6 +169,55 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b) return FALSE; } +/** + * See header. + */ +bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b) +{ + if (a->type == b->type) + { + switch (a->type) + { + case FEATURE_NONE: + case FEATURE_CRYPTER: + case FEATURE_AEAD: + case FEATURE_SIGNER: + case FEATURE_HASHER: + case FEATURE_PRF: + case FEATURE_DH: + case FEATURE_NONCE_GEN: + case FEATURE_PRIVKEY: + case FEATURE_PRIVKEY_GEN: + case FEATURE_PUBKEY: + case FEATURE_PRIVKEY_SIGN: + case FEATURE_PUBKEY_VERIFY: + case FEATURE_PRIVKEY_DECRYPT: + case FEATURE_PUBKEY_ENCRYPT: + case FEATURE_CERT_DECODE: + case FEATURE_CERT_ENCODE: + case FEATURE_CONTAINER_DECODE: + case FEATURE_CONTAINER_ENCODE: + case FEATURE_EAP_SERVER: + case FEATURE_EAP_PEER: + case FEATURE_CUSTOM: + case FEATURE_XAUTH_SERVER: + case FEATURE_XAUTH_PEER: + return plugin_feature_matches(a, b); + case FEATURE_RNG: + return a->arg.rng_quality == b->arg.rng_quality; + case FEATURE_DATABASE: + return a->arg.database == b->arg.database; + case FEATURE_FETCHER: + if (a->arg.fetcher && b->arg.fetcher) + { + return streq(a->arg.fetcher, b->arg.fetcher); + } + return !a->arg.fetcher && !b->arg.fetcher; + } + } + return FALSE; +} + /** * See header. */ diff --git a/src/libstrongswan/plugins/plugin_feature.h b/src/libstrongswan/plugins/plugin_feature.h index 7667fff3e..0f29bf69e 100644 --- a/src/libstrongswan/plugins/plugin_feature.h +++ b/src/libstrongswan/plugins/plugin_feature.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Hochschule fuer Technik Rapperswil * * Copyright (C) 2011 Martin Willi @@ -340,12 +340,25 @@ u_int32_t plugin_feature_hash(plugin_feature_t *feature); /** * Check if feature a matches to feature b. * + * This is no check for equality. For instance, for FEATURE_RNG a matches b if + * a's strength is at least the strength of b. Or for FEATURE_SQL if a is + * DB_ANY it will match b if it is of the same type. + * * @param a feature to check * @param b feature to match against * @return TRUE if a matches b */ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b); +/** + * Check if feature a equals feature b. + * + * @param a feature + * @param b feature to compare + * @return TRUE if a equals b + */ +bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b); + /** * Get a string describing feature. * diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index cea219e92..109f78a86 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -179,7 +179,7 @@ static plugin_t *static_features_create(const char *name, /** * Compare function for hashtable of loaded features. */ -static bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b) +static bool plugin_feature_equals_ptr(plugin_feature_t *a, plugin_feature_t *b) { return a == b; } @@ -850,7 +850,7 @@ plugin_loader_t *plugin_loader_create() .plugins = linked_list_create(), .loaded_features = hashtable_create( (hashtable_hash_t)plugin_feature_hash, - (hashtable_equals_t)plugin_feature_equals, 64), + (hashtable_equals_t)plugin_feature_equals_ptr, 64), ); return &this->public; From 989ec772b53f14ac679ab856809042192fa523a8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 15:07:39 +0200 Subject: [PATCH 03/43] attr-sql: Use plugin features with dependency to database backend --- .../plugins/attr_sql/attr_sql_plugin.c | 77 +++++++++++++------ 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/src/libhydra/plugins/attr_sql/attr_sql_plugin.c b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c index 69e6f7be6..702872c57 100644 --- a/src/libhydra/plugins/attr_sql/attr_sql_plugin.c +++ b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -15,6 +16,7 @@ #include #include +#include #include "attr_sql_plugin.h" #include "sql_attribute.h" @@ -48,12 +50,59 @@ METHOD(plugin_t, get_name, char*, return "attr-sql"; } +/** + * Connect to database + */ +static bool open_database(private_attr_sql_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + char *uri; + + uri = lib->settings->get_str(lib->settings, + "libhydra.plugins.attr-sql.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "attr-sql plugin: database URI not set"); + return FALSE; + } + + this->db = lib->db->create(lib->db, uri); + if (!this->db) + { + DBG1(DBG_CFG, "attr-sql plugin failed to connect to database"); + return FALSE; + } + this->attribute = sql_attribute_create(this->db); + hydra->attributes->add_provider(hydra->attributes, + &this->attribute->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->attribute->provider); + this->attribute->destroy(this->attribute); + this->db->destroy(this->db); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_attr_sql_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)open_database, NULL), + PLUGIN_PROVIDE(CUSTOM, "attr-sql"), + PLUGIN_DEPENDS(DATABASE, DB_ANY), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_attr_sql_plugin_t *this) { - hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider); - this->attribute->destroy(this->attribute); - this->db->destroy(this->db); free(this); } @@ -63,36 +112,16 @@ METHOD(plugin_t, destroy, void, plugin_t *attr_sql_plugin_create() { private_attr_sql_plugin_t *this; - char *uri; - - uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", - NULL); - if (!uri) - { - DBG1(DBG_CFG, "attr-sql plugin: database URI not set"); - return NULL; - } INIT(this, .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .db = lib->db->create(lib->db, uri), ); - if (!this->db) - { - DBG1(DBG_CFG, "attr-sql plugin failed to connect to database"); - free(this); - return NULL; - } - this->attribute = sql_attribute_create(this->db); - hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider); - return &this->public.plugin; } - From 11a27ea28fdcc0130871b7e23c9ce0bf5689e125 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 15:14:52 +0200 Subject: [PATCH 04/43] sql: Use plugin features with dependency to database backend --- src/libcharon/plugins/sql/sql_plugin.c | 95 +++++++++++++++++--------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c index afbb89c83..c1b4461d2 100644 --- a/src/libcharon/plugins/sql/sql_plugin.c +++ b/src/libcharon/plugins/sql/sql_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -16,6 +17,8 @@ #include "sql_plugin.h" #include +#include + #include "sql_config.h" #include "sql_cred.h" #include "sql_logger.h" @@ -59,16 +62,67 @@ METHOD(plugin_t, get_name, char*, return "sql"; } +/** + * Connect to database + */ +static bool open_database(private_sql_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + char *uri; + + uri = lib->settings->get_str(lib->settings, "%s.plugins.sql.database", + NULL, charon->name); + if (!uri) + { + DBG1(DBG_CFG, "sql plugin: database URI not set"); + return FALSE; + } + + this->db = lib->db->create(lib->db, uri); + if (!this->db) + { + DBG1(DBG_CFG, "sql plugin failed to connect to database"); + return FALSE; + } + this->config = sql_config_create(this->db); + this->cred = sql_cred_create(this->db); + this->logger = sql_logger_create(this->db); + + charon->backends->add_backend(charon->backends, &this->config->backend); + lib->credmgr->add_set(lib->credmgr, &this->cred->set); + charon->bus->add_logger(charon->bus, &this->logger->logger); + } + else + { + charon->backends->remove_backend(charon->backends, + &this->config->backend); + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + charon->bus->remove_logger(charon->bus, &this->logger->logger); + this->config->destroy(this->config); + this->cred->destroy(this->cred); + this->logger->destroy(this->logger); + this->db->destroy(this->db); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_sql_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)open_database, NULL), + PLUGIN_PROVIDE(CUSTOM, "sql"), + PLUGIN_DEPENDS(DATABASE, DB_ANY), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_sql_plugin_t *this) { - charon->backends->remove_backend(charon->backends, &this->config->backend); - lib->credmgr->remove_set(lib->credmgr, &this->cred->set); - charon->bus->remove_logger(charon->bus, &this->logger->logger); - this->config->destroy(this->config); - this->cred->destroy(this->cred); - this->logger->destroy(this->logger); - this->db->destroy(this->db); free(this); } @@ -77,42 +131,17 @@ METHOD(plugin_t, destroy, void, */ plugin_t *sql_plugin_create() { - char *uri; private_sql_plugin_t *this; - uri = lib->settings->get_str(lib->settings, "%s.plugins.sql.database", - NULL, charon->name); - if (!uri) - { - DBG1(DBG_CFG, "sql plugin: database URI not set"); - return NULL; - } - INIT(this, .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .db = lib->db->create(lib->db, uri), ); - if (!this->db) - { - DBG1(DBG_CFG, "sql plugin failed to connect to database"); - free(this); - return NULL; - } - this->config = sql_config_create(this->db); - this->cred = sql_cred_create(this->db); - this->logger = sql_logger_create(this->db); - - charon->backends->add_backend(charon->backends, &this->config->backend); - lib->credmgr->add_set(lib->credmgr, &this->cred->set); - charon->bus->add_logger(charon->bus, &this->logger->logger); - return &this->public.plugin; } - From 12459a4dc8f6e7536d71f25c9d4febbb3031c1f3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 15:35:47 +0200 Subject: [PATCH 05/43] dhcp: Use plugin features with dependency to RNG implementation --- src/libcharon/plugins/dhcp/dhcp_plugin.c | 62 +++++++++++++++++------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/src/libcharon/plugins/dhcp/dhcp_plugin.c b/src/libcharon/plugins/dhcp/dhcp_plugin.c index f8782c2a4..a31f12689 100644 --- a/src/libcharon/plugins/dhcp/dhcp_plugin.c +++ b/src/libcharon/plugins/dhcp/dhcp_plugin.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -17,6 +20,7 @@ #include #include +#include #include "dhcp_socket.h" #include "dhcp_provider.h" @@ -50,13 +54,49 @@ METHOD(plugin_t, get_name, char*, return "dhcp"; } +/** + * Register listener + */ +static bool plugin_cb(private_dhcp_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + this->socket = dhcp_socket_create(); + + if (!this->socket) + { + return FALSE; + } + this->provider = dhcp_provider_create(this->socket); + hydra->attributes->add_provider(hydra->attributes, + &this->provider->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->provider->provider); + this->provider->destroy(this->provider); + this->socket->destroy(this->socket); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_dhcp_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "dhcp"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_dhcp_plugin_t *this) { - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); - this->provider->destroy(this->provider); - this->socket->destroy(this->socket); free(this); } @@ -71,23 +111,11 @@ plugin_t *dhcp_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .socket = dhcp_socket_create(), ); - if (!this->socket) - { - free(this); - return NULL; - } - - this->provider = dhcp_provider_create(this->socket); - hydra->attributes->add_provider(hydra->attributes, - &this->provider->provider); - return &this->public.plugin; } - From 94ca7252c13f86bd93d1c41427a949a4eabcacd7 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 15:45:02 +0200 Subject: [PATCH 06/43] addrblock: Use plugin features with soft dependency on X.509 decoding --- .../plugins/addrblock/addrblock_plugin.c | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/libcharon/plugins/addrblock/addrblock_plugin.c b/src/libcharon/plugins/addrblock/addrblock_plugin.c index 72c551f0f..723747d8e 100644 --- a/src/libcharon/plugins/addrblock/addrblock_plugin.c +++ b/src/libcharon/plugins/addrblock/addrblock_plugin.c @@ -16,6 +16,7 @@ #include "addrblock_plugin.h" #include +#include #include "addrblock_validator.h" #include "addrblock_narrow.h" @@ -49,11 +50,41 @@ METHOD(plugin_t, get_name, char*, return "addrblock"; } +/** + * Register listener + */ +static bool plugin_cb(private_addrblock_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + charon->bus->add_listener(charon->bus, &this->narrower->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->narrower->listener); + lib->credmgr->remove_validator(lib->credmgr, + &this->validator->validator); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_addrblock_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "addrblock"), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_addrblock_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->narrower->listener); - lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); this->narrower->destroy(this->narrower); this->validator->destroy(this->validator); free(this); @@ -70,15 +101,13 @@ plugin_t *addrblock_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .validator = addrblock_validator_create(), .narrower = addrblock_narrow_create(), ); - lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); - charon->bus->add_listener(charon->bus, &this->narrower->listener); return &this->public.plugin; } From 0c52198bc15d18a5d0632dfd5cfab604ee7f326c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 17:19:13 +0200 Subject: [PATCH 07/43] certexpire: Use plugin features to register listener --- .../plugins/certexpire/certexpire_plugin.c | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/libcharon/plugins/certexpire/certexpire_plugin.c b/src/libcharon/plugins/certexpire/certexpire_plugin.c index 2b4c0b68b..985fb0d76 100644 --- a/src/libcharon/plugins/certexpire/certexpire_plugin.c +++ b/src/libcharon/plugins/certexpire/certexpire_plugin.c @@ -49,10 +49,37 @@ METHOD(plugin_t, get_name, char*, return "certexpire"; } +/** + * Register listener + */ +static bool plugin_cb(private_certexpire_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_certexpire_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "certexpire"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_certexpire_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); this->export->destroy(this->export); free(this); @@ -69,14 +96,13 @@ plugin_t *certexpire_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .export = certexpire_export_create(), ); - this->listener = certexpire_listener_create(this->export), - charon->bus->add_listener(charon->bus, &this->listener->listener); + this->listener = certexpire_listener_create(this->export); return &this->public.plugin; } From 6c51ff745ca901fe4e8d550ba8c0a7257592681e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 17:37:13 +0200 Subject: [PATCH 08/43] coupling: Use plugin features and soft depend on SHA1 --- .../plugins/coupling/coupling_plugin.c | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/libcharon/plugins/coupling/coupling_plugin.c b/src/libcharon/plugins/coupling/coupling_plugin.c index 7ccc51db5..cd46ddd11 100644 --- a/src/libcharon/plugins/coupling/coupling_plugin.c +++ b/src/libcharon/plugins/coupling/coupling_plugin.c @@ -43,11 +43,48 @@ METHOD(plugin_t, get_name, char*, return "coupling"; } +/** + * Since the validator instantiates a hasher we create it as plugin feature. + * The default is SHA1 which we soft depend but depending on the plugin order + * there is no guarantee that the configured algorithm is registered. + */ +static bool plugin_cb(private_coupling_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + this->validator = coupling_validator_create(); + + if (!this->validator) + { + return FALSE; + } + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + } + else + { + lib->credmgr->remove_validator(lib->credmgr, + &this->validator->validator); + this->validator->destroy(this->validator); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_coupling_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "coupling"), + PLUGIN_SDEPEND(HASHER, HASH_SHA1), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_coupling_plugin_t *this) { - lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); - this->validator->destroy(this->validator); free(this); } @@ -62,20 +99,11 @@ plugin_t *coupling_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .validator = coupling_validator_create(), ); - if (!this->validator) - { - free(this); - return NULL; - } - - lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); - return &this->public.plugin; } From 57c29f68959a9d856784c32a6268b633fc1bec1d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 17:43:41 +0200 Subject: [PATCH 09/43] duplicheck: Use plugin features to register listener --- .../plugins/duplicheck/duplicheck_plugin.c | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c index 100ef0c2d..4d018dbef 100644 --- a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c +++ b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c @@ -49,10 +49,37 @@ METHOD(plugin_t, get_name, char*, return "duplicheck"; } +/** + * Register listener + */ +static bool plugin_cb(private_duplicheck_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_duplicheck_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "duplicheck"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_duplicheck_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->notify->destroy(this->notify); this->listener->destroy(this->listener); free(this); @@ -75,7 +102,7 @@ plugin_t *duplicheck_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -88,7 +115,6 @@ plugin_t *duplicheck_plugin_create() return NULL; } this->listener = duplicheck_listener_create(this->notify); - charon->bus->add_listener(charon->bus, &this->listener->listener); return &this->public.plugin; } From aa71f5f51593af99debbc791c92c914f42d141fa Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 17:46:43 +0200 Subject: [PATCH 10/43] error-notify: Use plugin features to register listener --- .../error_notify/error_notify_plugin.c | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/libcharon/plugins/error_notify/error_notify_plugin.c b/src/libcharon/plugins/error_notify/error_notify_plugin.c index f4f0647fb..a1e4351eb 100644 --- a/src/libcharon/plugins/error_notify/error_notify_plugin.c +++ b/src/libcharon/plugins/error_notify/error_notify_plugin.c @@ -49,10 +49,37 @@ METHOD(plugin_t, get_name, char*, return "error-notify"; } +/** + * Register listener + */ +static bool plugin_cb(private_error_notify_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_error_notify_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "error-notify"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_error_notify_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); this->socket->destroy(this->socket); free(this); @@ -69,7 +96,7 @@ plugin_t *error_notify_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -77,7 +104,6 @@ plugin_t *error_notify_plugin_create() ); this->listener = error_notify_listener_create(this->socket); - charon->bus->add_listener(charon->bus, &this->listener->listener); return &this->public.plugin; } From e5f4b3ca5bdc9f770fd8e1b0da03a056e9f0a0d2 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 17:50:12 +0200 Subject: [PATCH 11/43] farp: Use plugin features to register listener --- src/libcharon/plugins/farp/farp_plugin.c | 34 ++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/libcharon/plugins/farp/farp_plugin.c b/src/libcharon/plugins/farp/farp_plugin.c index a30c11962..cbc0bcf82 100644 --- a/src/libcharon/plugins/farp/farp_plugin.c +++ b/src/libcharon/plugins/farp/farp_plugin.c @@ -49,11 +49,38 @@ METHOD(plugin_t, get_name, char*, return "farp"; } +/** + * Register listener + */ +static bool plugin_cb(private_farp_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_farp_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "farp"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_farp_plugin_t *this) { DESTROY_IF(this->spoofer); - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); free(this); } @@ -69,15 +96,13 @@ plugin_t *farp_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .listener = farp_listener_create(), ); - charon->bus->add_listener(charon->bus, &this->listener->listener); - this->spoofer = farp_spoofer_create(this->listener); if (!this->spoofer) { @@ -86,4 +111,3 @@ plugin_t *farp_plugin_create() } return &this->public.plugin; } - From 924196d6d46d45f7fe7bc66161cf63a6c645fb01 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 17:58:12 +0200 Subject: [PATCH 12/43] ha: Use plugin features to register listeners and attribute provider --- src/libcharon/plugins/ha/ha_plugin.c | 46 ++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c index 255eeafc0..677985c57 100644 --- a/src/libcharon/plugins/ha/ha_plugin.c +++ b/src/libcharon/plugins/ha/ha_plugin.c @@ -97,14 +97,46 @@ METHOD(plugin_t, get_name, char*, return "ha"; } +/** + * Register listener + */ +static bool plugin_cb(private_ha_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->segments->listener); + charon->bus->add_listener(charon->bus, &this->ike->listener); + charon->bus->add_listener(charon->bus, &this->child->listener); + hydra->attributes->add_provider(hydra->attributes, + &this->attr->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->attr->provider); + charon->bus->remove_listener(charon->bus, &this->segments->listener); + charon->bus->remove_listener(charon->bus, &this->ike->listener); + charon->bus->remove_listener(charon->bus, &this->child->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_ha_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "ha"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_ha_plugin_t *this) { DESTROY_IF(this->ctl); - hydra->attributes->remove_provider(hydra->attributes, &this->attr->provider); - charon->bus->remove_listener(charon->bus, &this->segments->listener); - charon->bus->remove_listener(charon->bus, &this->ike->listener); - charon->bus->remove_listener(charon->bus, &this->child->listener); this->ike->destroy(this->ike); this->child->destroy(this->child); this->dispatcher->destroy(this->dispatcher); @@ -151,7 +183,7 @@ plugin_t *ha_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -182,10 +214,6 @@ plugin_t *ha_plugin_create() this->ike = ha_ike_create(this->socket, this->tunnel, this->cache); this->child = ha_child_create(this->socket, this->tunnel, this->segments, this->kernel); - charon->bus->add_listener(charon->bus, &this->segments->listener); - charon->bus->add_listener(charon->bus, &this->ike->listener); - charon->bus->add_listener(charon->bus, &this->child->listener); - hydra->attributes->add_provider(hydra->attributes, &this->attr->provider); return &this->public.plugin; } From f5bd1a5e09e43d81b6a2f0a3c7b501f0ee864796 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:11:46 +0200 Subject: [PATCH 13/43] plugin-feature: Add feature for DNSSEC-enabled resolvers --- src/libstrongswan/plugins/plugin_feature.c | 11 +++++++++++ src/libstrongswan/plugins/plugin_feature.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c index 1ee726a42..8a1958be5 100644 --- a/src/libstrongswan/plugins/plugin_feature.c +++ b/src/libstrongswan/plugins/plugin_feature.c @@ -50,6 +50,7 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM, "XAUTH_CLIENT", "DATABASE", "FETCHER", + "RESOLVER", "CUSTOM", ); @@ -67,6 +68,7 @@ u_int32_t plugin_feature_hash(plugin_feature_t *feature) case FEATURE_NONCE_GEN: case FEATURE_DATABASE: case FEATURE_FETCHER: + case FEATURE_RESOLVER: /* put these special cases in their (type-specific) buckets */ data = chunk_empty; break; @@ -133,6 +135,7 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b) case FEATURE_RNG: return a->arg.rng_quality <= b->arg.rng_quality; case FEATURE_NONCE_GEN: + case FEATURE_RESOLVER: return TRUE; case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: @@ -186,6 +189,7 @@ bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b) case FEATURE_PRF: case FEATURE_DH: case FEATURE_NONCE_GEN: + case FEATURE_RESOLVER: case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: case FEATURE_PUBKEY: @@ -285,6 +289,7 @@ char* plugin_feature_get_string(plugin_feature_t *feature) } break; case FEATURE_NONCE_GEN: + case FEATURE_RESOLVER: if (asprintf(&str, "%N", plugin_feature_names, feature->type) > 0) { return str; @@ -462,6 +467,9 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature, lib->fetcher->add_fetcher(lib->fetcher, reg->arg.reg.f, feature->arg.fetcher); break; + case FEATURE_RESOLVER: + lib->resolver->add_resolver(lib->resolver, reg->arg.reg.f); + break; default: break; } @@ -534,6 +542,9 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature, case FEATURE_FETCHER: lib->fetcher->remove_fetcher(lib->fetcher, reg->arg.reg.f); break; + case FEATURE_RESOLVER: + lib->resolver->remove_resolver(lib->resolver, reg->arg.reg.f); + break; default: break; } diff --git a/src/libstrongswan/plugins/plugin_feature.h b/src/libstrongswan/plugins/plugin_feature.h index 0f29bf69e..00deb38b0 100644 --- a/src/libstrongswan/plugins/plugin_feature.h +++ b/src/libstrongswan/plugins/plugin_feature.h @@ -150,6 +150,8 @@ struct plugin_feature_t { FEATURE_DATABASE, /** fetcher_t */ FEATURE_FETCHER, + /** resolver_t */ + FEATURE_RESOLVER, /** custom feature, described with a string */ FEATURE_CUSTOM, } type; @@ -294,6 +296,7 @@ struct plugin_feature_t { #define _PLUGIN_FEATURE_EAP_PEER(kind, type) __PLUGIN_FEATURE(kind, EAP_PEER, .eap = type) #define _PLUGIN_FEATURE_DATABASE(kind, type) __PLUGIN_FEATURE(kind, DATABASE, .database = type) #define _PLUGIN_FEATURE_FETCHER(kind, type) __PLUGIN_FEATURE(kind, FETCHER, .fetcher = type) +#define _PLUGIN_FEATURE_RESOLVER(kind, ...) __PLUGIN_FEATURE(kind, RESOLVER, .custom = NULL) #define _PLUGIN_FEATURE_CUSTOM(kind, name) __PLUGIN_FEATURE(kind, CUSTOM, .custom = name) #define _PLUGIN_FEATURE_XAUTH_SERVER(kind, name) __PLUGIN_FEATURE(kind, XAUTH_SERVER, .xauth = name) #define _PLUGIN_FEATURE_XAUTH_PEER(kind, name) __PLUGIN_FEATURE(kind, XAUTH_PEER, .xauth = name) @@ -317,6 +320,7 @@ struct plugin_feature_t { #define _PLUGIN_FEATURE_REGISTER_CONTAINER_ENCODE(type, f, final)__PLUGIN_FEATURE_REGISTER_BUILDER(type, f, final) #define _PLUGIN_FEATURE_REGISTER_DATABASE(type, f) __PLUGIN_FEATURE_REGISTER(type, f) #define _PLUGIN_FEATURE_REGISTER_FETCHER(type, f) __PLUGIN_FEATURE_REGISTER(type, f) +#define _PLUGIN_FEATURE_REGISTER_RESOLVER(type, f) __PLUGIN_FEATURE_REGISTER(type, f) #define _PLUGIN_FEATURE_CALLBACK(_cb, _data) (plugin_feature_t){ FEATURE_CALLBACK, FEATURE_NONE, .arg.cb = { .f = _cb, .data = _data } } From d895721489fd76a9bcc5ce96eeb5a5f1a409291c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:16:08 +0200 Subject: [PATCH 14/43] unbound: Use plugin features and provide RESOLVER --- .../plugins/unbound/unbound_plugin.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.c b/src/libstrongswan/plugins/unbound/unbound_plugin.c index 90b95330a..f727cdaae 100644 --- a/src/libstrongswan/plugins/unbound/unbound_plugin.c +++ b/src/libstrongswan/plugins/unbound/unbound_plugin.c @@ -37,10 +37,20 @@ METHOD(plugin_t, get_name, char*, return "unbound"; } +METHOD(plugin_t, get_features, int, + private_unbound_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_REGISTER(RESOLVER, unbound_resolver_create), + PLUGIN_PROVIDE(RESOLVER), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_unbound_plugin_t *this) { - lib->resolver->remove_resolver(lib->resolver, unbound_resolver_create); free(this); } @@ -55,12 +65,11 @@ plugin_t *unbound_plugin_create() .public = { .plugin = { .get_name = _get_name, + .get_features = _get_features, .destroy = _destroy, }, }, ); - lib->resolver->add_resolver(lib->resolver, unbound_resolver_create); - return &this->public.plugin; } From 82d3f5122bb3da6923b52e4320ab8cf982573773 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:22:41 +0200 Subject: [PATCH 15/43] ipseckey: Use plugin features and depend on RESOLVER Also fixed a double-free of the resolver instance. --- .../plugins/ipseckey/ipseckey_cred.h | 2 +- .../plugins/ipseckey/ipseckey_plugin.c | 79 ++++++++++++------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.h b/src/libcharon/plugins/ipseckey/ipseckey_cred.h index 440020f5d..f0f52fd6a 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_cred.h +++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.h @@ -49,7 +49,7 @@ struct ipseckey_cred_t { * Create an ipseckey_cred instance which uses the given resolver * to query the DNS for IPSECKEY resource records. * - * @param res resolver to use + * @param res resolver to use (gets adopted) * @return credential set */ ipseckey_cred_t *ipseckey_cred_create(resolver_t *res); diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c index 9593cf939..a62a9747e 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c +++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2012 Reto Guadagnini * Hochschule fuer Technik Rapperswil * @@ -31,11 +32,6 @@ struct private_ipseckey_plugin_t { */ ipseckey_plugin_t public; - /** - * DNS resolver instance - */ - resolver_t *res; - /** * credential set */ @@ -53,15 +49,59 @@ METHOD(plugin_t, get_name, char*, return "ipseckey"; } +/** + * Create resolver and register credential set + */ +static bool plugin_cb(private_ipseckey_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + resolver_t *res; + + res = lib->resolver->create(lib->resolver); + if (!res) + { + DBG1(DBG_CFG, "failed to create a DNS resolver instance"); + return FALSE; + } + + if (this->enabled) + { + this->cred = ipseckey_cred_create(res); + lib->credmgr->add_set(lib->credmgr, &this->cred->set); + } + else + { + res->destroy(res); + } + } + else + { + if (this->enabled) + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + this->cred->destroy(this->cred); + } + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_ipseckey_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "ipseckey"), + PLUGIN_DEPENDS(RESOLVER), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_ipseckey_plugin_t *this) { - if (this->enabled) - { - lib->credmgr->remove_set(lib->credmgr, &this->cred->set); - } - DESTROY_IF(this->res); - DESTROY_IF(this->cred); free(this); } @@ -76,28 +116,13 @@ plugin_t *ipseckey_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .res = lib->resolver->create(lib->resolver), .enabled = lib->settings->get_bool(lib->settings, "%s.plugins.ipseckey.enable", FALSE, charon->name), ); - if (!this->res) - { - DBG1(DBG_CFG, "failed to create a DNS resolver instance"); - destroy(this); - return NULL; - } - - if (this->enabled) - { - this->cred = ipseckey_cred_create(this->res); - lib->credmgr->add_set(lib->credmgr, &this->cred->set); - } - return &this->public.plugin; } - From 21d094f4022800bb560f3c26c53b62df492fb307 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:38:16 +0200 Subject: [PATCH 16/43] ipseckey: Allow en-/disabling at runtime using plugin reload feature --- .../plugins/ipseckey/ipseckey_plugin.c | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c index a62a9747e..2fd820f94 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c +++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c @@ -49,6 +49,28 @@ METHOD(plugin_t, get_name, char*, return "ipseckey"; } +METHOD(plugin_t, reload, bool, + private_ipseckey_plugin_t *this) +{ + bool enabled = lib->settings->get_bool(lib->settings, + "%s.plugins.ipseckey.enable", FALSE, charon->name); + + if (enabled != this->enabled) + { + if (enabled) + { + lib->credmgr->add_set(lib->credmgr, &this->cred->set); + } + else + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + } + this->enabled = enabled; + } + DBG1(DBG_CFG, "ipseckey plugin is %sabled", this->enabled ? "en" : "dis"); + return TRUE; +} + /** * Create resolver and register credential set */ @@ -66,23 +88,16 @@ static bool plugin_cb(private_ipseckey_plugin_t *this, return FALSE; } - if (this->enabled) - { - this->cred = ipseckey_cred_create(res); - lib->credmgr->add_set(lib->credmgr, &this->cred->set); - } - else - { - res->destroy(res); - } + this->cred = ipseckey_cred_create(res); + reload(this); } else { if (this->enabled) { lib->credmgr->remove_set(lib->credmgr, &this->cred->set); - this->cred->destroy(this->cred); } + this->cred->destroy(this->cred); } return TRUE; } @@ -117,11 +132,10 @@ plugin_t *ipseckey_plugin_create() .plugin = { .get_name = _get_name, .get_features = _get_features, + .reload = _reload, .destroy = _destroy, }, }, - .enabled = lib->settings->get_bool(lib->settings, - "%s.plugins.ipseckey.enable", FALSE, charon->name), ); return &this->public.plugin; From 44d5e10d9e1e2e80c19fd2917c9d2d99bf301b7d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:52:33 +0200 Subject: [PATCH 17/43] attr: Use plugin features to register attribute provider --- src/libhydra/plugins/attr/attr_plugin.c | 33 +++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/libhydra/plugins/attr/attr_plugin.c b/src/libhydra/plugins/attr/attr_plugin.c index cb14495af..7d719d0f8 100644 --- a/src/libhydra/plugins/attr/attr_plugin.c +++ b/src/libhydra/plugins/attr/attr_plugin.c @@ -42,6 +42,36 @@ METHOD(plugin_t, get_name, char*, return "attr"; } +/** + * Register provider + */ +static bool plugin_cb(private_attr_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + hydra->attributes->add_provider(hydra->attributes, + &this->provider->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->provider->provider); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_attr_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "attr"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, reload, bool, private_attr_plugin_t *this) { @@ -52,7 +82,6 @@ METHOD(plugin_t, reload, bool, METHOD(plugin_t, destroy, void, private_attr_plugin_t *this) { - hydra->attributes->remove_provider(hydra->attributes, &this->provider->provider); this->provider->destroy(this->provider); free(this); } @@ -68,13 +97,13 @@ plugin_t *attr_plugin_create() .public = { .plugin = { .get_name = _get_name, + .get_features = _get_features, .reload = _reload, .destroy = _destroy, }, }, .provider = attr_provider_create(), ); - hydra->attributes->add_provider(hydra->attributes, &this->provider->provider); return &this->public.plugin; } From 8f49a8d0a6a623156e231b606e76e48e6bf40a8a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:54:36 +0200 Subject: [PATCH 18/43] resolve: Use plugin features to register attribute handler --- src/libhydra/plugins/attr/attr_plugin.c | 1 - src/libhydra/plugins/resolve/resolve_plugin.c | 34 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/libhydra/plugins/attr/attr_plugin.c b/src/libhydra/plugins/attr/attr_plugin.c index 7d719d0f8..72fcd6dff 100644 --- a/src/libhydra/plugins/attr/attr_plugin.c +++ b/src/libhydra/plugins/attr/attr_plugin.c @@ -107,4 +107,3 @@ plugin_t *attr_plugin_create() return &this->public.plugin; } - diff --git a/src/libhydra/plugins/resolve/resolve_plugin.c b/src/libhydra/plugins/resolve/resolve_plugin.c index f95827ed9..2fef09a49 100644 --- a/src/libhydra/plugins/resolve/resolve_plugin.c +++ b/src/libhydra/plugins/resolve/resolve_plugin.c @@ -42,10 +42,39 @@ METHOD(plugin_t, get_name, char*, return "resolve"; } +/** + * Register handler + */ +static bool plugin_cb(private_resolve_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + hydra->attributes->add_handler(hydra->attributes, + &this->handler->handler); + } + else + { + hydra->attributes->remove_handler(hydra->attributes, + &this->handler->handler); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_resolve_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "resolve"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_resolve_plugin_t *this) { - hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); this->handler->destroy(this->handler); free(this); } @@ -61,13 +90,12 @@ plugin_t *resolve_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .handler = resolve_handler_create(), ); - hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); return &this->public.plugin; } From e3bdf03af4bc4a6ef59e7b891c58ba65dd1f0da0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 18:57:15 +0200 Subject: [PATCH 19/43] blowfish: Use plugin features to properly register crypter --- .../plugins/blowfish/blowfish_plugin.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libstrongswan/plugins/blowfish/blowfish_plugin.c b/src/libstrongswan/plugins/blowfish/blowfish_plugin.c index 9dc8dfe7f..7494c52c3 100644 --- a/src/libstrongswan/plugins/blowfish/blowfish_plugin.c +++ b/src/libstrongswan/plugins/blowfish/blowfish_plugin.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008 Martin Willi * Copyright (C) 2009 Andreas Steffen + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -38,11 +38,20 @@ METHOD(plugin_t, get_name, char*, return "blowfish"; } +METHOD(plugin_t, get_features, int, + private_blowfish_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_REGISTER(CRYPTER, blowfish_crypter_create), + PLUGIN_PROVIDE(CRYPTER, ENCR_BLOWFISH, 0), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_blowfish_plugin_t *this) { - lib->crypto->remove_crypter(lib->crypto, - (crypter_constructor_t)blowfish_crypter_create); free(this); } @@ -57,15 +66,11 @@ plugin_t *blowfish_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, get_name(this), - (crypter_constructor_t)blowfish_crypter_create); - return &this->public.plugin; } - From c172a92bfb60b1fe7cec1377315097d488d725cd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 19:01:40 +0200 Subject: [PATCH 20/43] constraints: Use plugin features with soft dependency on X.509 decoding --- .../plugins/constraints/constraints_plugin.c | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/plugins/constraints/constraints_plugin.c b/src/libstrongswan/plugins/constraints/constraints_plugin.c index 502c83559..b9b456b23 100644 --- a/src/libstrongswan/plugins/constraints/constraints_plugin.c +++ b/src/libstrongswan/plugins/constraints/constraints_plugin.c @@ -42,10 +42,39 @@ METHOD(plugin_t, get_name, char*, return "constraints"; } +/** + * Register validator + */ +static bool plugin_cb(private_constraints_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + } + else + { + lib->credmgr->remove_validator(lib->credmgr, + &this->validator->validator); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_constraints_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "constraints"), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_constraints_plugin_t *this) { - lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); this->validator->destroy(this->validator); free(this); } @@ -61,13 +90,12 @@ plugin_t *constraints_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .validator = constraints_validator_create(), ); - lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); return &this->public.plugin; } From 886a40d75ebeed8581d9337c7a5089cd41875a82 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 19:19:22 +0200 Subject: [PATCH 21/43] plugin-feature: Added helper function to extend arrays of plugin features --- src/libstrongswan/plugins/plugin_feature.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libstrongswan/plugins/plugin_feature.h b/src/libstrongswan/plugins/plugin_feature.h index 00deb38b0..ea23f766c 100644 --- a/src/libstrongswan/plugins/plugin_feature.h +++ b/src/libstrongswan/plugins/plugin_feature.h @@ -329,6 +329,27 @@ struct plugin_feature_t { */ extern enum_name_t *plugin_feature_names; +/** + * Add a set of plugin features to the given array, which must have enough space + * to store the added features. + * + * @param features the array of plugin features to extend + * @param to_add the features to add + * @param count number of features to add + * @param pos current position in the features array, gets advanced + */ +static inline void plugin_features_add(plugin_feature_t *features, + plugin_feature_t *to_add, + int count, int *pos) +{ + int i; + + for (i = 0; i < count; i++) + { + features[(*pos)++] = to_add[i]; + } +} + /** * Calculates a hash value for the given feature. * From 7756c0383ef64b5b55a452c84731a41ecc0f6078 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 19:22:26 +0200 Subject: [PATCH 22/43] pkcs11: Use plugin_features_add() in get_features() --- .../plugins/pkcs11/pkcs11_plugin.c | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c index 9afaf123a..3faa59cae 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c @@ -185,19 +185,6 @@ METHOD(plugin_t, reload, bool, return FALSE; } -/** - * Add a set of features - */ -static inline void add_features(plugin_feature_t *f, plugin_feature_t *n, - int count, int *pos) -{ - int i; - for (i = 0; i < count; i++) - { - f[(*pos)++] = n[i]; - } -} - METHOD(plugin_t, get_features, int, private_pkcs11_plugin_t *this, plugin_feature_t *features[]) { @@ -261,32 +248,32 @@ METHOD(plugin_t, get_features, int, { /* initialize only once */ bool use_ecc = lib->settings->get_bool(lib->settings, "libstrongswan.plugins.pkcs11.use_ecc", FALSE); - add_features(f, f_manager, countof(f_manager), &count); + plugin_features_add(f, f_manager, countof(f_manager), &count); /* private key handling for EC keys is not disabled by use_ecc */ - add_features(f, f_privkey, countof(f_privkey), &count); + plugin_features_add(f, f_privkey, countof(f_privkey), &count); if (lib->settings->get_bool(lib->settings, "libstrongswan.plugins.pkcs11.use_pubkey", FALSE)) { - add_features(f, f_pubkey, countof(f_pubkey) - (use_ecc ? 0 : 1), - &count); + plugin_features_add(f, f_pubkey, countof(f_pubkey) - (use_ecc ? 0 : 1), + &count); } if (lib->settings->get_bool(lib->settings, "libstrongswan.plugins.pkcs11.use_hasher", FALSE)) { - add_features(f, f_hash, countof(f_hash), &count); + plugin_features_add(f, f_hash, countof(f_hash), &count); } if (lib->settings->get_bool(lib->settings, "libstrongswan.plugins.pkcs11.use_rng", FALSE)) { - add_features(f, f_rng, countof(f_rng), &count); + plugin_features_add(f, f_rng, countof(f_rng), &count); } if (lib->settings->get_bool(lib->settings, "libstrongswan.plugins.pkcs11.use_dh", FALSE)) { - add_features(f, f_dh, countof(f_dh), &count); + plugin_features_add(f, f_dh, countof(f_dh), &count); if (use_ecc) { - add_features(f, f_ecdh, countof(f_ecdh), &count); + plugin_features_add(f, f_ecdh, countof(f_ecdh), &count); } } } From 25da1943b3ad3ae0549076790a2457275ef025c4 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 19:23:11 +0200 Subject: [PATCH 23/43] padlock: Use plugin features to properly register algorithms --- .../plugins/padlock/padlock_plugin.c | 82 ++++++++++--------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c index b887c2c84..2005ef648 100644 --- a/src/libstrongswan/plugins/padlock/padlock_plugin.c +++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -21,6 +22,7 @@ #include #include +#include #include typedef struct private_padlock_plugin_t private_padlock_plugin_t; @@ -107,28 +109,49 @@ METHOD(plugin_t, get_name, char*, return "padlock"; } +METHOD(plugin_t, get_features, int, + private_padlock_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f_rng[] = { + PLUGIN_REGISTER(RNG, padlock_rng_create), + PLUGIN_PROVIDE(RNG, RNG_WEAK), + PLUGIN_PROVIDE(RNG, RNG_STRONG), + PLUGIN_PROVIDE(RNG, RNG_TRUE), + }; + static plugin_feature_t f_aes[] = { + PLUGIN_REGISTER(CRYPTER, padlock_aes_crypter_create), + PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16), + }; + static plugin_feature_t f_sha1[] = { + PLUGIN_REGISTER(HASHER, padlock_sha1_hasher_create), + PLUGIN_PROVIDE(HASHER, HASH_SHA1), + }; + static plugin_feature_t f[countof(f_rng) + countof(f_aes) + + countof(f_sha1)] = {}; + static int count = 0; + + if (!count) + { /* initialize only once */ + if (this->features & PADLOCK_RNG_ENABLED) + { + plugin_features_add(f, f_rng, countof(f_rng), &count); + } + if (this->features & PADLOCK_ACE2_ENABLED) + { + plugin_features_add(f, f_aes, countof(f_aes), &count); + } + if (this->features & PADLOCK_PHE_ENABLED) + { + plugin_features_add(f, f_sha1, countof(f_sha1), &count); + } + } + *features = f; + return count; +} + METHOD(plugin_t, destroy, void, private_padlock_plugin_t *this) { - if (this->features & PADLOCK_RNG_ENABLED) - { - lib->crypto->remove_rng(lib->crypto, - (rng_constructor_t)padlock_rng_create); - lib->crypto->remove_rng(lib->crypto, - (rng_constructor_t)padlock_rng_create); - lib->crypto->remove_rng(lib->crypto, - (rng_constructor_t)padlock_rng_create); - } - if (this->features & PADLOCK_ACE2_ENABLED) - { - lib->crypto->remove_crypter(lib->crypto, - (crypter_constructor_t)padlock_aes_crypter_create); - } - if (this->features & PADLOCK_PHE_ENABLED) - { - lib->crypto->remove_hasher(lib->crypto, - (hasher_constructor_t)padlock_sha1_hasher_create); - } free(this); } @@ -143,7 +166,7 @@ plugin_t *padlock_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -167,24 +190,5 @@ plugin_t *padlock_plugin_create() this->features & PADLOCK_PHE_ENABLED ? " PHE" : "", this->features & PADLOCK_PMM_ENABLED ? " PMM" : ""); - if (this->features & PADLOCK_RNG_ENABLED) - { - lib->crypto->add_rng(lib->crypto, RNG_TRUE, get_name(this), - (rng_constructor_t)padlock_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_STRONG, get_name(this), - (rng_constructor_t)padlock_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_WEAK, get_name(this), - (rng_constructor_t)padlock_rng_create); - } - if (this->features & PADLOCK_ACE2_ENABLED) - { - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, get_name(this), - (crypter_constructor_t)padlock_aes_crypter_create); - } - if (this->features & PADLOCK_PHE_ENABLED) - { - lib->crypto->add_hasher(lib->crypto, HASH_SHA1, get_name(this), - (hasher_constructor_t)padlock_sha1_hasher_create); - } return &this->public.plugin; } From 17f00db6d67613428b5e9578942cf82d89640ece Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 19:31:51 +0200 Subject: [PATCH 24/43] revocation: Use plugin features with soft dependencies on fetcher and en-/decoding --- .../plugins/revocation/revocation_plugin.c | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/plugins/revocation/revocation_plugin.c b/src/libstrongswan/plugins/revocation/revocation_plugin.c index fa04fb2a2..fe7eaa765 100644 --- a/src/libstrongswan/plugins/revocation/revocation_plugin.c +++ b/src/libstrongswan/plugins/revocation/revocation_plugin.c @@ -42,10 +42,43 @@ METHOD(plugin_t, get_name, char*, return "revocation"; } +/** + * Register validator + */ +static bool plugin_cb(private_revocation_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + } + else + { + lib->credmgr->remove_validator(lib->credmgr, + &this->validator->validator); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_revocation_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "revocation"), + PLUGIN_SDEPEND(CERT_ENCODE, CERT_X509_OCSP_REQUEST), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509_OCSP_RESPONSE), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509_CRL), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), + PLUGIN_SDEPEND(FETCHER, NULL), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_revocation_plugin_t *this) { - lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); this->validator->destroy(this->validator); free(this); } @@ -61,13 +94,12 @@ plugin_t *revocation_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .validator = revocation_validator_create(), ); - lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); return &this->public.plugin; } From da0491493336dba838209d83aa56824f73cbd883 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 7 Jun 2013 19:35:24 +0200 Subject: [PATCH 25/43] test-vectors: Use plugin features --- .../plugins/test_vectors/test_vectors_plugin.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c index 4a8743289..cd0a12a5c 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c +++ b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c @@ -110,6 +110,17 @@ METHOD(plugin_t, get_name, char*, return "test-vectors"; } +METHOD(plugin_t, get_features, int, + private_test_vectors_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_NOOP, + PLUGIN_PROVIDE(CUSTOM, "test-vectors"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_test_vectors_plugin_t *this) { @@ -128,7 +139,7 @@ plugin_t *test_vectors_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, From dfe97d63d8de7e98a265ec8f9d038c044b8e1fba Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:18:00 +0200 Subject: [PATCH 26/43] led: Use plugin features to register listener --- src/libcharon/plugins/led/led_plugin.c | 33 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/libcharon/plugins/led/led_plugin.c b/src/libcharon/plugins/led/led_plugin.c index b6b69b466..9149fb263 100644 --- a/src/libcharon/plugins/led/led_plugin.c +++ b/src/libcharon/plugins/led/led_plugin.c @@ -43,10 +43,37 @@ METHOD(plugin_t, get_name, char*, return "led"; } +/** + * Register listener + */ +static bool plugin_cb(private_led_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_led_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "led"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_led_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); free(this); } @@ -62,14 +89,12 @@ plugin_t *led_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .listener = led_listener_create(), ); - charon->bus->add_listener(charon->bus, &this->listener->listener); - return &this->public.plugin; } From d94c0913b13b0603b433701d188ce71fb2d15776 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:22:23 +0200 Subject: [PATCH 27/43] lookip: Use plugin features to register listener --- src/libcharon/plugins/lookip/lookip_plugin.c | 33 +++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/libcharon/plugins/lookip/lookip_plugin.c b/src/libcharon/plugins/lookip/lookip_plugin.c index 360864849..319d72753 100644 --- a/src/libcharon/plugins/lookip/lookip_plugin.c +++ b/src/libcharon/plugins/lookip/lookip_plugin.c @@ -49,11 +49,38 @@ METHOD(plugin_t, get_name, char*, return "lookip"; } +/** + * Register listener + */ +static bool plugin_cb(private_lookip_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_lookip_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "lookip"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_lookip_plugin_t *this) { this->socket->destroy(this->socket); - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); free(this); } @@ -69,14 +96,12 @@ plugin_t *lookip_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .listener = lookip_listener_create(), ); - - charon->bus->add_listener(charon->bus, &this->listener->listener); this->socket = lookip_socket_create(this->listener); return &this->public.plugin; From 64b0c2575f3b1ee47c709ff37fbae9f4e9429230 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:25:37 +0200 Subject: [PATCH 28/43] radattr: Use plugin features to register listener --- .../plugins/radattr/radattr_plugin.c | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/libcharon/plugins/radattr/radattr_plugin.c b/src/libcharon/plugins/radattr/radattr_plugin.c index 85ea326ac..0400449ab 100644 --- a/src/libcharon/plugins/radattr/radattr_plugin.c +++ b/src/libcharon/plugins/radattr/radattr_plugin.c @@ -43,10 +43,37 @@ METHOD(plugin_t, get_name, char*, return "radattr"; } +/** + * Register listener + */ +static bool plugin_cb(private_radattr_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_radattr_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "radattr"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_radattr_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); free(this); } @@ -62,14 +89,12 @@ plugin_t *radattr_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .listener = radattr_listener_create(), ); - charon->bus->add_listener(charon->bus, &this->listener->listener); - return &this->public.plugin; } From c1f5841bb2de38aa0961eb8871967a3230fff07b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:29:09 +0200 Subject: [PATCH 29/43] smp: Use plugin features --- src/libcharon/plugins/smp/smp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index db5295230..ad5029d1c 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -712,6 +712,17 @@ METHOD(plugin_t, get_name, char*, return "smp"; } +METHOD(plugin_t, get_features, int, + private_smp_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_NOOP, + PLUGIN_PROVIDE(CUSTOM, "smp"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_smp_t *this) { @@ -732,7 +743,7 @@ plugin_t *smp_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -777,4 +788,3 @@ plugin_t *smp_plugin_create() return &this->public.plugin; } - From 36f27c1506782e8764edecd349ee67d1cbb34289 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:34:31 +0200 Subject: [PATCH 30/43] systime-fix: Use plugin features to register validator --- .../plugins/systime_fix/systime_fix_plugin.c | 77 +++++++++++++------ 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/src/libcharon/plugins/systime_fix/systime_fix_plugin.c b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c index 7727ba03b..c8596114c 100644 --- a/src/libcharon/plugins/systime_fix/systime_fix_plugin.c +++ b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2013 Martin Willi * Copyright (C) 2013 revosec AG * @@ -68,17 +71,6 @@ METHOD(plugin_t, get_name, char*, return "systime-fix"; } -METHOD(plugin_t, destroy, void, - private_systime_fix_plugin_t *this) -{ - if (this->validator) - { - lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); - this->validator->destroy(this->validator); - } - free(this); -} - /** * Check if all certificates associated to an IKE_SA have valid lifetimes */ @@ -215,11 +207,57 @@ static bool load_validator(private_systime_fix_plugin_t *this) DBG1(DBG_CFG, "enabling %s, threshold: %s", get_name(this), asctime(&tm)); this->validator = systime_fix_validator_create(this->threshold); - lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); - return TRUE; } +/** + * Load validator + */ +static bool plugin_cb(private_systime_fix_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + if (!load_validator(this)) + { + return FALSE; + } + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + if (this->interval != 0) + { + DBG1(DBG_CFG, "starting systime check, interval: %ds", + this->interval); + lib->scheduler->schedule_job(lib->scheduler, (job_t*) + callback_job_create((callback_job_cb_t)check_systime, + this, NULL, NULL), this->interval); + } + } + else + { + lib->credmgr->remove_validator(lib->credmgr, + &this->validator->validator); + this->validator->destroy(this->validator); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_systime_fix_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "systime-fix"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_systime_fix_plugin_t *this) +{ + free(this); +} + /** * Plugin constructor */ @@ -231,7 +269,7 @@ plugin_t *systime_fix_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -241,16 +279,5 @@ plugin_t *systime_fix_plugin_create() "%s.plugins.%s.reauth", FALSE, charon->name, get_name(this)), ); - if (load_validator(this)) - { - if (this->interval != 0) - { - DBG1(DBG_CFG, "starting systime check, interval: %ds", - this->interval); - lib->scheduler->schedule_job(lib->scheduler, (job_t*) - callback_job_create((callback_job_cb_t)check_systime, this, - NULL, NULL), this->interval); - } - } return &this->public.plugin; } From e1360331e997e412847cc556aef606318b852422 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:34:44 +0200 Subject: [PATCH 31/43] uci: Use plugin features to register backend and credential set --- src/libcharon/plugins/uci/uci_plugin.c | 39 +++++++++++++++++++++----- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/libcharon/plugins/uci/uci_plugin.c b/src/libcharon/plugins/uci/uci_plugin.c index 497c473a4..cc0836b7a 100644 --- a/src/libcharon/plugins/uci/uci_plugin.c +++ b/src/libcharon/plugins/uci/uci_plugin.c @@ -64,11 +64,40 @@ METHOD(plugin_t, get_name, char*, return "uci"; } +/** + * Register backend + */ +static bool plugin_cb(private_uci_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->backends->add_backend(charon->backends, &this->config->backend); + lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); + } + else + { + charon->backends->remove_backend(charon->backends, + &this->config->backend); + lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_uci_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "uci"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_uci_plugin_t *this) { - charon->backends->remove_backend(charon->backends, &this->config->backend); - lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set); this->config->destroy(this->config); this->creds->destroy(this->creds); this->parser->destroy(this->parser); @@ -87,7 +116,7 @@ plugin_t *uci_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -97,9 +126,5 @@ plugin_t *uci_plugin_create() this->config = uci_config_create(this->parser); this->creds = uci_creds_create(this->parser); - charon->backends->add_backend(charon->backends, &this->config->backend); - lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); - return &this->public.plugin; } - From b033d59d1ecb63a07f5d61b80f44c76ea038371c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:41:39 +0200 Subject: [PATCH 32/43] unit-tester: Use plugin features --- .../plugins/unit_tester/unit_tester.c | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/libcharon/plugins/unit_tester/unit_tester.c b/src/libcharon/plugins/unit_tester/unit_tester.c index ad7dba7a5..ea7ffca04 100644 --- a/src/libcharon/plugins/unit_tester/unit_tester.c +++ b/src/libcharon/plugins/unit_tester/unit_tester.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -98,6 +99,32 @@ METHOD(plugin_t, get_name, char*, return "unit-tester"; } +/** + * We currently don't depend explicitly on any plugin features. But in case + * activated tests depend on such features we at least try to run them in plugin + * order. + */ +static bool plugin_cb(private_unit_tester_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + run_tests(this); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_unit_tester_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "unit-tester"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_unit_tester_t *this) { @@ -115,14 +142,11 @@ plugin_t *unit_tester_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - run_tests(this); - return &this->public.plugin; } - From 819cb66298c8998661f0437cc67270373aeec83a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:44:56 +0200 Subject: [PATCH 33/43] unity: Use plugin features to register listener and attribute handler/provider --- src/libcharon/plugins/unity/unity_plugin.c | 49 +++++++++++++++++----- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/libcharon/plugins/unity/unity_plugin.c b/src/libcharon/plugins/unity/unity_plugin.c index 9e21bd9ed..9e4571d34 100644 --- a/src/libcharon/plugins/unity/unity_plugin.c +++ b/src/libcharon/plugins/unity/unity_plugin.c @@ -55,14 +55,47 @@ METHOD(plugin_t, get_name, char*, return "unity"; } +/** + * Register listener + */ +static bool plugin_cb(private_unity_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + hydra->attributes->add_handler(hydra->attributes, + &this->handler->handler); + hydra->attributes->add_provider(hydra->attributes, + &this->provider->provider); + charon->bus->add_listener(charon->bus, &this->narrower->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->narrower->listener); + hydra->attributes->remove_handler(hydra->attributes, + &this->handler->handler); + hydra->attributes->remove_provider(hydra->attributes, + &this->provider->provider); + + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_unity_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "unity"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_unity_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->narrower->listener); this->narrower->destroy(this->narrower); - hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); this->handler->destroy(this->handler); this->provider->destroy(this->provider); free(this); @@ -79,18 +112,14 @@ plugin_t *unity_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .handler = unity_handler_create(), .provider = unity_provider_create(), ); - hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); - hydra->attributes->add_provider(hydra->attributes, &this->provider->provider); - - this->narrower = unity_narrow_create(this->handler), - charon->bus->add_listener(charon->bus, &this->narrower->listener); + this->narrower = unity_narrow_create(this->handler); return &this->public.plugin; } From 49d333ac67c8f724b893a3c8ded32658a496bbcd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:47:38 +0200 Subject: [PATCH 34/43] updown: Use plugin features to register listener and attribute handler --- src/libcharon/plugins/updown/updown_plugin.c | 64 ++++++++++++++------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c index e1f0d1380..3c1aba5cc 100644 --- a/src/libcharon/plugins/updown/updown_plugin.c +++ b/src/libcharon/plugins/updown/updown_plugin.c @@ -49,17 +49,52 @@ METHOD(plugin_t, get_name, char*, return "updown"; } +/** + * Register listener + */ +static bool plugin_cb(private_updown_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + if (lib->settings->get_bool(lib->settings, + "charon.plugins.updown.dns_handler", FALSE)) + { + this->handler = updown_handler_create(); + hydra->attributes->add_handler(hydra->attributes, + &this->handler->handler); + } + this->listener = updown_listener_create(this->handler); + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->listener->destroy(this->listener); + if (this->handler) + { + this->handler->destroy(this->handler); + hydra->attributes->remove_handler(hydra->attributes, + &this->handler->handler); + } + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_updown_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "updown"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_updown_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); - this->listener->destroy(this->listener); - if (this->handler) - { - hydra->attributes->remove_handler(hydra->attributes, - &this->handler->handler); - this->handler->destroy(this->handler); - } free(this); } @@ -74,22 +109,11 @@ plugin_t *updown_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - if (lib->settings->get_bool(lib->settings, - "charon.plugins.updown.dns_handler", FALSE)) - { - this->handler = updown_handler_create(); - hydra->attributes->add_handler(hydra->attributes, - &this->handler->handler); - } - this->listener = updown_listener_create(this->handler); - charon->bus->add_listener(charon->bus, &this->listener->listener); - return &this->public.plugin; } - From d0ccae4dd217882dc9577235b7edc1fc12718049 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:55:42 +0200 Subject: [PATCH 35/43] whitelist: Use plugin features to register listener --- .../plugins/whitelist/whitelist_plugin.c | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/libcharon/plugins/whitelist/whitelist_plugin.c b/src/libcharon/plugins/whitelist/whitelist_plugin.c index fca9d293f..5ba3e1449 100644 --- a/src/libcharon/plugins/whitelist/whitelist_plugin.c +++ b/src/libcharon/plugins/whitelist/whitelist_plugin.c @@ -49,10 +49,37 @@ METHOD(plugin_t, get_name, char*, return "whitelist"; } +/** + * Register listener + */ +static bool plugin_cb(private_whitelist_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_whitelist_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "whitelist"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_whitelist_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); DESTROY_IF(this->control); free(this); @@ -69,7 +96,7 @@ plugin_t *whitelist_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -77,7 +104,5 @@ plugin_t *whitelist_plugin_create() ); this->control = whitelist_control_create(this->listener); - charon->bus->add_listener(charon->bus, &this->listener->listener); - return &this->public.plugin; } From da7c3f8900962a843f90b46235b4aa73799f6159 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 10:56:44 +0200 Subject: [PATCH 36/43] medcli: Use plugin features with dependency on database implementation --- src/libcharon/plugins/medcli/medcli_plugin.c | 95 ++++++++++++-------- 1 file changed, 60 insertions(+), 35 deletions(-) diff --git a/src/libcharon/plugins/medcli/medcli_plugin.c b/src/libcharon/plugins/medcli/medcli_plugin.c index 469915476..e6a8a8981 100644 --- a/src/libcharon/plugins/medcli/medcli_plugin.c +++ b/src/libcharon/plugins/medcli/medcli_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -60,16 +61,67 @@ METHOD(plugin_t, get_name, char*, return "medcli"; } +/** + * Connect to database + */ +static bool open_database(private_medcli_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + char *uri; + + uri = lib->settings->get_str(lib->settings, + "medcli.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "mediation client database URI not defined, skipped"); + return FALSE; + } + + this->db = lib->db->create(lib->db, uri); + if (this->db == NULL) + { + DBG1(DBG_CFG, "opening mediation client database failed"); + return FALSE; + } + + this->creds = medcli_creds_create(this->db); + this->config = medcli_config_create(this->db); + this->listener = medcli_listener_create(this->db); + + lib->credmgr->add_set(lib->credmgr, &this->creds->set); + charon->backends->add_backend(charon->backends, &this->config->backend); + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + charon->backends->remove_backend(charon->backends, &this->config->backend); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); + this->listener->destroy(this->listener); + this->config->destroy(this->config); + this->creds->destroy(this->creds); + this->db->destroy(this->db); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_medcli_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)open_database, NULL), + PLUGIN_PROVIDE(CUSTOM, "medcli"), + PLUGIN_DEPENDS(DATABASE, DB_ANY), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_medcli_plugin_t *this) { - charon->bus->remove_listener(charon->bus, &this->listener->listener); - charon->backends->remove_backend(charon->backends, &this->config->backend); - lib->credmgr->remove_set(lib->credmgr, &this->creds->set); - this->listener->destroy(this->listener); - this->config->destroy(this->config); - this->creds->destroy(this->creds); - this->db->destroy(this->db); free(this); } @@ -78,44 +130,17 @@ METHOD(plugin_t, destroy, void, */ plugin_t *medcli_plugin_create() { - char *uri; private_medcli_plugin_t *this; INIT(this, .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - uri = lib->settings->get_str(lib->settings, - "medcli.database", NULL); - if (!uri) - { - DBG1(DBG_CFG, "mediation client database URI not defined, skipped"); - free(this); - return NULL; - } - - this->db = lib->db->create(lib->db, uri); - if (this->db == NULL) - { - DBG1(DBG_CFG, "opening mediation client database failed"); - free(this); - return NULL; - } - - this->creds = medcli_creds_create(this->db); - this->config = medcli_config_create(this->db); - this->listener = medcli_listener_create(this->db); - - lib->credmgr->add_set(lib->credmgr, &this->creds->set); - charon->backends->add_backend(charon->backends, &this->config->backend); - charon->bus->add_listener(charon->bus, &this->listener->listener); - return &this->public.plugin; } - From 6d766925b23dfdf43b6ae899f29cfbb24fe6b565 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 11:00:48 +0200 Subject: [PATCH 37/43] medsrv: Use plugin features with dependency on database implementation --- src/libcharon/plugins/medsrv/medsrv_plugin.c | 87 +++++++++++++------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.c b/src/libcharon/plugins/medsrv/medsrv_plugin.c index 5df46d04f..fcc8502f8 100644 --- a/src/libcharon/plugins/medsrv/medsrv_plugin.c +++ b/src/libcharon/plugins/medsrv/medsrv_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -54,14 +55,63 @@ METHOD(plugin_t, get_name, char*, return "medsrv"; } +/** + * Connect to database + */ +static bool open_database(private_medsrv_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + char *uri; + + uri = lib->settings->get_str(lib->settings, + "medsrv.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "mediation database URI not defined, skipped"); + return FALSE; + } + + this->db = lib->db->create(lib->db, uri); + if (this->db == NULL) + { + DBG1(DBG_CFG, "opening mediation server database failed"); + return FALSE; + } + + this->creds = medsrv_creds_create(this->db); + this->config = medsrv_config_create(this->db); + + lib->credmgr->add_set(lib->credmgr, &this->creds->set); + charon->backends->add_backend(charon->backends, &this->config->backend); + } + else + { + charon->backends->remove_backend(charon->backends, &this->config->backend); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); + this->config->destroy(this->config); + this->creds->destroy(this->creds); + this->db->destroy(this->db); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_medsrv_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)open_database, NULL), + PLUGIN_PROVIDE(CUSTOM, "medsrv"), + PLUGIN_DEPENDS(DATABASE, DB_ANY), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_medsrv_plugin_t *this) { - charon->backends->remove_backend(charon->backends, &this->config->backend); - lib->credmgr->remove_set(lib->credmgr, &this->creds->set); - this->config->destroy(this->config); - this->creds->destroy(this->creds); - this->db->destroy(this->db); free(this); } @@ -70,42 +120,17 @@ METHOD(plugin_t, destroy, void, */ plugin_t *medsrv_plugin_create() { - char *uri; private_medsrv_plugin_t *this; INIT(this, .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - uri = lib->settings->get_str(lib->settings, - "medsrv.database", NULL); - if (!uri) - { - DBG1(DBG_CFG, "mediation database URI not defined, skipped"); - free(this); - return NULL; - } - - this->db = lib->db->create(lib->db, uri); - if (this->db == NULL) - { - DBG1(DBG_CFG, "opening mediation server database failed"); - free(this); - return NULL; - } - - this->creds = medsrv_creds_create(this->db); - this->config = medsrv_config_create(this->db); - - lib->credmgr->add_set(lib->credmgr, &this->creds->set); - charon->backends->add_backend(charon->backends, &this->config->backend); - return &this->public.plugin; } - From e183a6c36d7764173127aaeedb94d55dab49b851 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 11:02:26 +0200 Subject: [PATCH 38/43] maemo: Use plugin features --- src/libcharon/plugins/maemo/maemo_plugin.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libcharon/plugins/maemo/maemo_plugin.c b/src/libcharon/plugins/maemo/maemo_plugin.c index 38cb031b5..ddf9cdb5b 100644 --- a/src/libcharon/plugins/maemo/maemo_plugin.c +++ b/src/libcharon/plugins/maemo/maemo_plugin.c @@ -42,6 +42,17 @@ METHOD(plugin_t, get_name, char*, return "maemo"; } +METHOD(plugin_t, get_features, int, + private_maemo_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_NOOP, + PLUGIN_PROVIDE(CUSTOM, "maemo"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_maemo_plugin_t *this) { @@ -60,7 +71,7 @@ plugin_t *maemo_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -74,4 +85,3 @@ plugin_t *maemo_plugin_create() return &this->public.plugin; } - From df60999b5f9681920cb5b05543e7cae472c817df Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 11:03:42 +0200 Subject: [PATCH 39/43] android-dns: Use plugin features to register attribute handler --- .../plugins/android_dns/android_dns_plugin.c | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/libcharon/plugins/android_dns/android_dns_plugin.c b/src/libcharon/plugins/android_dns/android_dns_plugin.c index 4e2b5f58b..b8eb11b57 100644 --- a/src/libcharon/plugins/android_dns/android_dns_plugin.c +++ b/src/libcharon/plugins/android_dns/android_dns_plugin.c @@ -43,11 +43,39 @@ METHOD(plugin_t, get_name, char*, return "android-dns"; } +/** + * Register handler + */ +static bool plugin_cb(private_android_dns_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + hydra->attributes->add_handler(hydra->attributes, + &this->handler->handler); + } + else + { + hydra->attributes->remove_handler(hydra->attributes, + &this->handler->handler); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_android_dns_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "android-dns"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_android_dns_plugin_t *this) { - hydra->attributes->remove_handler(hydra->attributes, - &this->handler->handler); this->handler->destroy(this->handler); free(this); } @@ -63,14 +91,12 @@ plugin_t *android_dns_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .handler = android_dns_handler_create(), ); - hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); - return &this->public.plugin; } From facc7815004db80cb8fb386f100ab6076f24fda0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 11:05:02 +0200 Subject: [PATCH 40/43] android-log: Use plugin features --- .../plugins/android_log/android_log_plugin.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libcharon/plugins/android_log/android_log_plugin.c b/src/libcharon/plugins/android_log/android_log_plugin.c index 6757c2210..515917a22 100644 --- a/src/libcharon/plugins/android_log/android_log_plugin.c +++ b/src/libcharon/plugins/android_log/android_log_plugin.c @@ -43,6 +43,17 @@ METHOD(plugin_t, get_name, char*, return "android-log"; } +METHOD(plugin_t, get_features, int, + private_android_log_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_NOOP, + PLUGIN_PROVIDE(CUSTOM, "android-log"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_android_log_plugin_t *this) { @@ -62,7 +73,7 @@ plugin_t *android_log_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -73,4 +84,3 @@ plugin_t *android_log_plugin_create() return &this->public.plugin; } - From 49d7a98f471a449e45b77f2af3f7889c348781a0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 8 Jun 2013 15:46:33 +0200 Subject: [PATCH 41/43] Refactored plugin-loader with improved dependency resolution With the new implementation the plugins don't have to be listed in any special order, dependencies are properly resolved. The order only matters if two plugins provide the same feature. --- src/libcharon/plugins/stroke/stroke_list.c | 1 + src/libstrongswan/plugins/plugin_loader.c | 751 ++++++++++++++------- src/libstrongswan/plugins/plugin_loader.h | 8 +- 3 files changed, 501 insertions(+), 259 deletions(-) diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index a2e1c80a5..e76afec68 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -1364,6 +1364,7 @@ static void list_plugins(FILE *out) free(str); } } + list->destroy(list); } enumerator->destroy(enumerator); } diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index 109f78a86..0549b3728 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Tobias Brunner + * Copyright (C) 2010-2013 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -30,6 +30,8 @@ #include typedef struct private_plugin_loader_t private_plugin_loader_t; +typedef struct registered_feature_t registered_feature_t; +typedef struct provided_feature_t provided_feature_t; typedef struct plugin_entry_t plugin_entry_t; /** @@ -48,9 +50,14 @@ struct private_plugin_loader_t { linked_list_t *plugins; /** - * Hashtable for loaded features, as plugin_feature_t + * Hashtable for registered features, as registered_feature_t */ - hashtable_t *loaded_features; + hashtable_t *features; + + /** + * Loaded features (stored in reverse order), as provided_feature_t + */ + linked_list_t *loaded; /** * List of names of loaded plugins @@ -58,6 +65,80 @@ struct private_plugin_loader_t { char *loaded_plugins; }; +/** + * Registered plugin feature + */ +struct registered_feature_t { + + /** + * The registered feature + */ + plugin_feature_t *feature; + + /** + * List of plugins providing this feature, as provided_feature_t + */ + linked_list_t *plugins; +}; + +/** + * Hash a registered feature + */ +static bool registered_feature_hash(registered_feature_t *this) +{ + return plugin_feature_hash(this->feature); +} + +/** + * Compare two registered features + */ +static bool registered_feature_equals(registered_feature_t *a, + registered_feature_t *b) +{ + return plugin_feature_equals(a->feature, b->feature); +} + +/** + * Feature as provided by a plugin + */ +struct provided_feature_t { + + /** + * Plugin providing the feature + */ + plugin_entry_t *entry; + + /** + * FEATURE_REGISTER or FEATURE_CALLBACK entry + */ + plugin_feature_t *reg; + + /** + * The provided feature (followed by dependencies) + */ + plugin_feature_t *feature; + + /** + * Maximum number of dependencies (following feature) + */ + int dependencies; + + /** + * TRUE if currently loading this feature (to prevent loops) + */ + bool loading; + + /** + * TRUE if feature loaded + */ + bool loaded; + + /** + * TRUE if feature failed to load + */ + bool failed; +}; + /** * Entry for a plugin */ @@ -79,14 +160,9 @@ struct plugin_entry_t { void *handle; /** - * List of loaded features + * List of features, as provided_feature_t */ - linked_list_t *loaded; - - /** - * List features failed to load - */ - linked_list_t *failed; + linked_list_t *features; }; /** @@ -99,8 +175,7 @@ static void plugin_entry_destroy(plugin_entry_t *entry) { dlclose(entry->handle); } - entry->loaded->destroy(entry->loaded); - entry->failed->destroy(entry->failed); + entry->features->destroy(entry->features); free(entry); } @@ -176,14 +251,6 @@ static plugin_t *static_features_create(const char *name, return &this->public; } -/** - * Compare function for hashtable of loaded features. - */ -static bool plugin_feature_equals_ptr(plugin_feature_t *a, plugin_feature_t *b) -{ - return a == b; -} - /** * create a plugin * returns: NOT_FOUND, if the constructor was not found @@ -228,8 +295,7 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle, INIT(*entry, .plugin = plugin, .critical = critical, - .loaded = linked_list_create(), - .failed = linked_list_create(), + .features = linked_list_create(), ); DBG2(DBG_LIB, "plugin '%s': loaded successfully", name); return SUCCESS; @@ -238,8 +304,8 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle, /** * load a single plugin */ -static bool load_plugin(private_plugin_loader_t *this, char *name, char *file, - bool critical) +static plugin_entry_t *load_plugin(private_plugin_loader_t *this, char *name, + char *file, bool critical) { plugin_entry_t *entry; void *handle; @@ -248,7 +314,7 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file, { case SUCCESS: this->plugins->insert_last(this->plugins, entry); - return TRUE; + return entry; case NOT_FOUND: if (file) { /* try to load the plugin from a file */ @@ -256,7 +322,7 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file, } /* fall-through */ default: - return FALSE; + return NULL; } if (lib->integrity) { @@ -264,23 +330,33 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file, { DBG1(DBG_LIB, "plugin '%s': failed file integrity test of '%s'", name, file); - return FALSE; + return NULL; } } handle = dlopen(file, RTLD_LAZY); if (handle == NULL) { DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror()); - return FALSE; + return NULL; } if (create_plugin(this, handle, name, TRUE, critical, &entry) != SUCCESS) { dlclose(handle); - return FALSE; + return NULL; } entry->handle = handle; this->plugins->insert_last(this->plugins, entry); - return TRUE; + return entry; +} + +/** + * Convert enumerated provided_feature_t to plugin_feature_t + */ +static bool feature_filter(void *null, provided_feature_t **provided, + plugin_feature_t **feature) +{ + *feature = (*provided)->feature; + return (*provided)->loaded; } /** @@ -289,10 +365,16 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file, static bool plugin_filter(void *null, plugin_entry_t **entry, plugin_t **plugin, void *in, linked_list_t **list) { - *plugin = (*entry)->plugin; + plugin_entry_t *this = *entry; + + *plugin = this->plugin; if (list) { - *list = (*entry)->loaded; + enumerator_t *features; + features = enumerator_create_filter( + this->features->create_enumerator(this->features), + (void*)feature_filter, NULL, NULL); + *list = linked_list_create_from_enumerator(features); } return TRUE; } @@ -336,7 +418,6 @@ static char* loaded_plugins_list(private_plugin_loader_t *this) return buf; } - /** * Check if a plugin is already loaded */ @@ -360,59 +441,171 @@ static bool plugin_loaded(private_plugin_loader_t *this, char *name) } /** - * Check if a feature of a plugin is already loaded + * Forward declaration */ -static bool feature_loaded(private_plugin_loader_t *this, plugin_entry_t *entry, - plugin_feature_t *feature) +static void load_provided(private_plugin_loader_t *this, + provided_feature_t *provided, + int level); + +/** + * Used to find a loaded feature + */ +static bool is_feature_loaded(provided_feature_t *item) { - return entry->loaded->find_first(entry->loaded, NULL, - (void**)&feature) == SUCCESS; + return item->loaded; } /** - * Check if loading a feature of a plugin failed + * Used to find a loadable feature */ -static bool feature_failed(private_plugin_loader_t *this, plugin_entry_t *entry, - plugin_feature_t *feature) +static bool is_feature_loadable(provided_feature_t *item) { - return entry->failed->find_first(entry->failed, NULL, - (void**)&feature) == SUCCESS; + return !item->loading && !item->loaded && !item->failed; } /** - * Check if dependencies are satisfied + * Find a loaded and matching feature */ -static bool dependencies_satisfied(private_plugin_loader_t *this, - plugin_entry_t *entry, bool soft, bool report, - plugin_feature_t *features, int count) +static bool loaded_feature_matches(registered_feature_t *a, + registered_feature_t *b) { + if (plugin_feature_matches(a->feature, b->feature)) + { + return b->plugins->find_first(b->plugins, (void*)is_feature_loaded, + NULL) == SUCCESS; + } + return FALSE; +} + +/** + * Find a loadable module that equals the requested feature + */ +static bool loadable_feature_equals(registered_feature_t *a, + registered_feature_t *b) +{ + if (plugin_feature_equals(a->feature, b->feature)) + { + return b->plugins->find_first(b->plugins, (void*)is_feature_loadable, + NULL) == SUCCESS; + } + return FALSE; +} + +/** + * Find a loadable module that matches the requested feature + */ +static bool loadable_feature_matches(registered_feature_t *a, + registered_feature_t *b) +{ + if (plugin_feature_matches(a->feature, b->feature)) + { + return b->plugins->find_first(b->plugins, (void*)is_feature_loadable, + NULL) == SUCCESS; + } + return FALSE; +} + +/** + * Returns a compatible plugin feature for the given depencency + */ +static bool find_compatible_feature(private_plugin_loader_t *this, + plugin_feature_t *dependency) +{ + registered_feature_t *feature, lookup = { + .feature = dependency, + }; + + feature = this->features->get_match(this->features, &lookup, + (void*)loaded_feature_matches); + return feature != NULL; +} + +/** + * Load a registered plugin feature + */ +static void load_registered(private_plugin_loader_t *this, + registered_feature_t *registered, + int level) +{ + enumerator_t *enumerator; + provided_feature_t *provided; + + enumerator = registered->plugins->create_enumerator(registered->plugins); + while (enumerator->enumerate(enumerator, &provided)) + { + load_provided(this, provided, level); + } + enumerator->destroy(enumerator); +} + +/** + * Try to load dependencies of the given feature + */ +static bool load_dependencies(private_plugin_loader_t *this, + provided_feature_t *provided, + int level) +{ + registered_feature_t *registered, lookup; + int indent = level * 2; int i; /* first entry is provided feature, followed by dependencies */ - for (i = 1; i < count; i++) + for (i = 1; i < provided->dependencies; i++) { - plugin_feature_t *found; - - if (features[i].kind != FEATURE_DEPENDS && - features[i].kind != FEATURE_SDEPEND) + if (provided->feature[i].kind != FEATURE_DEPENDS && + provided->feature[i].kind != FEATURE_SDEPEND) { /* end of dependencies */ break; } - found = this->loaded_features->get_match(this->loaded_features, - &features[i], (hashtable_equals_t)plugin_feature_matches); - if (!found && (features[i].kind != FEATURE_SDEPEND || soft)) - { - if (report) - { - char *provide, *depend, *name; - name = entry->plugin->get_name(entry->plugin); - provide = plugin_feature_get_string(&features[0]); - depend = plugin_feature_get_string(&features[i]); - DBG2(DBG_LIB, "feature %s in '%s' plugin has unsatisfied " - "dependency: %s", provide, name, depend); - free(provide); - free(depend); + /* we load the feature even if a compatible one is already loaded, + * otherwise e.g. a specific database implementation loaded before + * another might cause a plugin feature loaded in-between to fail */ + lookup.feature = &provided->feature[i]; + do + { /* prefer an exactly matching feature, could be omitted but + * results in a more predictable behavior */ + registered = this->features->get_match(this->features, + &lookup, + (void*)loadable_feature_equals); + if (!registered) + { /* try fuzzy matching */ + registered = this->features->get_match(this->features, + &lookup, + (void*)loadable_feature_matches); + } + if (registered) + { + load_registered(this, registered, level); + } + /* we could stop after finding one but for dependencies like + * DB_ANY it might be needed to load all matching features */ + } + while (registered); + + if (!find_compatible_feature(this, &provided->feature[i])) + { + char *name, *provide, *depend; + bool soft = provided->feature[i].kind == FEATURE_SDEPEND; + + name = provided->entry->plugin->get_name(provided->entry->plugin); + provide = plugin_feature_get_string(&provided->feature[0]); + depend = plugin_feature_get_string(&provided->feature[i]); + if (soft) + { + DBG2(DBG_LIB, "%*sfeature %s in plugin '%s' has unmet soft " + "dependency: %s", indent, "", provide, name, depend); + } + else + { + DBG1(DBG_LIB, "feature %s in plugin '%s' has unmet dependency: " + "%s", provide, name, depend); + } + free(provide); + free(depend); + if (soft) + { /* it's ok if we can't resolve soft dependencies */ + continue; } return FALSE; } @@ -421,128 +614,133 @@ static bool dependencies_satisfied(private_plugin_loader_t *this, } /** - * Check if a given feature is still required as dependency + * Load registered plugin features */ -static bool dependency_required(private_plugin_loader_t *this, - plugin_feature_t *dep) +static void load_feature(private_plugin_loader_t *this, + provided_feature_t *provided, + int level) { - enumerator_t *enumerator; - plugin_feature_t *features; - plugin_entry_t *entry; + if (load_dependencies(this, provided, level)) + { + if (plugin_feature_load(provided->entry->plugin, provided->feature, + provided->reg)) + { + provided->loaded = TRUE; + /* insert first so we can unload the features in reverse order */ + this->loaded->insert_first(this->loaded, provided); + } + else + { + provided->failed = TRUE; + } + } + else + { /* TODO: we could check the current level and set a different flag when + * being loaded as dependency. If there are loops there is a chance the + * feature can be loaded later when loading the feature directly. */ + provided->failed = TRUE; + } +} + +/** + * Load a provided feature + */ +static void load_provided(private_plugin_loader_t *this, + provided_feature_t *provided, + int level) +{ + char *name, *provide; + int indent = level * 2; + + if (provided->loaded || provided->failed) + { + return; + } + name = provided->entry->plugin->get_name(provided->entry->plugin); + provide = plugin_feature_get_string(provided->feature); + if (provided->loading) + { /* prevent loop */ + DBG2(DBG_LIB, "%*sloop detected while loading %s in plugin '%s'", + indent, "", provide, name); + free(provide); + return; + } + DBG2(DBG_LIB, "%*sloading feature %s in plugin '%s'", + indent, "", provide, name); + free(provide); + + provided->loading = TRUE; + load_feature(this, provided, level + 1); + provided->loading = FALSE; +} + +/** + * Load registered plugin features + */ +static void load_features(private_plugin_loader_t *this) +{ + enumerator_t *enumerator, *inner; + plugin_entry_t *plugin; + provided_feature_t *provided; + + /* we do this in plugin order to allow implicit dependencies to be resolved + * by reordering plugins */ + enumerator = this->plugins->create_enumerator(this->plugins); + while (enumerator->enumerate(enumerator, &plugin)) + { + inner = plugin->features->create_enumerator(plugin->features); + while (inner->enumerate(inner, &provided)) + { + load_provided(this, provided, 0); + } + inner->destroy(inner); + } + enumerator->destroy(enumerator); +} + +/** + * Register plugin features provided by the given plugin + */ +static void register_features(private_plugin_loader_t *this, + plugin_entry_t *entry) +{ + plugin_feature_t *feature, *reg; + registered_feature_t *registered, lookup; + provided_feature_t *provided; int count, i; - enumerator = this->plugins->create_enumerator(this->plugins); - while (enumerator->enumerate(enumerator, &entry)) - { - if (!entry->plugin->get_features) - { /* features not supported */ - continue; - } - count = entry->plugin->get_features(entry->plugin, &features); - for (i = 0; i < count; i++) - { - if (&features[i] != dep && - feature_loaded(this, entry, &features[i])) - { - while (++i < count && (features[i].kind == FEATURE_DEPENDS || - features[i].kind == FEATURE_SDEPEND)) - { - if (plugin_feature_matches(&features[i], dep)) - { - enumerator->destroy(enumerator); - return TRUE; - } - } - } - } + if (!entry->plugin->get_features) + { /* feature interface not supported */ + DBG1(DBG_LIB, "plugin '%s' does not provide features, deprecated", + entry->plugin->get_name(entry->plugin)); + return; } - enumerator->destroy(enumerator); - return FALSE; -} - -/** - * Load plugin features in correct order - */ -static int load_features(private_plugin_loader_t *this, bool soft, bool report) -{ - enumerator_t *enumerator; - plugin_feature_t *feature, *reg; - plugin_entry_t *entry; - int count, i, loaded = 0; - - enumerator = this->plugins->create_enumerator(this->plugins); - while (enumerator->enumerate(enumerator, &entry)) - { - if (!entry->plugin->get_features) - { /* feature interface not supported */ - continue; - } - reg = NULL; - count = entry->plugin->get_features(entry->plugin, &feature); - for (i = 0; i < count; i++) - { - switch (feature->kind) - { - case FEATURE_PROVIDE: - if (!feature_loaded(this, entry, feature) && - !feature_failed(this, entry, feature) && - dependencies_satisfied(this, entry, soft, report, - feature, count - i)) - { - if (plugin_feature_load(entry->plugin, feature, reg)) - { - this->loaded_features->put(this->loaded_features, - feature, feature); - entry->loaded->insert_last(entry->loaded, feature); - loaded++; - } - else - { - entry->failed->insert_last(entry->failed, feature); - } - } - break; - case FEATURE_REGISTER: - case FEATURE_CALLBACK: - reg = feature; - break; - default: - break; - } - feature++; - } - if (loaded && !report) - { /* got new feature, restart from beginning of list */ - break; - } - } - enumerator->destroy(enumerator); - return loaded; -} - -/** - * Try to unload plugin features on which is not depended anymore - */ -static int unload_features(private_plugin_loader_t *this, plugin_entry_t *entry) -{ - plugin_feature_t *feature, *reg = NULL; - int count, i, unloaded = 0; - + reg = NULL; count = entry->plugin->get_features(entry->plugin, &feature); for (i = 0; i < count; i++) { switch (feature->kind) { case FEATURE_PROVIDE: - if (feature_loaded(this, entry, feature) && - !dependency_required(this, feature) && - plugin_feature_unload(entry->plugin, feature, reg)) + lookup.feature = feature; + registered = this->features->get(this->features, &lookup); + if (!registered) { - this->loaded_features->remove(this->loaded_features, - feature); - entry->loaded->remove(entry->loaded, feature, NULL); - unloaded++; + INIT(registered, + .feature = feature, + .plugins = linked_list_create(), + ); + this->features->put(this->features, registered, registered); } + INIT(provided, + .entry = entry, + .feature = feature, + .reg = reg, + .dependencies = count - i, + ); + registered->plugins->insert_last(registered->plugins, + provided); + entry->features->insert_last(entry->features, provided); break; case FEATURE_REGISTER: case FEATURE_CALLBACK: @@ -553,7 +751,54 @@ static int unload_features(private_plugin_loader_t *this, plugin_entry_t *entry) } feature++; } - return unloaded; +} + +/** + * Unregister a plugin feature + */ +static void unregister_feature(private_plugin_loader_t *this, + provided_feature_t *provided) +{ + registered_feature_t *registered, lookup; + + lookup.feature = provided->feature; + registered = this->features->get(this->features, &lookup); + if (registered) + { + registered->plugins->remove(registered->plugins, provided, NULL); + if (registered->plugins->get_count(registered->plugins) == 0) + { + this->features->remove(this->features, &lookup); + registered->plugins->destroy(registered->plugins); + free(registered); + } + else if (registered->feature == provided->feature) + { /* update feature in case the providing plugin gets unloaded */ + provided_feature_t *first; + + registered->plugins->get_first(registered->plugins, (void**)&first); + registered->feature = first->feature; + } + } + free(provided); +} + +/** + * Unregister plugin features + */ +static void unregister_features(private_plugin_loader_t *this, + plugin_entry_t *entry) +{ + provided_feature_t *provided; + enumerator_t *enumerator; + + enumerator = entry->features->create_enumerator(entry->features); + while (enumerator->enumerate(enumerator, &provided)) + { + entry->features->remove_at(entry->features, enumerator); + unregister_feature(this, provided); + } + enumerator->destroy(enumerator); } /** @@ -561,44 +806,43 @@ static int unload_features(private_plugin_loader_t *this, plugin_entry_t *entry) */ static bool missing_critical_features(private_plugin_loader_t *this) { - enumerator_t *enumerator; + enumerator_t *enumerator, *features; plugin_entry_t *entry; bool critical_failed = FALSE; enumerator = this->plugins->create_enumerator(this->plugins); while (enumerator->enumerate(enumerator, &entry)) { - if (!entry->plugin->get_features) - { /* feature interface not supported */ + provided_feature_t *provided; + char *name, *provide; + int failed = 0; + + if (!entry->plugin->get_features || + !entry->critical) + { /* feature interface not supported, or not critical */ continue; } - if (entry->critical) - { - plugin_feature_t *feature; - char *name, *provide; - int count, i, failed = 0; - name = entry->plugin->get_name(entry->plugin); - count = entry->plugin->get_features(entry->plugin, &feature); - for (i = 0; i < count; i++, feature++) + name = entry->plugin->get_name(entry->plugin); + features = entry->features->create_enumerator(entry->features); + while (features->enumerate(features, &provided)) + { + if (!provided->loaded) { - if (feature->kind == FEATURE_PROVIDE && - !feature_loaded(this, entry, feature)) - { - provide = plugin_feature_get_string(feature); - DBG2(DBG_LIB, " failed to load %s in critical plugin '%s'", - provide, name); - free(provide); - failed++; - } - } - if (failed) - { - DBG1(DBG_LIB, "failed to load %d feature%s in critical plugin " - "'%s'", failed, failed > 1 ? "s" : "", name); - critical_failed = TRUE; + provide = plugin_feature_get_string(provided->feature); + DBG2(DBG_LIB, " failed to load %s in critical plugin '%s'", + provide, name); + free(provide); + failed++; } } + features->destroy(features); + if (failed) + { + DBG1(DBG_LIB, "failed to load %d feature%s in critical plugin '%s'", + failed, failed > 1 ? "s" : "", name); + critical_failed = TRUE; + } } enumerator->destroy(enumerator); @@ -606,7 +850,7 @@ static bool missing_critical_features(private_plugin_loader_t *this) } /** - * Remove plugins that we were not able to load any features from. + * Remove plugins we were not able to load any plugin features from. */ static void purge_plugins(private_plugin_loader_t *this) { @@ -620,9 +864,13 @@ static void purge_plugins(private_plugin_loader_t *this) { /* feature interface not supported */ continue; } - if (!entry->loaded->get_count(entry->loaded)) + if (entry->features->find_first(entry->features, + (void*)is_feature_loaded, NULL) != SUCCESS) { + DBG2(DBG_LIB, "unloading plugin '%s' without loaded features", + entry->plugin->get_name(entry->plugin)); this->plugins->remove_at(this->plugins, enumerator); + unregister_features(this, entry); plugin_entry_destroy(entry); } } @@ -641,10 +889,10 @@ METHOD(plugin_loader_t, add_static_features, void, INIT(entry, .plugin = plugin, .critical = critical, - .loaded = linked_list_create(), - .failed = linked_list_create(), + .features = linked_list_create(), ); this->plugins->insert_last(this->plugins, entry); + register_features(this, entry); } METHOD(plugin_loader_t, load_plugins, bool, @@ -664,6 +912,7 @@ METHOD(plugin_loader_t, load_plugins, bool, enumerator = enumerator_create_token(list, " ", " "); while (!critical_failed && enumerator->enumerate(enumerator, &token)) { + plugin_entry_t *entry; bool critical = FALSE; char buf[PATH_MAX], *file = NULL; int len; @@ -689,29 +938,22 @@ METHOD(plugin_loader_t, load_plugins, bool, } file = buf; } - if (!load_plugin(this, token, file, critical) && critical) + entry = load_plugin(this, token, file, critical); + if (entry) + { + register_features(this, entry); + } + else if (critical) { critical_failed = TRUE; DBG1(DBG_LIB, "loading critical plugin '%s' failed", token); } free(token); - /* TODO: we currently load features after each plugin is loaded. This - * will not be necessary once we have features support in all plugins. - */ - while (load_features(this, TRUE, FALSE)) - { - /* try load new features until we don't get new ones */ - } } enumerator->destroy(enumerator); if (!critical_failed) { - while (load_features(this, FALSE, FALSE)) - { - /* enforce loading features, ignoring soft dependencies */ - } - /* report missing dependencies */ - load_features(this, FALSE, TRUE); + load_features(this); /* check for unloaded features provided by critical plugins */ critical_failed = missing_critical_features(this); /* unload plugins that we were not able to load any features for */ @@ -725,44 +967,42 @@ METHOD(plugin_loader_t, load_plugins, bool, return !critical_failed; } +/** + * Unload plugin features, they are registered in reverse order + */ +static void unload_features(private_plugin_loader_t *this) +{ + enumerator_t *enumerator; + provided_feature_t *provided; + plugin_entry_t *entry; + + enumerator = this->loaded->create_enumerator(this->loaded); + while (enumerator->enumerate(enumerator, &provided)) + { + entry = provided->entry; + plugin_feature_unload(entry->plugin, provided->feature, provided->reg); + this->loaded->remove_at(this->loaded, enumerator); + entry->features->remove(entry->features, provided, NULL); + unregister_feature(this, provided); + } + enumerator->destroy(enumerator); +} + METHOD(plugin_loader_t, unload, void, private_plugin_loader_t *this) { - enumerator_t *enumerator; plugin_entry_t *entry; - linked_list_t *list; - /* unload plugins in reverse order, for those not supporting features */ - list = linked_list_create(); + /* unload features followed by plugins, in reverse order */ + unload_features(this); while (this->plugins->remove_last(this->plugins, (void**)&entry) == SUCCESS) { - list->insert_last(list, entry); - } - while (list->remove_last(list, (void**)&entry) == SUCCESS) - { - this->plugins->insert_first(this->plugins, entry); - } - list->destroy(list); - while (this->plugins->get_count(this->plugins)) - { - enumerator = this->plugins->create_enumerator(this->plugins); - while (enumerator->enumerate(enumerator, &entry)) - { - if (entry->plugin->get_features) - { /* supports features */ - while (unload_features(this, entry)); - } - if (entry->loaded->get_count(entry->loaded) == 0) - { - if (lib->leak_detective) - { /* keep handle to report leaks properly */ - entry->handle = NULL; - } - this->plugins->remove_at(this->plugins, enumerator); - plugin_entry_destroy(entry); - } + if (lib->leak_detective) + { /* keep handle to report leaks properly */ + entry->handle = NULL; } - enumerator->destroy(enumerator); + unregister_features(this, entry); + plugin_entry_destroy(entry); } free(this->loaded_plugins); this->loaded_plugins = NULL; @@ -824,7 +1064,8 @@ METHOD(plugin_loader_t, destroy, void, private_plugin_loader_t *this) { unload(this); - this->loaded_features->destroy(this->loaded_features); + this->features->destroy(this->features); + this->loaded->destroy(this->loaded); this->plugins->destroy(this->plugins); free(this->loaded_plugins); free(this); @@ -848,11 +1089,11 @@ plugin_loader_t *plugin_loader_create() .destroy = _destroy, }, .plugins = linked_list_create(), - .loaded_features = hashtable_create( - (hashtable_hash_t)plugin_feature_hash, - (hashtable_equals_t)plugin_feature_equals_ptr, 64), + .loaded = linked_list_create(), + .features = hashtable_create( + (hashtable_hash_t)registered_feature_hash, + (hashtable_equals_t)registered_feature_equals, 64), ); return &this->public; } - diff --git a/src/libstrongswan/plugins/plugin_loader.h b/src/libstrongswan/plugins/plugin_loader.h index 6a8f8f6a1..857bb2d9d 100644 --- a/src/libstrongswan/plugins/plugin_loader.h +++ b/src/libstrongswan/plugins/plugin_loader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -84,9 +84,9 @@ struct plugin_loader_t { /** * Create an enumerator over all loaded plugins. * - * In addition to the plugin, the enumerator returns a list of pointers to - * plugin features currently loaded (if the argument is not NULL). - * This list is to be read only. + * In addition to the plugin, the enumerator optionally provides a list of + * pointers to plugin features currently loaded. + * This list has to be destroyed. * * @return enumerator over plugin_t*, linked_list_t* */ From 460488b180226a76f10561dae82856c88384c420 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 10 Jun 2013 18:15:40 +0200 Subject: [PATCH 42/43] eap-radius: Do initialization in a plugin feature callback --- .../plugins/eap_radius/eap_radius_plugin.c | 75 ++++++++++++------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index e186cb0fe..63592db06 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2009 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -186,12 +187,57 @@ METHOD(plugin_t, get_name, char*, return "eap-radius"; } +/** + * Register listener + */ +static bool plugin_cb(private_eap_radius_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + this->accounting = eap_radius_accounting_create(); + this->forward = eap_radius_forward_create(); + this->provider = eap_radius_provider_create(); + + load_configs(this); + + if (lib->settings->get_bool(lib->settings, + "%s.plugins.eap-radius.dae.enable", FALSE, charon->name)) + { + this->dae = eap_radius_dae_create(this->accounting); + } + if (this->forward) + { + charon->bus->add_listener(charon->bus, &this->forward->listener); + } + hydra->attributes->add_provider(hydra->attributes, + &this->provider->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->provider->provider); + if (this->forward) + { + charon->bus->remove_listener(charon->bus, &this->forward->listener); + this->forward->destroy(this->forward); + } + DESTROY_IF(this->dae); + this->provider->destroy(this->provider); + this->accounting->destroy(this->accounting); + } + return TRUE; +} + METHOD(plugin_t, get_features, int, - eap_radius_plugin_t *this, plugin_feature_t *features[]) + private_eap_radius_plugin_t *this, plugin_feature_t *features[]) { static plugin_feature_t f[] = { PLUGIN_CALLBACK(eap_method_register, eap_radius_create), PLUGIN_PROVIDE(EAP_SERVER, EAP_RADIUS), + PLUGIN_DEPENDS(CUSTOM, "eap-radius"), + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "eap-radius"), PLUGIN_DEPENDS(HASHER, HASH_MD5), PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_MD5_128), PLUGIN_DEPENDS(RNG, RNG_WEAK), @@ -215,19 +261,9 @@ METHOD(plugin_t, reload, bool, METHOD(plugin_t, destroy, void, private_eap_radius_plugin_t *this) { - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); - this->provider->destroy(this->provider); - if (this->forward) - { - charon->bus->remove_listener(charon->bus, &this->forward->listener); - this->forward->destroy(this->forward); - } - DESTROY_IF(this->dae); this->configs->destroy_offset(this->configs, offsetof(radius_config_t, destroy)); this->lock->destroy(this->lock); - this->accounting->destroy(this->accounting); free(this); instance = NULL; } @@ -250,26 +286,9 @@ plugin_t *eap_radius_plugin_create() }, .configs = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), - .accounting = eap_radius_accounting_create(), - .forward = eap_radius_forward_create(), - .provider = eap_radius_provider_create(), ); - - load_configs(this); instance = this; - if (lib->settings->get_bool(lib->settings, - "%s.plugins.eap-radius.dae.enable", FALSE, charon->name)) - { - this->dae = eap_radius_dae_create(this->accounting); - } - if (this->forward) - { - charon->bus->add_listener(charon->bus, &this->forward->listener); - } - hydra->attributes->add_provider(hydra->attributes, - &this->provider->provider); - return &this->public.plugin; } From 31a416a5b2d0b63bade04d50083b4b9b75daa1ae Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 10 Jun 2013 18:33:49 +0200 Subject: [PATCH 43/43] Removed stray *_plugin_create() declarations from header files --- src/libcharon/plugins/eap_peap/eap_peap_plugin.h | 5 ----- src/libcharon/plugins/eap_tls/eap_tls_plugin.h | 5 ----- src/libcharon/plugins/eap_ttls/eap_ttls_plugin.h | 5 ----- 3 files changed, 15 deletions(-) diff --git a/src/libcharon/plugins/eap_peap/eap_peap_plugin.h b/src/libcharon/plugins/eap_peap/eap_peap_plugin.h index 75bb504e1..0c3c571ef 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_plugin.h +++ b/src/libcharon/plugins/eap_peap/eap_peap_plugin.h @@ -39,9 +39,4 @@ struct eap_peap_plugin_t { plugin_t plugin; }; -/** - * Create a eap_peap_plugin instance. - */ -plugin_t *eap_peap_plugin_create(); - #endif /** EAP_PEAP_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/eap_tls_plugin.h b/src/libcharon/plugins/eap_tls/eap_tls_plugin.h index 5ea719603..33d0dfbaf 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls_plugin.h +++ b/src/libcharon/plugins/eap_tls/eap_tls_plugin.h @@ -39,9 +39,4 @@ struct eap_tls_plugin_t { plugin_t plugin; }; -/** - * Create a eap_tls_plugin instance. - */ -plugin_t *eap_tls_plugin_create(); - #endif /** EAP_TLS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.h b/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.h index 2abc82931..ca84ad7bb 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.h +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.h @@ -39,9 +39,4 @@ struct eap_ttls_plugin_t { plugin_t plugin; }; -/** - * Create a eap_ttls_plugin instance. - */ -plugin_t *eap_ttls_plugin_create(); - #endif /** EAP_TTLS_PLUGIN_H_ @}*/