/* * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ha_plugin.h" #include "ha_ike.h" #include "ha_child.h" #include "ha_socket.h" #include "ha_tunnel.h" #include "ha_dispatcher.h" #include "ha_segments.h" #include "ha_ctl.h" #include "ha_cache.h" #include "ha_attribute.h" #include #include typedef struct private_ha_plugin_t private_ha_plugin_t; /** * private data of ha plugin */ struct private_ha_plugin_t { /** * implements plugin interface */ ha_plugin_t public; /** * Communication socket */ ha_socket_t *socket; /** * Tunnel securing sync messages. */ ha_tunnel_t *tunnel; /** * IKE_SA synchronization */ ha_ike_t *ike; /** * CHILD_SA synchronization */ ha_child_t *child; /** * Dispatcher to process incoming messages */ ha_dispatcher_t *dispatcher; /** * Active/Passive segment management */ ha_segments_t *segments; /** * Interface to control segments at kernel level */ ha_kernel_t *kernel; /** * Segment control interface via FIFO */ ha_ctl_t *ctl; /** * Message cache for resynchronization */ ha_cache_t *cache; /** * Attribute provider */ ha_attribute_t *attr; }; METHOD(plugin_t, get_name, char*, private_ha_plugin_t *this) { return "ha"; } /** * Initialize plugin */ static bool initialize_plugin(private_ha_plugin_t *this) { char *local, *remote, *secret; u_int count; bool fifo, monitor, resync; local = lib->settings->get_str(lib->settings, "%s.plugins.ha.local", NULL, lib->ns); remote = lib->settings->get_str(lib->settings, "%s.plugins.ha.remote", NULL, lib->ns); secret = lib->settings->get_str(lib->settings, "%s.plugins.ha.secret", NULL, lib->ns); fifo = lib->settings->get_bool(lib->settings, "%s.plugins.ha.fifo_interface", TRUE, lib->ns); monitor = lib->settings->get_bool(lib->settings, "%s.plugins.ha.monitor", TRUE, lib->ns); resync = lib->settings->get_bool(lib->settings, "%s.plugins.ha.resync", TRUE, lib->ns); count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings, "%s.plugins.ha.segment_count", 1, lib->ns)); if (!local || !remote) { DBG1(DBG_CFG, "HA config misses local/remote address"); return FALSE; } if (secret) { this->tunnel = ha_tunnel_create(local, remote, secret); } this->socket = ha_socket_create(local, remote); if (!this->socket) { return FALSE; } this->kernel = ha_kernel_create(count); this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel, count, strcmp(local, remote) > 0, monitor); this->cache = ha_cache_create(this->kernel, this->socket, this->tunnel, resync, count); if (fifo) { this->ctl = ha_ctl_create(this->segments, this->cache); } this->attr = ha_attribute_create(this->kernel, this->segments); this->dispatcher = ha_dispatcher_create(this->socket, this->segments, this->cache, this->kernel, this->attr); this->ike = ha_ike_create(this->socket, this->tunnel, this->cache); this->child = ha_child_create(this->socket, this->tunnel, this->segments, this->kernel); return TRUE; } /** * Initialize plugin and register listener */ static bool plugin_cb(private_ha_plugin_t *this, plugin_feature_t *feature, bool reg, void *cb_data) { if (reg) { if (!initialize_plugin(this)) { return FALSE; } 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); charon->attributes->add_provider(charon->attributes, &this->attr->provider); } else { charon->attributes->remove_provider(charon->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"), PLUGIN_SDEPEND(CUSTOM, "kernel-ipsec"), }; *features = f; return countof(f); } METHOD(plugin_t, destroy, void, private_ha_plugin_t *this) { DESTROY_IF(this->ctl); DESTROY_IF(this->ike); DESTROY_IF(this->child); DESTROY_IF(this->dispatcher); DESTROY_IF(this->attr); DESTROY_IF(this->cache); DESTROY_IF(this->segments); DESTROY_IF(this->kernel); DESTROY_IF(this->socket); DESTROY_IF(this->tunnel); free(this); } /** * Plugin constructor */ plugin_t *ha_plugin_create() { private_ha_plugin_t *this; if (!lib->caps->keep(lib->caps, CAP_CHOWN)) { /* required to chown(2) control socket, ha_kernel also needs it at * runtime */ DBG1(DBG_CFG, "ha plugin requires CAP_CHOWN capability"); return NULL; } INIT(this, .public = { .plugin = { .get_name = _get_name, .get_features = _get_features, .destroy = _destroy, }, }, ); return &this->public.plugin; }