diff --git a/ldpd/lde.c b/ldpd/lde.c index 91b2b1727f..a28862881d 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -58,7 +58,7 @@ struct ldpd_conf *ldeconf; struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs); static struct imsgev *iev_ldpe; -static struct imsgev *iev_main; +static struct imsgev *iev_main, *iev_main_sync; /* Master of threads. */ struct thread_master *master; @@ -133,15 +133,18 @@ lde(const char *user, const char *group) /* setup signal handler */ signal_init(master, array_size(lde_signals), lde_signals); - /* setup pipe and event handler to the parent process */ - if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) + /* setup pipes and event handlers to the parent process */ + if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL) fatal(NULL); - imsg_init(&iev_main->ibuf, 3); + imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); iev_main->handler_read = lde_dispatch_parent; iev_main->ev_read = thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd); iev_main->handler_write = ldp_write_handler; - iev_main->ev_write = NULL; + + if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL) + fatal(NULL); + imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC); /* start the LIB garbage collector */ lde_gc_start_timer(); @@ -162,6 +165,8 @@ lde_shutdown(void) close(iev_ldpe->ibuf.fd); msgbuf_clear(&iev_main->ibuf.w); close(iev_main->ibuf.fd); + msgbuf_clear(&iev_main_sync->ibuf.w); + close(iev_main_sync->ibuf.fd); lde_gc_stop_timer(); lde_nbr_clear(); @@ -171,6 +176,7 @@ lde_shutdown(void) free(iev_ldpe); free(iev_main); + free(iev_main_sync); log_info("label decision engine exiting"); exit(0); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index c9f4e37eee..6fd4251edc 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -42,7 +42,7 @@ #include "qobj.h" static void ldpd_shutdown(void); -static pid_t start_child(enum ldpd_process, char *, int, +static pid_t start_child(enum ldpd_process, char *, int, int, const char *, const char *); static int main_dispatch_ldpe(struct thread *); static int main_dispatch_lde(struct thread *); @@ -77,8 +77,8 @@ DEFINE_QOBJ_TYPE(ldpd_conf) struct ldpd_global global; struct ldpd_conf *ldpd_conf; -static struct imsgev *iev_ldpe; -static struct imsgev *iev_lde; +static struct imsgev *iev_ldpe, *iev_ldpe_sync; +static struct imsgev *iev_lde, *iev_lde_sync; static pid_t ldpe_pid; static pid_t lde_pid; @@ -207,8 +207,8 @@ main(int argc, char *argv[]) { char *saved_argv0; int lflag = 0, eflag = 0; - int pipe_parent2ldpe[2]; - int pipe_parent2lde[2]; + int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2]; + int pipe_parent2lde[2], pipe_parent2lde_sync[2]; char *p; char *vty_addr = NULL; int vty_port = LDP_VTY_PORT; @@ -347,22 +347,34 @@ main(int argc, char *argv[]) if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1) fatal("socketpair"); + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, + pipe_parent2ldpe_sync) == -1) + fatal("socketpair"); if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1) fatal("socketpair"); + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, + pipe_parent2lde_sync) == -1) + fatal("socketpair"); sock_set_nonblock(pipe_parent2ldpe[0]); sock_set_cloexec(pipe_parent2ldpe[0]); sock_set_nonblock(pipe_parent2ldpe[1]); sock_set_cloexec(pipe_parent2ldpe[1]); + sock_set_nonblock(pipe_parent2ldpe_sync[0]); + sock_set_cloexec(pipe_parent2ldpe_sync[0]); + sock_set_cloexec(pipe_parent2ldpe_sync[1]); sock_set_nonblock(pipe_parent2lde[0]); sock_set_cloexec(pipe_parent2lde[0]); sock_set_nonblock(pipe_parent2lde[1]); sock_set_cloexec(pipe_parent2lde[1]); + sock_set_nonblock(pipe_parent2lde_sync[0]); + sock_set_cloexec(pipe_parent2lde_sync[0]); + sock_set_cloexec(pipe_parent2lde_sync[1]); /* start children */ lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0, - pipe_parent2lde[1], user, group); + pipe_parent2lde[1], pipe_parent2lde_sync[1], user, group); ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0, - pipe_parent2ldpe[1], user, group); + pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1], user, group); /* drop privileges */ if (user) @@ -378,22 +390,34 @@ main(int argc, char *argv[]) ldp_zebra_init(master); /* setup pipes to children */ - if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL || - (iev_lde = malloc(sizeof(struct imsgev))) == NULL) + if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL || + (iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL || + (iev_lde = calloc(1, sizeof(struct imsgev))) == NULL || + (iev_lde_sync = calloc(1, sizeof(struct imsgev))) == NULL) fatal(NULL); imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]); iev_ldpe->handler_read = main_dispatch_ldpe; iev_ldpe->ev_read = thread_add_read(master, iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd); iev_ldpe->handler_write = ldp_write_handler; - iev_ldpe->ev_write = NULL; + + imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]); + iev_ldpe_sync->handler_read = main_dispatch_ldpe; + iev_ldpe_sync->ev_read = thread_add_read(master, + iev_ldpe_sync->handler_read, iev_ldpe_sync, iev_ldpe_sync->ibuf.fd); + iev_ldpe_sync->handler_write = ldp_write_handler; imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]); iev_lde->handler_read = main_dispatch_lde; iev_lde->ev_read = thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd); iev_lde->handler_write = ldp_write_handler; - iev_lde->ev_write = NULL; + + imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]); + iev_lde_sync->handler_read = main_dispatch_lde; + iev_lde_sync->ev_read = thread_add_read(master, + iev_lde_sync->handler_read, iev_lde_sync, iev_lde_sync->ibuf.fd); + iev_lde_sync->handler_write = ldp_write_handler; if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf)) fatal("could not establish imsg links"); @@ -466,8 +490,8 @@ ldpd_shutdown(void) } static pid_t -start_child(enum ldpd_process p, char *argv0, int fd, const char *user, - const char *group) +start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync, + const char *user, const char *group) { char *argv[7]; int argc = 0; @@ -479,12 +503,15 @@ start_child(enum ldpd_process p, char *argv0, int fd, const char *user, case 0: break; default: - close(fd); + close(fd_async); + close(fd_sync); return (pid); } - if (dup2(fd, 3) == -1) - fatal("cannot setup imsg fd"); + if (dup2(fd_async, LDPD_FD_ASYNC) == -1) + fatal("cannot setup imsg async fd"); + if (dup2(fd_sync, LDPD_FD_SYNC) == -1) + fatal("cannot setup imsg sync fd"); argv[argc++] = argv0; switch (p) { @@ -702,10 +729,11 @@ main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len) void imsg_event_add(struct imsgev *iev) { - THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev, - iev->ibuf.fd); + if (iev->handler_read) + THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev, + iev->ibuf.fd); - if (iev->ibuf.w.queued) + if (iev->handler_write && iev->ibuf.w.queued) THREAD_WRITE_ON(master, iev->ev_write, iev->handler_write, iev, iev->ibuf.fd); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 3f6d7ac569..2c9706cf47 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -33,6 +33,9 @@ #define CONF_FILE "/etc/ldpd.conf" #define LDPD_USER "_ldpd" +#define LDPD_FD_ASYNC 3 +#define LDPD_FD_SYNC 4 + #define LDPD_OPT_VERBOSE 0x00000001 #define LDPD_OPT_VERBOSE2 0x00000002 #define LDPD_OPT_NOACTION 0x00000004 diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 1a60af8f41..236e71f322 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -48,7 +48,7 @@ struct ldpd_conf *leconf; struct ldpd_sysdep sysdep; #endif -static struct imsgev *iev_main; +static struct imsgev *iev_main, *iev_main_sync; static struct imsgev *iev_lde; #ifdef __OpenBSD__ static struct thread *pfkey_ev; @@ -142,15 +142,18 @@ ldpe(const char *user, const char *group) /* setup signal handler */ signal_init(master, array_size(ldpe_signals), ldpe_signals); - /* setup pipe and event handler to the parent process */ - if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) + /* setup pipes and event handlers to the parent process */ + if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL) fatal(NULL); - imsg_init(&iev_main->ibuf, 3); + imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); iev_main->handler_read = ldpe_dispatch_main; iev_main->ev_read = thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd); iev_main->handler_write = ldp_write_handler; - iev_main->ev_write = NULL; + + if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL) + fatal(NULL); + imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC); #ifdef __OpenBSD__ if (sysdep.no_pfkey == 0) @@ -191,6 +194,8 @@ ldpe_shutdown(void) msgbuf_write(&iev_main->ibuf.w); msgbuf_clear(&iev_main->ibuf.w); close(iev_main->ibuf.fd); + msgbuf_clear(&iev_main_sync->ibuf.w); + close(iev_main_sync->ibuf.fd); control_cleanup(); config_clear(leconf); @@ -215,6 +220,7 @@ ldpe_shutdown(void) /* clean up */ free(iev_lde); free(iev_main); + free(iev_main_sync); free(pkt_ptr); log_info("ldp engine exiting");