summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/server-mainloop.c77
-rw-r--r--plugin/Makefile.am2
-rw-r--r--plugin/slapi-dnsnotify.c76
-rw-r--r--tools/Makefile.am10
-rw-r--r--tools/notify-dns-slaves.c (renamed from tools/notify-slaves.c)59
5 files changed, 132 insertions, 92 deletions
diff --git a/common/server-mainloop.c b/common/server-mainloop.c
index fcd471d..1ba5085 100644
--- a/common/server-mainloop.c
+++ b/common/server-mainloop.c
@@ -45,6 +45,7 @@ typedef struct _socket_callback {
int fd;
server_socket_callback callback;
void *arg;
+ int closed;
struct _socket_callback *next;
} socket_callback;
@@ -54,6 +55,7 @@ typedef struct _timer_callback {
struct timeval interval;
server_timer_callback callback;
void* arg;
+ int closed;
struct _timer_callback *next;
} timer_callback;
@@ -166,35 +168,33 @@ add_timer (int ms, int oneshot, server_timer_callback callback, void *arg)
return 0;
}
-static timer_callback*
-remove_timer(timer_callback *timcb)
+static void
+remove_closed (void)
{
- timer_callback *cb;
- timer_callback *next;
-
- if (!ctx.timers)
- return NULL;
-
- /* First in list */;
- if (ctx.timers == timcb) {
- cb = ctx.timers;
- ctx.timers = ctx.timers->next;
- free (cb);
- return ctx.timers;
+ timer_callback **tcb, *timcb;
+ socket_callback **scb, *sockcb;
+
+ for (tcb = &ctx.timers; *tcb; ) {
+ timcb = *tcb;
+ if (timcb->closed) {
+ *tcb = timcb->next;
+ free (timcb);
+ continue;
+ } else {
+ tcb = &timcb->next;
+ }
}
- /* One ahead processing of rest */
- for (cb = ctx.timers; cb->next; cb = cb->next) {
- if(cb->next == timcb) {
- next = cb->next->next;
- free (cb->next);
- cb->next = next;
- return cb->next;
+ for (scb = &ctx.callbacks; *scb; ) {
+ sockcb = *scb;
+ if (sockcb->closed) {
+ *scb = sockcb->next;
+ free (sockcb);
+ continue;
+ } else {
+ scb = &sockcb->next;
}
}
-
- /* Couldn't remove, return self */
- return timcb;
}
void
@@ -248,7 +248,7 @@ server_run (void)
struct timeval *timeout;
struct timeval tv, current;
timer_callback *timcb;
- socket_callback *sockcb, *socknx;
+ socket_callback *sockcb;
fd_set rfds, wfds;
int r;
@@ -268,9 +268,12 @@ server_run (void)
return -1;
/* Cycle through timers */
- for (timcb = ctx.timers; timcb; ) {
+ for (timcb = ctx.timers; timcb; timcb = timcb->next) {
assert (timcb->callback);
+ if (timcb->closed)
+ continue;
+
/* Call any timers that have already passed */
if (timeval_compare (&current, &timcb->at) >= 0) {
@@ -287,7 +290,7 @@ server_run (void)
/* Otherwise remove it. Either one shot, or returned 0 */
} else {
- timcb = remove_timer (timcb);
+ timcb->closed = 1;
continue;
}
}
@@ -295,8 +298,6 @@ server_run (void)
/* Get soonest timer */
if (!timeout || timeval_compare (&timcb->at, timeout) < 0)
timeout = &timcb->at;
-
- timcb = timcb->next;
}
/* Convert to an offset */
@@ -309,6 +310,10 @@ server_run (void)
if (ctx.stopped)
continue;
+ remove_closed ();
+ if (!ctx.callbacks && !ctx.timers)
+ break;
+
/* fprintf(stderr, "selecting with timeout: ");
timeval_dump(timeout);
fprintf(stderr, "\n"); */
@@ -329,17 +334,16 @@ server_run (void)
if(r == 0)
continue;
- for (sockcb = ctx.callbacks; sockcb; ) {
+ for (sockcb = ctx.callbacks; sockcb; sockcb = sockcb->next) {
assert (sockcb->fd != -1);
- socknx = sockcb->next;
+ if (sockcb->closed)
+ continue;
/* Call any that are set */
if (FD_ISSET (sockcb->fd, &rfds))
(sockcb->callback) (sockcb->fd, SERVER_READ, sockcb->arg);
if (FD_ISSET (sockcb->fd, &wfds))
(sockcb->callback) (sockcb->fd, SERVER_WRITE, sockcb->arg);
-
- sockcb = socknx;
}
}
@@ -405,17 +409,14 @@ server_unwatch (int fd)
/* First in list */;
if (ctx.callbacks->fd == fd) {
- cb = ctx.callbacks;
- ctx.callbacks = cb->next;
- free (cb);
+ ctx.callbacks->closed = 1;
return;
}
/* One ahead processing of rest */
for (cb = ctx.callbacks; cb->next; cb = cb->next) {
if (cb->next->fd == fd) {
- cb->next = cb->next->next;
- free (cb->next);
+ cb->next->closed = 1;
return;
}
}
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index d1887a3..9b8f4de 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -2,7 +2,7 @@
INCLUDES = \
-I$(top_srcdir) \
-DSTRSET_CUSTMEM=1 \
- -DDNS_NOTIFY_PATH=\"$(bindir)/notify-slaves\"
+ -DDNS_NOTIFY_PATH=\"$(bindir)/notify-dns-slaves\"
lib_LTLIBRARIES = slapi-dnsnotify.la
diff --git a/plugin/slapi-dnsnotify.c b/plugin/slapi-dnsnotify.c
index b871c86..329b913 100644
--- a/plugin/slapi-dnsnotify.c
+++ b/plugin/slapi-dnsnotify.c
@@ -190,13 +190,32 @@ load_soa_ns_attributes (const char *dn, char **soa_result, char ***ns_result)
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)
{
- pid_t pid;
- int status;
+ 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));
@@ -221,18 +240,11 @@ fork_notify_process (void)
/* close read end */
close (commpipe[0]);
- /* hang onto write end */
- if (dnsnotify_pipe != -1)
- close (dnsnotify_pipe);
- dnsnotify_pipe = commpipe[1];
+ /* Kill any previous process */
+ kill_notify_process ();
- 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);
- }
- }
+ /* hang onto write end, and new pid */
+ dnsnotify_pipe = commpipe[1];
dnsnotify_pid = pid;
return 0;
@@ -245,6 +257,11 @@ fork_notify_process (void)
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;
@@ -285,7 +302,7 @@ prep_soa_domain (char *soa)
/* Find the first space in the SOA and cut it off there */
while (soa[0] && isspace (soa[0]))
++soa;
- at = strspn (soa, " \t\n\r\v");
+ at = strcspn (soa, " \t\n\r\v");
if (at == 0) {
log_plugin ("invalid SOA present");
return NULL;
@@ -334,11 +351,11 @@ notify_dns_slaves (char *soa, char **ns)
if (!n[0])
continue;
- if (write_all (dnsnotify_pipe, "NOTIFY: ", 5) < 0 ||
+ 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 (soa)) < 0 ||
- write_all (dnsnotify_pipe, "\n", 2) < 0) {
+ write_all (dnsnotify_pipe, *ns, strlen (*ns)) < 0 ||
+ write_all (dnsnotify_pipe, "\n", 1) < 0) {
if (errno == EPIPE) {
complete = 0;
break;
@@ -363,6 +380,8 @@ slapi_dnsnotify_modify (Slapi_PBlock *pb)
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);
@@ -380,6 +399,7 @@ slapi_dnsnotify_modify (Slapi_PBlock *pb)
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);
@@ -432,8 +452,25 @@ static Slapi_PluginDesc plugin_description = {
"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)
+plugin_init (Slapi_PBlock *pb)
{
char **argv = NULL;
int argc = 0;
@@ -464,7 +501,8 @@ plugin_init (Slapi_PBlock* pb)
}
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_DESCRIPTION, &plugin_description) != 0 ||
+ slapi_pblock_set (pb, SLAPI_PLUGIN_DESTROY_FN, plugin_destroy)) {
log_plugin ("error registring plugin");
return -1;
}
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 19bbc50..fe0ffc5 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -4,14 +4,14 @@ INCLUDES = \
$(PTHREAD_CFLAGS)
bin_PROGRAMS = \
- notify-slaves
+ notify-dns-slaves
-notify_slaves_SOURCES = \
- notify-slaves.c \
+notify_dns_slaves_SOURCES = \
+ notify-dns-slaves.c \
../common/async-resolver.c \
../common/server-mainloop.c \
../common/sock-any.c
# TODO: Somehow PTHREAD_LIBS isn't setup on linux gcc
-notify_slaves_LDFLAGS = -pthread
-notify_slaves_LIBS = $(PTHREAD_LIBS) \ No newline at end of file
+notify_dns_slaves_LDFLAGS = -pthread
+notify_dns_slaves_LIBS = $(PTHREAD_LIBS) \ No newline at end of file
diff --git a/tools/notify-slaves.c b/tools/notify-dns-slaves.c
index ebd2262..96f2ea7 100644
--- a/tools/notify-slaves.c
+++ b/tools/notify-dns-slaves.c
@@ -105,13 +105,13 @@ static int the_socket6 = -1;
static char stdin_buffer[LINE_LENGTH + 1];
static size_t stdin_offset = 0;
-static int stdin_closed = 0;
static int processing_active = 0;
+static int input_complete = 0;
static unsigned int unique_identifier = 1;
static int is_helper = 0;
-static int debug_level = LOG_WARNING;
+static int debug_level = LOG_INFO;
typedef struct _notification {
struct _notification *next;
@@ -164,9 +164,10 @@ vmessage(int level, int erno, const char* msg, va_list ap)
}
/* Either to syslog or stderr */
- if (is_helper && level < LOG_DEBUG)
+ if (is_helper && level != LOG_DEBUG)
vsyslog (level, buf, ap);
- vwarnx(buf, ap);
+
+ vwarnx (buf, ap);
}
static void
@@ -366,20 +367,18 @@ process_all_packets (uint64_t when, void *unused)
}
}
- not = &(*not)->next;
+ not = &notif->next;
}
/* Continue processing? */
if (the_notifications)
return 1;
- if (stdin_closed) {
- debug ("processing done, and no more input, stopping");
+ if (input_complete)
server_stop ();
- } else {
- debug ("processing done for now");
- processing_active = 0;
- }
+
+ debug ("processing done");
+ processing_active = 0;
return 0;
}
@@ -418,6 +417,7 @@ address_resolved (int ecode, struct addrinfo *ai, void *arg)
notif->server, gai_strerror (ecode));
*not = notif->next;
free (notif);
+ break;
/* A successful resolve */
} else {
@@ -426,9 +426,8 @@ address_resolved (int ecode, struct addrinfo *ai, void *arg)
SANY_LEN (notif->address) = ai->ai_addrlen;
notif->resolved = 1;
prepare_and_process (notif, server_get_time ());
+ break;
}
-
- break;
}
}
@@ -641,27 +640,25 @@ stdin_callback (int fd, int type, void *arg)
if (errno == EAGAIN || errno == EINTR)
return;
warningx ("couldn't read from stdin");
- server_unwatch (fd);
- stdin_closed = 1;
- return;
+ input_complete = 1;
} else if (num == 0) {
- stdin_closed = 1;
- server_unwatch (fd);
+ debug ("input closed");
+ input_complete = 1;
+ } else {
+ stdin_offset += num;
}
- stdin_offset += num;
-
- for (;;) {
+ do {
line = strchr (stdin_buffer, '\n');
+ if (!line && input_complete)
+ line = stdin_buffer + stdin_offset;
+
if (!line && stdin_offset >= LINE_LENGTH) {
warningx ("input line too long");
line = stdin_buffer + LINE_LENGTH;
}
- if (!line && stdin_closed)
- line = stdin_buffer + stdin_offset;
-
if (!line) /* Wait for more data */
break;
@@ -672,8 +669,12 @@ stdin_callback (int fd, int type, void *arg)
stdin_offset = LINE_LENGTH - num;
memmove (stdin_buffer, stdin_buffer + num, stdin_offset);
- if (stdin_closed)
- break;
+ } while (!input_complete);
+
+ if (input_complete) {
+ if (!the_notifications)
+ server_stop ();
+ server_unwatch (fd);
}
}
@@ -785,14 +786,14 @@ main(int argc, char *argv[])
fatal (1, "couldn't initialize DNS resolver");
if (is_helper) {
- stdin_closed = 0;
-
+ openlog ("notify-dns-slaves", 0, LOG_DAEMON);
+ input_complete = 0;
/* Watch stdin for data */
fcntl (0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NONBLOCK);
if (server_watch (0, SERVER_READ, stdin_callback, NULL) < 0)
fatal (1, "coludn't watch stdin for changes");
} else {
- stdin_closed = 1;
+ input_complete = 1;
str = argv[0];
for (i = 1; i < argc; ++i)
process_notify (str, argv[i], 0);