Load hooks based on listener dynamically
authorMartin Willi <martin@revosec.ch>
Tue, 26 Oct 2010 08:51:28 +0000 (10:51 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:45:40 +0000 (16:45 +0100)
src/conftest/Makefile.am
src/conftest/conftest.c
src/conftest/conftest.h
src/conftest/hooks/hook.h [new file with mode: 0644]

index d975810..0b041a4 100644 (file)
@@ -1,6 +1,8 @@
 ipsec_PROGRAMS = conftest
 
-conftest_SOURCES = conftest.c
+AM_CFLAGS = -rdynamic
+
+conftest_SOURCES = conftest.c hooks/hook.h
 
 INCLUDES = \
        -I$(top_srcdir)/src/libstrongswan \
index 777cf68..881db5d 100644 (file)
  * for more details.
  */
 
+#define _GNU_SOURCE
 #include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
 #include <getopt.h>
+#include <dlfcn.h>
 #include <libgen.h>
 
 #include "conftest.h"
+#include "hooks/hook.h"
 
 #include <threading/thread.h>
 
@@ -32,19 +35,8 @@ conftest_t *conftest;
 /**
  * Print usage information
  */
-static void usage(char *error)
+static void usage(FILE *out)
 {
-       FILE *out = stdout;
-
-       if (error)
-       {
-               out = stderr;
-               fprintf(out, "%s\n", error);
-       }
-       else
-       {
-               fprintf(out, "strongSwan %s conftest\n", VERSION);
-       }
        fprintf(out, "Usage:\n");
        fprintf(out, "  --help           show usage information\n");
        fprintf(out, "  --version        show conftest version\n");
@@ -147,14 +139,59 @@ static bool load_certs()
 }
 
 /**
+ * Load configured hooks
+ */
+static bool load_hooks()
+{
+       enumerator_t *enumerator;
+       char *name, buf[64];
+       hook_t *(*create)(void);
+       hook_t *hook;
+
+       enumerator = conftest->test->create_section_enumerator(conftest->test,
+                                                                                                                  "hooks");
+       while (enumerator->enumerate(enumerator, &name))
+       {
+               snprintf(buf, sizeof(buf), "%s_hook_create", name);
+               create = dlsym(RTLD_DEFAULT, buf);
+               if (create)
+               {
+                       hook = create();
+                       if (hook)
+                       {
+                               conftest->hooks->insert_last(conftest->hooks, hook);
+                               charon->bus->add_listener(charon->bus, &hook->listener);
+                       }
+               }
+               else
+               {
+                       fprintf(stderr, "dlsym() for hook '%s' failed: %s\n", name, dlerror());
+                       enumerator->destroy(enumerator);
+                       return FALSE;
+               }
+       }
+       enumerator->destroy(enumerator);
+       return TRUE;
+}
+
+/**
  * atexit() cleanup handler
  */
 static void cleanup()
 {
+       hook_t *hook;
+
        DESTROY_IF(conftest->suite);
        DESTROY_IF(conftest->test);
        lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set);
        conftest->creds->destroy(conftest->creds);
+       while (conftest->hooks->remove_last(conftest->hooks,
+                                                                               (void**)&hook) == SUCCESS)
+       {
+               charon->bus->remove_listener(charon->bus, &hook->listener);
+               hook->destroy(hook);
+       }
+       conftest->hooks->destroy(conftest->hooks);
        free(conftest->suite_dir);
        free(conftest->test_dir);
        free(conftest);
@@ -221,7 +258,7 @@ int main(int argc, char *argv[])
                        case EOF:
                                break;
                        case 'h':
-                               usage(NULL);
+                               usage(stdout);
                                return 0;
                        case 'v':
                                printf("strongSwan %s conftest\n", VERSION);
@@ -233,7 +270,7 @@ int main(int argc, char *argv[])
                                test_file = optarg;
                                continue;
                        default:
-                               usage("Invalid option.");
+                               usage(stderr);
                                return 1;
                }
                break;
@@ -251,6 +288,10 @@ int main(int argc, char *argv[])
        {
                return 1;
        }
+       if (!load_hooks())
+       {
+               return 1;
+       }
 
        /* set up thread specific handlers */
        action.sa_handler = segv_handler;
index 22d3deb..614248e 100644 (file)
@@ -56,6 +56,11 @@ struct conftest_t {
         * Credentials loaded from configuration
         */
        mem_cred_t *creds;
+
+       /**
+        * Loaded hooks
+        */
+       linked_list_t *hooks;
 };
 
 /**
diff --git a/src/conftest/hooks/hook.h b/src/conftest/hooks/hook.h
new file mode 100644 (file)
index 0000000..39a15f2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup hook hook
+ * @{ @ingroup hooks
+ */
+
+#ifndef HOOK_H_
+#define HOOK_H_
+
+typedef struct hook_t hook_t;
+
+#include <daemon.h>
+#include <conftest.h>
+
+/**
+ * Hook providing interface.
+ */
+struct hook_t {
+
+       /**
+        * Implements listener_t.
+        */
+       listener_t listener;
+
+       /**
+        * Destroy a hook_t.
+        */
+       void (*destroy)(hook_t *this);
+};
+
+#endif /** HOOK_H_ @}*/