summaryrefslogtreecommitdiff
path: root/plugin/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/plugin.c')
-rw-r--r--plugin/plugin.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/plugin/plugin.c b/plugin/plugin.c
new file mode 100644
index 0000000..c38eb67
--- /dev/null
+++ b/plugin/plugin.c
@@ -0,0 +1,352 @@
+
+#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>
+
+#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';
+
+#if _DEBUG
+ fprintf (stderr, "%s", 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 *** %s:%d %s%s",
+ PLUGIN_NAME, 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 = strchr (arg, '=');
+ if (value) {
+ *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]);
+ }
+
+ /* Next we initialize all components */
+ if (autoserial_init () < 0 ||
+ dnsnotify_init() < 0)
+ return -1;
+
+ 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_POST_ADD_FN, (void*)post_add) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void*)post_modify) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_POST_DELETE_FN, (void*)post_delete) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void*)post_modrdn) != 0) {
+ log_plugin ("error registering plugin hooks");
+ return -1;
+ }
+
+ log_plugin ("%s initialized", PLUGIN_NAME);
+ return 0;
+}
+