diff options
author | Stef Walter <stef@memberwebs.com> | 2008-06-09 17:22:43 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2008-06-09 17:22:43 +0000 |
commit | b9ecd6e5e5b87fe1c4dab960e92246772002dd6a (patch) | |
tree | eb05eb48888e391678fa706ec5f62b012df2456e /plugin/slapi-dnsnotify.c | |
parent | 3add3c0e19b659427a2624ec85daf67019b8ed7f (diff) |
Merge the two dns plugins
Diffstat (limited to 'plugin/slapi-dnsnotify.c')
-rw-r--r-- | plugin/slapi-dnsnotify.c | 529 |
1 files changed, 0 insertions, 529 deletions
diff --git a/plugin/slapi-dnsnotify.c b/plugin/slapi-dnsnotify.c deleted file mode 100644 index 329b913..0000000 --- a/plugin/slapi-dnsnotify.c +++ /dev/null @@ -1,529 +0,0 @@ - -#include "config.h" - -#include <sys/wait.h> - -#include <stdarg.h> -#include <string.h> -#include <stdio.h> -#include <assert.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <signal.h> -#include <ctype.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" - -/*---------------------------------------------------------------------------------- - * DECLARATIONS - */ - -static const char *dnsnotify_soa_attribute = "sOARecord"; -static const char *dnsnotify_ns_attribute = "nSRecord"; - -static Slapi_Mutex *dnsnotify_mutex = NULL; -static int dnsnotify_pipe = -1; -static pid_t dnsnotify_pid = -1; - -/* --------------------------------------------------------------------- - * 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); -} - -static 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 -static 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 - -static void -log_plugin (const char* msg, ...) -{ - va_list ap; - va_start (ap, msg); - log_msg_va (SLAPI_LOG_PLUGIN, msg, ap); - va_end (ap); -} - -#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) - -#if _DEBUG -#define trace(x) log_trace (__PRETTY_FUNCTION__, __LINE__, (x)) -#else -#define trace(x) -#endif - -/* --------------------------------------------------------------------------------- - * OPERATIONS - */ - -static int -load_soa_ns_attributes (const char *dn, char **soa_result, char ***ns_result) -{ - Slapi_Entry **entries; - struct berval **values, **v; - Slapi_PBlock *pb; - Slapi_Attr *attr; - LDAPControl *ctrl; - char *attrs[2]; - char *soa, **ns; - int rc, code, num, i; - - trace (dn); - assert (dn && dn[0]); - assert (dnsnotify_soa_attribute); - assert (dnsnotify_ns_attribute); - - ctrl = NULL; /* No controls */ - attrs[0] = (char*)dnsnotify_soa_attribute; - attrs[1] = NULL; - - trace ("performing internal search"); - - /* Do the actual search */ - pb = slapi_search_internal ((char*)dn, LDAP_SCOPE_BASE, "(objectClass=*)", &ctrl, attrs, 0); - return_val_if_fail (pb, 0); - - /* Was it successful? */ - code = -1; - rc = slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_RESULT, &code); - return_val_if_fail (rc >= 0, 0); - if (code != LDAP_SUCCESS) { - log_plugin ("error loading attribute %s from %s (code %d)", dnsnotify_soa_attribute, dn, code); - slapi_pblock_destroy (pb); - trace ("failure"); - return 0; - } - - /* Dig out all the entries */ - entries = NULL; - slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); - return_val_if_fail (entries, 0); - - soa = NULL; - if (entries[0]) { - if (slapi_entry_attr_find (entries[0], (char*)dnsnotify_soa_attribute, &attr) >= 0 && attr && - slapi_attr_get_values (attr, &values) >= 0 && values && values[0]) { - - /* Convert the berval into a string */ - soa = slapi_ch_malloc (values[0]->bv_len + 1); - if (values[0]->bv_len) - memcpy (soa, values[0]->bv_val, values[0]->bv_len); - soa[values[0]->bv_len] = 0; - } - - if (slapi_entry_attr_find (entries[0], (char*)dnsnotify_ns_attribute, &attr) >= 0 && attr && - slapi_attr_get_values (attr, &values) >= 0 && values) { - - num = 0; - for (v = values; *v; ++v) - ++num; - - ns = (char**)slapi_ch_calloc (num, sizeof (char*)); - for (i = 0; i < num; ++i) { - ns[i] = slapi_ch_malloc (values[i]->bv_len + 1); - if (values[i]->bv_len) - memcpy (ns[i], values[i]->bv_val, values[i]->bv_len); - ns[i][values[i]->bv_len] = 0; - } - } - } - - slapi_pblock_destroy (pb); - - /* Only proceed if we have all the data we need */ - if (soa && soa[0] && ns && ns[0] && ns[0]) { - *soa_result = soa; - *ns_result = ns; - return 1; - } - - slapi_ch_free_string (&soa); - slapi_ch_array_free (ns); - - return 0; -} - -static void -kill_notify_process (void) -{ - int status; - - if (dnsnotify_pipe != -1) - close (dnsnotify_pipe); - dnsnotify_pipe = -1; - - if (dnsnotify_pid != -1) { - if (waitpid (dnsnotify_pid, &status, WNOHANG) == 0) { - /* We can play rough, because we know process can take it */ - if (kill (dnsnotify_pid, SIGKILL) >= 0) - waitpid (dnsnotify_pid, &status, 0); - } - dnsnotify_pid = -1; - } -} - -static int -fork_notify_process (void) -{ - int open_max, fd; - int commpipe[2]; - char *args[3]; - pid_t pid; - - if (pipe (commpipe) < 0) { - log_plugin ("couldn't create communication pipe for child process: %s", strerror (errno)); - return -1; - } - - pid = fork(); - switch (pid) { - case -1: - log_plugin ("couldn't fork for child notify process: %s", strerror (errno)); - close (commpipe[0]); - close (commpipe[1]); - return -1; - - /* The child, continues below */ - case 0: - break; - - /* The parent */ - default: - - /* close read end */ - close (commpipe[0]); - - /* Kill any previous process */ - kill_notify_process (); - - /* hang onto write end, and new pid */ - dnsnotify_pipe = commpipe[1]; - dnsnotify_pid = pid; - - return 0; - }; - - /* The child process, here */ - close (commpipe[1]); - - /* Dup the pipe into stdin of the process */ - if (dup2 (commpipe[0], 0) < 0) - log_plugin ("couldn't setup stdin on notify child process: %s", strerror (errno)); - - /* Close all other file descriptors */ - open_max = sysconf (_SC_OPEN_MAX); - for (fd = 3; fd < open_max; ++fd) - close (fd); - - args[0] = DNS_NOTIFY_PATH; - args[1] = "-s"; - args[2] = NULL; - - execv (args[0], args); - log_plugin ("couldn't launch '%s' process: %s", DNS_NOTIFY_PATH, strerror (errno)); - _exit (1); -} - -static ssize_t -write_all (int fd, const void *b, size_t len) -{ - const unsigned char *buf = (const unsigned char*)b; - ssize_t l, left = len; - - while (left > 0) { - l = write (fd, buf, len); - if (l < 0) { - if (errno == EINTR && errno == EAGAIN) - continue; - return -1; - } else { - left -= l; - buf += l; - } - } - - return len; -} - -static char* -prep_soa_domain (char *soa) -{ - size_t at; - - assert (soa && soa[0]); - - /* Find the first space in the SOA and cut it off there */ - while (soa[0] && isspace (soa[0])) - ++soa; - at = strcspn (soa, " \t\n\r\v"); - if (at == 0) { - log_plugin ("invalid SOA present"); - return NULL; - } - - soa[at] = 0; - trace (soa); - return soa; -} - -static void -notify_dns_slaves (char *soa, char **ns) -{ - int i, complete = 1; - char *n; - - trace (soa); - - assert (ns); - assert (soa && soa[0]); - - if (!*ns) - return; - - soa = prep_soa_domain (soa); - if (!soa) - return; - - slapi_lock_mutex (dnsnotify_mutex); - - /* Try this twice in case things have closed up shop */ - for (i = 0; i < 2; ++i) { - - if (dnsnotify_pipe < 0 || i > 0) - if (fork_notify_process () < 0) - break; - - assert (dnsnotify_pipe >= 0); - - for (; *ns; ++ns) { - n = *ns; - - /* An empty string ? */ - while (n[0] && isspace (n[0])) - ++n; - if (!n[0]) - continue; - - if (write_all (dnsnotify_pipe, "NOTIFY: ", 8) < 0 || - write_all (dnsnotify_pipe, soa, strlen (soa)) < 0 || - write_all (dnsnotify_pipe, " ", 1) < 0 || - write_all (dnsnotify_pipe, *ns, strlen (*ns)) < 0 || - write_all (dnsnotify_pipe, "\n", 1) < 0) { - if (errno == EPIPE) { - complete = 0; - break; - } - log_plugin ("couldn't write data to child notify process: %s", strerror (errno)); - } - } - - if (complete) - break; - } - - slapi_unlock_mutex (dnsnotify_mutex); -} - -static int -slapi_dnsnotify_modify (Slapi_PBlock *pb) -{ - LDAPMod **mods, **m, *mod; - char *dn, *soa, **ns; - int rc, code; - - return_val_if_fail (pb, -1); - - trace ("detect modify"); - - /* 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); - - for (m = mods; *m; ++m) { - mod = *m; - trace (mod->mod_type); - if (strcmp (mod->mod_type, dnsnotify_soa_attribute) == 0) { - if (load_soa_ns_attributes (dn, &soa, &ns)) { - notify_dns_slaves (soa, ns); - slapi_ch_array_free (ns); - slapi_ch_free_string (&soa); - } - break; - } - } - - slapi_ch_free_string (&dn); - return 0; -} - -static int -slapi_dnsnotify_add (Slapi_PBlock *pb) -{ - char *dn, *soa, **ns; - int rc, code, ret; - - 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); - - /* A DN that is an SOA? */ - if (load_soa_ns_attributes (dn, &soa, &ns)) { - notify_dns_slaves (soa, ns); - slapi_ch_free_string (&soa); - slapi_ch_array_free (ns); - } - - slapi_ch_free_string (&dn); - return ret; -} - -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) -{ - if (dnsnotify_mutex) - slapi_lock_mutex (dnsnotify_mutex); - - kill_notify_process (); - - if (dnsnotify_mutex) { - slapi_unlock_mutex (dnsnotify_mutex); - slapi_destroy_mutex (dnsnotify_mutex); - dnsnotify_mutex = NULL; - } - - return 0; -} - -int -plugin_init (Slapi_PBlock *pb) -{ - char **argv = NULL; - int argc = 0; - int rc; - - 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); - - if (argc >= 1) - dnsnotify_soa_attribute = argv[0]; - if (argc >= 2) - dnsnotify_ns_attribute = argv[1]; - if (argc > 2) - log_plugin ("extra arguments present"); - - if (!dnsnotify_soa_attribute || !dnsnotify_soa_attribute[0]) { - log_plugin ("DNS SOA attribute specified for plugin is empty"); - return -1; - } - - if (!dnsnotify_ns_attribute || !dnsnotify_ns_attribute[0]) { - log_plugin ("DNS SOA attribute specified for plugin is empty"); - 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; - } - - /* - * TODO: Add support for changing the default attributes and search uri - * Accept an argument for this. - */ - - /* Setup the entry add/mobify functions */ - if (slapi_pblock_set (pb, SLAPI_PLUGIN_POST_ADD_FN, (void*)slapi_dnsnotify_add) != 0 || - slapi_pblock_set (pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void*)slapi_dnsnotify_modify)) { - log_plugin ("error registering plugin hooks"); - return -1; - } - - assert (!dnsnotify_mutex); - dnsnotify_mutex = slapi_new_mutex (); - return_val_if_fail (dnsnotify_mutex, -1); - - log_plugin ("%s initialized", PLUGIN_NAME); - return 0; -} - |