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; } 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; } 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; } - 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; } 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; } 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; } - 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; } 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_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; } 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_ @}*/ 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; } 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; } - 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; } 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..2fd820f94 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,74 @@ 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 + */ +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; + } + + 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); + } + 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 +131,12 @@ plugin_t *ipseckey_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, + .reload = _reload, .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; } - 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; } 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; 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; } - 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; } - 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; } - 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; } 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; } - 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); 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; } - 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/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; } 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; } - 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; } - 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; } 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; } - 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; } diff --git a/src/libhydra/plugins/attr/attr_plugin.c b/src/libhydra/plugins/attr/attr_plugin.c index cb14495af..72fcd6dff 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,14 +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; } - 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; } - 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; } 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; } - 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; } 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; } 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); } } } diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c index 6c954f76d..8a1958be5 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 @@ -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: @@ -169,6 +172,56 @@ 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_RESOLVER: + 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. */ @@ -236,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; @@ -413,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; } @@ -485,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 7667fff3e..ea23f766c 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 @@ -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 } } @@ -325,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. * @@ -340,12 +365,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..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(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, 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* */ 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; } 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, }, }, 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; }