From 51534ef3a17fcb9b5f0748e39ddfd46a771a2268 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sat, 19 Jan 2013 16:13:50 +0100 Subject: [PATCH] lldpd: invoke lldpcli at start To configure itself, lldpd now invokes lldpcli when starting. Currently, it does not really check if everything works as expected but in the future, lldpcli will ask lldpd to "start". The configuration files are: - ${sysconfdir}/lldpd.conf - ${sysconfdir}/lldpd.d/*.conf --- src/client/lldpcli.c | 4 ++- src/daemon/Makefile.am | 1 + src/daemon/lldpd.8 | 7 +++++ src/daemon/lldpd.c | 60 ++++++++++++++++++++++++++++++++++++++++-- src/daemon/priv.c | 28 +++++++++++++++----- 5 files changed, 90 insertions(+), 10 deletions(-) diff --git a/src/client/lldpcli.c b/src/client/lldpcli.c index f878c97c..5834d5e0 100644 --- a/src/client/lldpcli.c +++ b/src/client/lldpcli.c @@ -355,7 +355,7 @@ main(int argc, char *argv[]) int ch, debug = 1, rc = EXIT_FAILURE; const char *fmt = "plain"; lldpctl_conn_t *conn = NULL; - const char *options = is_lldpctl(argv[0])?"hdvf:":"hdvf:c:"; + const char *options = is_lldpctl(argv[0])?"hdvf:":"hdsvf:c:"; int gotinputs = 0; struct inputs inputs; @@ -365,6 +365,7 @@ main(int argc, char *argv[]) while ((ch = getopt(argc, argv, options)) != -1) { switch (ch) { case 'd': debug++; break; + case 's': debug--; break; } } log_init(debug, __progname); @@ -374,6 +375,7 @@ main(int argc, char *argv[]) while ((ch = getopt(argc, argv, options)) != -1) { switch (ch) { case 'd': break; + case 's': break; case 'h': usage(); break; diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index a0dc7bf5..21567af8 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -17,6 +17,7 @@ liblldpd_la_SOURCES = \ interfaces.c \ event.c lldpd.c liblldpd_la_CFLAGS = $(AM_CFLAGS) @LIBEVENT_CFLAGS@ +liblldpd_la_CPPFLAGS = -DSYSCONFDIR='"$(sysconfdir)"' -DLLDPCLI_PATH='"$(sbindir)/lldpcli"' liblldpd_la_LIBADD = \ $(top_builddir)/src/libcommon-daemon-client.la \ $(top_builddir)/src/libcommon-daemon-lib.la @LIBEVENT_LIBS@ diff --git a/src/daemon/lldpd.8 b/src/daemon/lldpd.8 index 580439c3..57520d14 100644 --- a/src/daemon/lldpd.8 +++ b/src/daemon/lldpd.8 @@ -31,6 +31,7 @@ .Op Fl C Ar interfaces .Op Fl M Ar class .Op Fl H Ar hide +.Op Fl L Ar lldpcli .Sh DESCRIPTION .Nm is a daemon able to receive and send @@ -233,6 +234,12 @@ transmit sensible information like serial numbers. Filter neighbors. See section .Sx FILTERING NEIGHBORS for details. +.It Fl L Ar lldpcli +Provide an alternative path to +.Nm lldpcli +for configuration. If empty, does not use +.Nm lldpcli +for configuration. .It Fl v Show .Nm diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index 356a1260..855034d4 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -992,6 +992,51 @@ lldpd_exit(struct lldpd *cfg) } } +/** + * Run lldpcli to configure lldpd. + * + * @return PID of running lldpcli or -1 if error. + */ +static pid_t +lldpd_configure(int debug, const char *path) +{ + pid_t lldpcli = fork(); + int devnull; + + switch (lldpcli) { + case -1: + log_warn("main", "unable to fork"); + return -1; + case 0: + /* Child, exec lldpcli */ + if ((devnull = open("/dev/null", O_RDWR, 0)) != -1) { + char sdebug[debug + 3]; + memset(sdebug, 'd', debug + 3); + sdebug[debug + 2] = '\0'; + sdebug[0] = '-'; sdebug[1] = 's'; + + dup2(devnull, STDIN_FILENO); + if (devnull > 2) close(devnull); + + log_debug("main", "invoke %s %s", path, sdebug); + if (execl(path, "lldpcli", sdebug, + "-c", SYSCONFDIR "/lldpd.conf", + "-c", SYSCONFDIR "/lldpd.d", + NULL) == -1) { + log_warn("main", "unable to execute %s", path); + log_warnx("main", "configuration may be incomplete"); + } + } + exit(127); + break; + default: + /* Father, don't do anything stupid */ + return lldpcli; + } + /* Should not be here */ + return -1; +} + struct intint { int a; int b; }; static const struct intint filters[] = { { 0, 0 }, @@ -1108,8 +1153,8 @@ lldpd_main(int argc, char *argv[]) char *mgmtp = NULL; char *cidp = NULL; char *interfaces = NULL; - char *popt, opts[] = - "H:vhkrdD:xX:m:4:6:I:C:p:M:P:S:i@ "; + char *popt, opts[] = + "H:vhkrdD:xX:m:4:6:I:C:p:M:P:S:iL:@ "; int i, found, advertise_version = 1; #ifdef ENABLE_LLDPMED int lldpmed = 0, noinventory = 0; @@ -1117,6 +1162,7 @@ lldpd_main(int argc, char *argv[]) char *descr_override = NULL; char *platform_override = NULL; char *lsb_release = NULL; + const char *lldpcli = LLDPCLI_PATH; int smart = 15; int receiveonly = 0; int ctl; @@ -1163,6 +1209,9 @@ lldpd_main(int argc, char *argv[]) case 'C': cidp = optarg; break; + case 'L': + if (strlen(optarg)) lldpcli = optarg; + else lldpcli = NULL; case 'k': advertise_version = 0; break; @@ -1284,6 +1333,13 @@ lldpd_main(int argc, char *argv[]) /* Disable SIGPIPE */ signal(SIGPIPE, SIG_IGN); + /* Configuration with lldpcli */ + if (lldpcli) { + log_debug("main", "invoking lldpcli for configuration"); + if (lldpd_configure(debug, lldpcli) == -1) + fatal("main", "unable to spawn lldpcli"); + } + /* Daemonization, unless started by upstart, systemd or launchd or debug */ #ifndef HOST_OS_OSX if (!lldpd_started_by_upstart() && !lldpd_started_by_systemd() && diff --git a/src/daemon/priv.c b/src/daemon/priv.c index ad4746d2..8fdd7c9b 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -619,11 +619,7 @@ priv_loop() } static void -priv_exit() -{ - int status; - int rc; - rc = waitpid(monitored, &status, WNOHANG); +priv_exit_rc_status(int rc, int status) { switch (rc) { case 0: log_debug("privsep", "killing child"); @@ -655,6 +651,15 @@ priv_exit() } } +static void +priv_exit() +{ + int status; + int rc; + rc = waitpid(monitored, &status, WNOHANG); + priv_exit_rc_status(rc, status); +} + /* If priv parent gets a TERM or HUP, pass it through to child instead */ static void sig_pass_to_chld(int sig) @@ -669,8 +674,17 @@ sig_pass_to_chld(int sig) static void sig_chld(int sig) { - log_debug("privsep", "received signal %d, exiting", sig); - priv_exit(); + int status; + int rc = waitpid(monitored, &status, WNOHANG); + if (rc == 0) { + while ((rc = waitpid(-1, &status, WNOHANG)) > 0) { + if (rc == monitored) priv_exit_rc_status(rc, status); + else log_debug("privsep", "unrelated process %d has died", + rc); + } + return; + } + priv_exit_rc_status(rc, status); } /* Initialization */ -- 2.39.5