diff --git a/Makefile.top b/Makefile.top new file mode 100644 index 0000000..20e10a2 --- /dev/null +++ b/Makefile.top @@ -0,0 +1 @@ +CFLAGS=-fPIC -Wall -Wstrict-prototypes -Werror -ggdb -D_GNU_SOURCE diff --git a/client/Makefile b/client/Makefile index 93d3fe1..6681022 100644 --- a/client/Makefile +++ b/client/Makefile @@ -10,6 +10,7 @@ ############################################################################### ############################################################################### +include=../Makefile.top TARGETS=fence_virt fence_xvm @@ -21,8 +22,7 @@ INCLUDES=-I../include\ -I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \ -I/usr/include/libvirt -CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" \ - -Wall -Werror -Wstrict-prototypes -Wshadow -ggdb -D_GNU_SOURCE +CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" LIBS+=-L../../../cman/lib -L../../../ccs/lib -L${libdir}/openais \ -L../../../dlm/lib -lnss3 -lxml2 diff --git a/common/Makefile b/common/Makefile index f0a10ff..88c0fce 100644 --- a/common/Makefile +++ b/common/Makefile @@ -10,6 +10,7 @@ ############################################################################### ############################################################################### +include ../Makefile.top TARGETS=libfence_virt.a @@ -22,8 +23,7 @@ INCLUDES=-I../include \ -I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \ -I/usr/include/libvirt -CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" \ - -Wall -Werror -Wstrict-prototypes -Wshadow -ggdb -D_GNU_SOURCE +CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" LIBS+=-L../../../cman/lib -L../../../ccs/lib -L${libdir}/openais \ -L../../../dlm/lib -lnss3 -lxml2 diff --git a/include/options.h b/include/options.h index bb96dd2..7d6fdd7 100644 --- a/include/options.h +++ b/include/options.h @@ -33,7 +33,7 @@ typedef enum { typedef enum { MODE_MULTICAST = 0, - //MODE_BROADCAST = 1, + /*MODE_BROADCAST = 1,*/ MODE_SERIAL = 2, MODE_VMCHANNEL = 3 } client_mode_t; diff --git a/include/server_plugin.h b/include/server_plugin.h index c808f35..b63419f 100644 --- a/include/server_plugin.h +++ b/include/server_plugin.h @@ -1,8 +1,21 @@ - /* */ - #include +#define PLUGIN_VERSION_FRONTEND ((double)0.1) +#define PLUGIN_VERSION_BACKEND ((double)0.1) + +#define FRONTEND_VER_SYM frontend_plugin_version +#define BACKEND_VER_SYM backend_plugin_version +#define FRONTEND_INFO_SYM frontend_plugin_info +#define BACKEND_INFO_SYM backend_plugin_info +#define FRONTEND_VER_STR "frontend_plugin_version" +#define BACKEND_VER_STR "backend_plugin_version" +#define FRONTEND_INFO_STR "frontend_plugin_info" +#define BACKEND_INFO_STR "backend_plugin_info" + + + + typedef void * srv_context_t; /* These callbacks hand requests off to the @@ -56,10 +69,11 @@ typedef struct _backend_plugin { fence_cleanup_callback cleanup; } plugin_t; -#ifndef _USE_MODULES -void plugin_register(const plugin_t *plugin); +int plugin_register(const plugin_t *plugin); const plugin_t *plugin_find(const char *name); void plugin_dump(void); +#ifdef _MODULE +int plugin_load(const char *libpath); #endif diff --git a/include/xvm.h b/include/xvm.h index 6a099c1..2a9a183 100644 --- a/include/xvm.h +++ b/include/xvm.h @@ -43,7 +43,7 @@ typedef enum { AUTH_NONE = 0x0, /* Plain TCP */ AUTH_SHA1 = 0x1, /* Challenge-response (SHA1) */ AUTH_SHA256 = 0x2, /* Challenge-response (SHA256) */ - AUTH_SHA512 = 0x3, /* Challenge-response (SHA512) */ + AUTH_SHA512 = 0x3 /* Challenge-response (SHA512) */ /* AUTH_SSL_X509 = 0x10 SSL X509 certificates */ } fence_auth_type_t; diff --git a/server/Makefile b/server/Makefile index 458ed72..ff644f5 100644 --- a/server/Makefile +++ b/server/Makefile @@ -10,10 +10,14 @@ ############################################################################### ############################################################################### +include ../Makefile.top -TARGETS=fence_virtd -fence_virtd_SOURCES = mcast.c libvirt.c main.c plugin.c +TARGETS=fence_virtd libvirt.so + +fence_virtd_SOURCES = mcast.c main.c plugin.c + +libvirt_so_SOURCES = libvirt.c INCLUDES=-I../include\ -I/usr/include/openais -I/usr/include/libvirt \ @@ -21,8 +25,7 @@ INCLUDES=-I../include\ -I../../../cman/lib -I../../../ccs/lib -I/usr/include/libxml2 \ -I/usr/include/libvirt -CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" \ - -Wall -Werror -Wstrict-prototypes -Wshadow -ggdb -D_GNU_SOURCE +CFLAGS+=-DFENCE_RELEASE_NAME=\"devel\" -D_MODULE LIBS+=-L/usr/lib64/openais -lnss3 -lxml2 -lSaCkpt -lccs -lvirt -lcman \ -L../common -lfence_virt @@ -32,6 +35,9 @@ all: ${TARGETS} fence_virtd: ${fence_virtd_SOURCES:.c=.o} gcc -o $@ $^ $(LIBS) -L../common -lfence_virt +libvirt.so: ${libvirt_so_SOURCES:.c=.o} + gcc -o $@ $^ $(LIBS) -shared -L../common -lvirt + %.o: %.c gcc $(CFLAGS) -c -o $@ $^ $(INCLUDES) diff --git a/server/libvirt.c b/server/libvirt.c index 43ae044..6cf24d5 100644 --- a/server/libvirt.c +++ b/server/libvirt.c @@ -305,14 +305,6 @@ static fence_callbacks_t libvirt_callbacks = { .devstatus = libvirt_devstatus }; -#ifdef _MODULE -fence_callbacks_t * -plugin_callbacks(void) -{ - return &libvirt_callbacks; -} -#else - static plugin_t libvirt_plugin = { .name = NAME, .version = VERSION, @@ -321,8 +313,22 @@ static plugin_t libvirt_plugin = { .cleanup = libvirt_shutdown, }; + +#ifdef _MODULE +double +BACKEND_VER_SYM(void) +{ + return PLUGIN_VERSION_BACKEND; +} + +const plugin_t * +BACKEND_INFO_SYM(void) +{ + return &libvirt_plugin; +} +#else static void __attribute__((constructor)) -initialize_plugin(void) +libvirt_register_plugin(void) { plugin_register(&libvirt_plugin); } diff --git a/server/main.c b/server/main.c index a4f7398..2856ee6 100644 --- a/server/main.c +++ b/server/main.c @@ -22,6 +22,11 @@ main(int argc, char **argv) dset(99); +#ifdef _MODULE + if (plugin_load("./libvirt.so") < 0) { + printf("Doom\n"); + } +#endif plugin_dump(); p = plugin_find(plugin_name); diff --git a/server/plugin.c b/server/plugin.c index fea3b27..f055b17 100644 --- a/server/plugin.c +++ b/server/plugin.c @@ -1,4 +1,33 @@ +/* + Copyright Red Hat, Inc. 2002-2004, 2009 + + The Magma Cluster API Library is free software; you can redistribute + it and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either version + 2.1 of the License, or (at your option) any later version. + + The Magma Cluster API Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. + */ +/** @file + * Plugin loading routines + */ +#include +#include +#include #include +#include +#include +#include +#include + #include #include #include @@ -12,17 +41,18 @@ typedef struct _plugin_list { static plugin_list_t *server_plugins = NULL; -void +int plugin_register(const plugin_t *plugin) { plugin_list_t *newplug; newplug = malloc(sizeof(*newplug)); - if (!newplug) - return; + if (!newplug) + return -1; memset(newplug, 0, sizeof(*newplug)); newplug->plugin = plugin; list_insert(&server_plugins, newplug); + return 0; } void @@ -64,4 +94,101 @@ plugin_shutdown(const plugin_t *p, srv_context_t c) return p->cleanup(c); } +/** + * Load a cluster plugin .so file and map all the functions + * provided to entries in a plugin_t structure. + * + * @param libpath Path to file. + * @return NULL on failure, or plugin-specific + * (const) plugin_t * structure on + * success. + */ +int +plugin_load(const char *libpath) +{ + void *handle = NULL; + const plugin_t *plug = NULL; + double (*modversion)(void); + plugin_t *(*modinfo)(void); + struct stat sb; + errno = 0; + + if (!libpath) { + errno = EINVAL; + return -1; + } + + if (stat(libpath, &sb) != 0) { + return -1; + } + + /* + If it's not owner-readable or it's a directory, + ignore/fail. Thus, a user may change the permission of + a plugin "u-r" and this would then prevent magma apps + from loading it. + */ + if (S_ISDIR(sb.st_mode)) { + errno = EISDIR; + return -1; + } + + if (!(sb.st_mode & S_IRUSR)) { +#ifdef DEBUG + printf("Ignoring %s (User-readable bit not set)\n", + libpath); +#endif + errno = EPERM; + return -1; + } + + handle = dlopen(libpath, RTLD_LAZY); + if (!handle) { + errno = ELIBACC; + return -1; + } + + modversion = dlsym(handle, BACKEND_VER_STR); + if (!modversion) { +#ifdef DEBUG + printf("Failed to map %s\n", BACKEND_VER_STR); +#endif + dlclose(handle); + errno = EINVAL; + return -1; + } + + if (modversion() != PLUGIN_VERSION_BACKEND) { +#ifdef DEBUG + printf("API version mismatch in %s: \n" + " %f expected; %f received.\n", libpath, + , modversion()); +#endif + dlclose(handle); + errno = EINVAL; + return -1; + } + + modinfo = dlsym(handle, BACKEND_INFO_STR); + if (!modinfo) { +#ifdef DEBUG + printf("Failed to map %s\n", BACKEND_INFO_STR); +#endif + dlclose(handle); + errno = EINVAL; + return -1; + } + + plug = modinfo(); + if (plugin_register(plug) < 0) { + dlclose(handle); + errno = EINVAL; + return -1; + } else { + printf("Registered plugin %s %s\n", + plug->name, plug->version); + } + + return 0; +}