]> the.earth.li Git - onak.git/commitdiff
Add keyd support for systemd socket activation
authorJonathan McDowell <noodles@earth.li>
Tue, 23 Sep 2014 21:41:38 +0000 (22:41 +0100)
committerJonathan McDowell <noodles@earth.li>
Tue, 23 Sep 2014 21:41:38 +0000 (22:41 +0100)
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
configure.ac
debian/control
keyd.c

index c35db1aba2e26d0727001d2a69b607b5bcaef8ce..c5725935e50ca98387bc59f20d7c80d6407dabf4 100644 (file)
@@ -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) \
index 09c5ac35172d586eec6b58730aa952cee7e3bfc5..740f79cbafc239d2153d8a96d50589d8c89ae62a 100644 (file)
@@ -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"
index 4e21b7a751cd70970aba21caaf51cce6023a0f7c..c9dbfc031d9880f0ec46487b12c7c981e8d29d12 100644 (file)
@@ -3,7 +3,7 @@ Section: net
 Priority: optional
 Maintainer: Jonathan McDowell <noodles@earth.li>
 Uploaders: Ross Burton <ross@debian.org>
-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 18e9ddca873a84e37c172408bb0ecdc20b611b19..6a171d43b3f575e8b92b17c2f96c6b33f0b8ff97 100644 (file)
--- a/keyd.c
+++ b/keyd.c
 #include <time.h>
 #include <unistd.h>
 
+#include "config.h"
+
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include "charfuncs.h"
 #include "cleanup.h"
 #include "keyd.h"
 /* 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);