summaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'plugin')
-rw-r--r--plugin/plugin.c389
-rw-r--r--plugin/plugin.h105
2 files changed, 494 insertions, 0 deletions
diff --git a/plugin/plugin.c b/plugin/plugin.c
new file mode 100644
index 0000000..8f91f52
--- /dev/null
+++ b/plugin/plugin.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2009, Stefan Walter
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "config.h"
+
+#include "plugin.h"
+
+#include <sys/wait.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef WITH_SYSLOG
+#include <syslog.h>
+#endif
+
+#define WHITESPACE " \t\r\n\v"
+
+static char **plugin_arguments = NULL;
+
+/* ---------------------------------------------------------------------
+ * LOGGING/TRACING
+ */
+
+static void
+log_msg_va (int level, const char* msg, va_list ap)
+{
+ size_t len;
+ char buf[1024];
+
+ assert (level >= 0);
+ assert (msg != NULL);
+
+ vsnprintf (buf, sizeof (buf) - 2, msg, ap);
+
+ len = strlen (buf);
+ buf[len] = '\n';
+ buf[len + 1] = '\0';
+
+ fprintf (stderr, "%s: %s", PLUGIN_NAME, buf);
+#ifdef WITH_SYSLOG
+ if (level != SLAPI_LOG_TRACE)
+ syslog (LOG_WARNING | LOG_DAEMON, "%s: %s", PLUGIN_NAME, buf);
+#endif
+ slapi_log_error (level, PLUGIN_NAME, buf);
+}
+
+void
+log_msg (int level, const char* msg, ...)
+{
+ va_list ap;
+ va_start (ap, msg);
+ log_msg_va (level, msg, ap);
+ va_end (ap);
+}
+
+#if _DEBUG
+void
+log_trace (const char *where, int line, const char *msg)
+{
+ log_msg (SLAPI_LOG_TRACE, " *** %s:%d %s%s",
+ where, line, msg ? ": " : "", msg ? msg : "");
+}
+#endif
+
+void
+log_plugin (const char* msg, ...)
+{
+ va_list ap;
+ va_start (ap, msg);
+ log_msg_va (SLAPI_LOG_PLUGIN, msg, ap);
+ va_end (ap);
+}
+
+/* --------------------------------------------------------------------------------
+ * HELPERS
+ */
+
+const char*
+ltrim (const char *data)
+{
+ while (*data && isspace (*data))
+ ++data;
+ return data;
+}
+
+void
+rtrim (char *data)
+{
+ char *t = data + strlen (data);
+ while (t > data && isspace (*(t - 1))) {
+ t--;
+ *t = 0;
+ }
+}
+
+char*
+trim (char *data)
+{
+ data = (char*)ltrim (data);
+ rtrim (data);
+ return data;
+}
+
+void
+lowercase (char *data)
+{
+ while (*data) {
+ *data = tolower (*data);
+ ++data;
+ }
+}
+
+/* ---------------------------------------------------------------------------------
+ * OPERATIONS
+ */
+
+static char*
+dn_build_normalize (const char *dn, const char *rdn)
+{
+ char *result;
+ Slapi_DN *sdn;
+ Slapi_DN *parent;
+ Slapi_RDN *srdn;
+
+ /* Get the parent of the dn */
+ sdn = slapi_sdn_new_dn_byval (dn);
+ return_val_if_fail (sdn, NULL);
+ parent = slapi_sdn_new ();
+ slapi_sdn_get_parent (sdn, parent);
+
+ /* Add the rdn to the parent */
+ srdn = slapi_rdn_new_dn (rdn);
+ return_val_if_fail (srdn, NULL);
+ slapi_sdn_add_rdn (parent, srdn);
+
+ /* Get the result out */
+ result = (char*)slapi_sdn_get_dn (parent);
+ return_val_if_fail (result, NULL);
+
+ /* Normalize the result */
+ result = slapi_ch_strdup (result);
+ slapi_dn_normalize_case (result);
+
+ slapi_sdn_free (&sdn);
+ slapi_rdn_free (&srdn);
+ slapi_sdn_free (&parent);
+
+ trace (result);
+ return result;
+}
+
+static int
+post_delete (Slapi_PBlock *pb)
+{
+ int rc, code;
+ char *dn;
+
+ return_val_if_fail (pb, -1);
+
+ /* Make sure it was successful, don't process errors */
+ rc = slapi_pblock_get (pb, SLAPI_RESULT_CODE, &code);
+ return_val_if_fail (rc >= 0, -1);
+ if (code != LDAP_SUCCESS)
+ return 0;
+
+ /* Get out the DN and normalize it */
+ rc = slapi_pblock_get (pb, SLAPI_DELETE_TARGET, &dn);
+ return_val_if_fail (rc >= 0 && dn, -1);
+ dn = slapi_ch_strdup (dn);
+ slapi_dn_normalize_case (dn);
+
+ /* Send off to components */
+ autoserial_post_delete (dn);
+
+ slapi_ch_free_string (&dn);
+ return 0;
+}
+
+static int
+post_modrdn (Slapi_PBlock *pb)
+{
+ char *rdn, *odn, *ndn;
+ int rc, code;
+
+ return_val_if_fail (pb, -1);
+
+ /* Make sure it was successful, don't process errors */
+ rc = slapi_pblock_get (pb, SLAPI_RESULT_CODE, &code);
+ return_val_if_fail (rc >= 0, -1);
+ if (code != LDAP_SUCCESS)
+ return 0;
+
+ /* Get out the DN and normalize it */
+ rc = slapi_pblock_get (pb, SLAPI_MODRDN_TARGET, &odn);
+ return_val_if_fail (rc >= 0 && odn, -1);
+ odn = slapi_ch_strdup (odn);
+ slapi_dn_normalize_case (odn);
+
+ /* Get out the changed DN and calculate it */
+ rc = slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &rdn);
+ return_val_if_fail (rc >= 0 && rdn, -1);
+ ndn = dn_build_normalize (odn, rdn);
+ return_val_if_fail (ndn, -1);
+
+ /* Send off to components */
+ autoserial_post_modrdn (odn, ndn);
+
+ slapi_ch_free_string (&odn);
+ slapi_ch_free_string (&ndn);
+ return 0;
+}
+
+static int
+post_modify (Slapi_PBlock *pb)
+{
+ LDAPMod **mods;
+ char *dn;
+ int rc, code;
+
+ return_val_if_fail (pb, -1);
+
+ /* Make sure it was successful, don't process errors */
+ rc = slapi_pblock_get (pb, SLAPI_RESULT_CODE, &code);
+ return_val_if_fail (rc >= 0, -1);
+ if (code != LDAP_SUCCESS)
+ return 0;
+
+ /* Get out the DN and normalize it */
+ rc = slapi_pblock_get (pb, SLAPI_MODIFY_TARGET, &dn);
+ return_val_if_fail (rc >= 0 && dn, -1);
+ dn = slapi_ch_strdup (dn);
+ slapi_dn_normalize_case (dn);
+
+ rc = slapi_pblock_get (pb, SLAPI_MODIFY_MODS, &mods);
+ return_val_if_fail (rc >= 0 && mods, -1);
+
+ /* Send off to components */
+ autoserial_post_modify (dn, mods);
+ dnsnotify_post_modify (dn, mods);
+
+ slapi_ch_free_string (&dn);
+ return 0;
+}
+
+static int
+post_add (Slapi_PBlock *pb)
+{
+ char *dn;
+ int rc, code;
+
+ return_val_if_fail (pb, -1);
+
+ /* Make sure it was successful, don't process errors */
+ rc = slapi_pblock_get (pb, SLAPI_RESULT_CODE, &code);
+ return_val_if_fail (rc >= 0, -1);
+ if (code != LDAP_SUCCESS)
+ return 0;
+
+ /* Get out the DN and normalize it */
+ rc = slapi_pblock_get (pb, SLAPI_ADD_TARGET, &dn);
+ return_val_if_fail (rc >= 0 && dn, -1);
+ dn = slapi_ch_strdup (dn);
+ slapi_dn_normalize_case (dn);
+
+ /* Send off to components */
+ autoserial_post_add (dn);
+ dnsnotify_post_add (dn);
+
+ slapi_ch_free_string (&dn);
+ return 0;
+}
+
+static Slapi_PluginDesc plugin_description = {
+ PLUGIN_NAME, /* plug-in identifier */
+ "stef@memberwebs.com", /* vendor name */
+ VERSION, /* plug-in revision number */
+ "Notify's DNS slaves when SOA change is made" /* plug-in description */
+};
+
+static int
+plugin_destroy (Slapi_PBlock *pb)
+{
+ autoserial_destroy ();
+ dnsnotify_destroy ();
+
+ slapi_ch_array_free (plugin_arguments);
+ plugin_arguments = NULL;
+
+ return 0;
+}
+
+int
+plugin_init (Slapi_PBlock *pb)
+{
+ char **argv = NULL, *arg, *value;
+ int argc = 0;
+ int rc, i;
+
+ return_val_if_fail (pb, -1);
+
+ rc = slapi_pblock_get (pb, SLAPI_PLUGIN_ARGV, &argv);
+ return_val_if_fail (rc >= 0, -1);
+ slapi_pblock_get (pb, SLAPI_PLUGIN_ARGC, &argc);
+ return_val_if_fail (rc >= 0, -1);
+
+ /*
+ * Copy all the arguments, until we get destroyed, and
+ * send the arguments to the components to configure
+ * themselves.
+ */
+ plugin_arguments = (char**)slapi_ch_calloc (argc + 1, sizeof (char*));
+ for (i = 0; i < argc; ++i) {
+ plugin_arguments[i] = slapi_ch_strdup (argv[i]);
+ arg = trim (plugin_arguments[i]);
+
+ value = arg + strcspn (arg, ":=");
+ if (!*value) {
+ value = NULL;
+ } else {
+ *value = 0;
+ value = trim (value + 1);
+ }
+
+ lowercase (arg);
+
+ rc = autoserial_config (arg, value);
+ rc |= dnsnotify_config (arg, value);
+
+ if (!rc)
+ log_plugin ("unrecognized plugin argument: %s", argv[i]);
+ }
+
+ /* Null terminate */
+ plugin_arguments[i] = NULL;
+
+ if (slapi_pblock_set (pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_DESTROY_FN, plugin_destroy)) {
+ log_plugin ("error registring plugin");
+ return -1;
+ }
+
+ /* Setup the entry add/mobify functions */
+ if (slapi_pblock_set (pb, SLAPI_PLUGIN_PRE_ADD_FN, (void*)post_add) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void*)post_modify) != 0) {
+ log_plugin ("error registering plugin hooks");
+ return -1;
+ }
+
+#ifdef _DEBUG
+ log_trace ("%s initialized", PLUGIN_NAME);
+#endif
+ return 0;
+}
+
diff --git a/plugin/plugin.h b/plugin/plugin.h
new file mode 100644
index 0000000..400dc6f
--- /dev/null
+++ b/plugin/plugin.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2008, Stefan Walter
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef PLUGIN_H_
+#define PLUGIN_H_
+
+#include <lber.h>
+#include <ldap.h>
+
+#ifdef HAVE_SLAPI_PLUGIN_H
+#include <slapi-plugin.h>
+#else
+#include "include/slapi-plugin.h"
+#endif
+
+#define PLUGIN_NAME "slapi-dnsnotify"
+
+/* ---------------------------------------------------------------------
+ * LOGGING
+ */
+
+void log_msg (int level, const char* msg, ...);
+void log_plugin (const char* msg, ...);
+
+#define return_val_if_fail(expr, ret) \
+ do { if (expr) { } else { \
+ log_plugin ("*** %s *** check failed: '%s' at %s:%d", PLUGIN_NAME, #expr, __PRETTY_FUNCTION__, __LINE__); \
+ return (ret); \
+ } } while (0)
+#define return_if_fail(expr) \
+ do { if (expr) { } else { \
+ log_plugin ("*** %s *** check failed: '%s' at %s:%d", PLUGIN_NAME, #expr, __PRETTY_FUNCTION__, __LINE__); \
+ return; \
+ } } while (0)
+
+#if _DEBUG
+void log_trace (const char *where, int line, const char *msg);
+#define trace(x) log_trace (__PRETTY_FUNCTION__, __LINE__, (x))
+#else
+#define trace(x)
+#endif
+
+/* ----------------------------------------------------------------------
+ * HELPERS
+ */
+
+const char* ltrim (const char *data);
+void rtrim (char *data);
+char* trim (char *data);
+void lowercase (char *data);
+
+/* ----------------------------------------------------------------------
+ * AUTO SERIAL
+ */
+
+int autoserial_init (void);
+void autoserial_destroy (void);
+int autoserial_config (const char *name, const char *value);
+void autoserial_post_add (const char *dn);
+void autoserial_post_modify (const char *dn, LDAPMod **mods);
+void autoserial_post_modrdn (const char *odn, const char *ndn);
+void autoserial_post_delete (const char *dn);
+
+/* ----------------------------------------------------------------------
+ * DNS NOTIFY
+ */
+
+int dnsnotify_init (void);
+void dnsnotify_destroy (void);
+int dnsnotify_config (const char *name, const char *value);
+void dnsnotify_post_add (const char *dn);
+void dnsnotify_post_modify (const char *dn, LDAPMod **mods);
+
+
+#endif /*PLUGIN_H_*/