/* * 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 #include #include #include #include #include #include #ifdef WITH_SYSLOG #include #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; }