summaryrefslogtreecommitdiff
path: root/plugin/slapi-dnsnotify.c
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2008-06-09 17:22:43 +0000
committerStef Walter <stef@memberwebs.com>2008-06-09 17:22:43 +0000
commitb9ecd6e5e5b87fe1c4dab960e92246772002dd6a (patch)
treeeb05eb48888e391678fa706ec5f62b012df2456e /plugin/slapi-dnsnotify.c
parent3add3c0e19b659427a2624ec85daf67019b8ed7f (diff)
Merge the two dns plugins
Diffstat (limited to 'plugin/slapi-dnsnotify.c')
-rw-r--r--plugin/slapi-dnsnotify.c529
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;
-}
-