From 5c137b7d6af54fb54dfe13b65c933b5b6a4c764c Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Tue, 23 Sep 2014 22:41:38 +0100 Subject: [PATCH] Add keyd support for systemd socket activation If we have libsystemd-daemon available then enable support for systemd socket activation of keyd. Even if this support is compiled in we will fall back to the old behaviour of setting up our own listening Unix domain socket if systemd is not in use. --- Makefile.in | 3 ++- configure.ac | 6 +++++ debian/control | 2 +- keyd.c | 71 ++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/Makefile.in b/Makefile.in index c35db1a..c572593 100644 --- a/Makefile.in +++ b/Makefile.in @@ -78,7 +78,8 @@ endif keyd: keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o $(CC) $(LDFLAGS) $(PROGS_LDFLAGS_EXTRA) \ - -o keyd keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o $(LIBS) + -o keyd keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o $(LIBS) \ + @SYSTEMD_LIBS@ keydctl: keydctl.o onak-conf.o ll.o log.o $(CC) $(LDFLAGS) $(PROGS_LDFLAGS_EXTRA) \ diff --git a/configure.ac b/configure.ac index 09c5ac3..740f79c 100644 --- a/configure.ac +++ b/configure.ac @@ -11,6 +11,12 @@ AC_C_BIGENDIAN m4_include([m4/ax_lib_nettle.m4]) AX_LIB_NETTLE(auto) +AC_CHECK_HEADER([systemd/sd-daemon.h], [ + AC_CHECK_LIB([systemd-daemon], [sd_listen_fds], + [AC_DEFINE([HAVE_SYSTEMD], [1], [systemd-daemon is available]) + AC_SUBST([SYSTEMD_LIBS], [-lsystemd-daemon]) + ]) +]) dnl We should always have these backends available. backends="file fs keyd" diff --git a/debian/control b/debian/control index 4e21b7a..c9dbfc0 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: net Priority: optional Maintainer: Jonathan McDowell Uploaders: Ross Burton -Build-Depends: debhelper (>= 9), dh-autoreconf, libdb-dev, nettle-dev, libcurl4-gnutls-dev | libcurl-dev +Build-Depends: debhelper (>= 9), dh-autoreconf, libdb-dev, nettle-dev, libcurl4-gnutls-dev | libcurl-dev, libsystemd-daemon-dev Standards-Version: 3.9.4.0 Homepage: http://www.earth.li/projectpurple/progs/onak.html Vcs-Browser: http://the.earth.li/gitweb/?p=onak.git;a=summary diff --git a/keyd.c b/keyd.c index 18e9ddc..6a171d4 100644 --- a/keyd.c +++ b/keyd.c @@ -31,6 +31,12 @@ #include #include +#include "config.h" + +#ifdef HAVE_SYSTEMD +#include +#endif + #include "charfuncs.h" #include "cleanup.h" #include "keyd.h" @@ -46,6 +52,10 @@ /* Maximum number of clients we're prepared to accept at once */ #define MAX_CLIENTS 16 +#ifdef HAVE_SYSTEMD +static bool using_socket_activation = false; +#endif + static struct keyd_stats *stats; static void daemonize(void) @@ -189,26 +199,47 @@ static int sock_init(const char *sockname) struct sockaddr_un sock; int fd = -1; int ret = -1; +#ifdef HAVE_SYSTEMD + int n; - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (fd != -1) { - ret = fcntl(fd, F_SETFD, FD_CLOEXEC); - } + n = sd_listen_fds(0); + if (n > 1) { + logthing(LOGTHING_ERROR, + "Too many file descriptors received from systemd."); + } else if (n == 1) { + fd = SD_LISTEN_FDS_START + 0; + if (sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0) <= 0) { + logthing(LOGTHING_ERROR, + "systemd passed an invalid socket."); + fd = -1; + } + using_socket_activation = true; + } else { +#endif + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd != -1) { + ret = fcntl(fd, F_SETFD, FD_CLOEXEC); + } - if (ret != -1) { - sock.sun_family = AF_UNIX; - strncpy(sock.sun_path, sockname, sizeof(sock.sun_path) - 1); - unlink(sockname); - ret = bind(fd, (struct sockaddr *) &sock, sizeof(sock)); - } + if (ret != -1) { + sock.sun_family = AF_UNIX; + strncpy(sock.sun_path, sockname, + sizeof(sock.sun_path) - 1); + unlink(sockname); + ret = bind(fd, (struct sockaddr *) &sock, + sizeof(sock)); + } - if (ret != -1) { - ret = listen(fd, 5); - if (ret == -1) { - close(fd); - fd = -1; + if (ret != -1) { + ret = listen(fd, 5); + if (ret == -1) { + close(fd); + fd = -1; + } } +#ifdef HAVE_SYSTEMD } +#endif return fd; } @@ -680,8 +711,14 @@ int main(int argc, char *argv[]) } } dbctx->cleanupdb(dbctx); - sock_close(fd); - unlink(sockname); +#ifdef HAVE_SYSTEMD + if (!using_socket_activation) { +#endif + sock_close(fd); + unlink(sockname); +#ifdef HAVE_SYSTEMD + } +#endif } free(stats); -- 2.39.2