diff --git a/bin/named/Makefile.am b/bin/named/Makefile.am index 291bab5e2a..aec650875e 100644 --- a/bin/named/Makefile.am +++ b/bin/named/Makefile.am @@ -13,7 +13,6 @@ AM_CPPFLAGS += \ $(MAXMINDDB_CFLAGS) \ $(DNSTAP_CFLAGS) \ $(LIBUV_CFLAGS) \ - $(LIBSYSTEMD_CFLAGS) \ $(ZLIB_CFLAGS) if HAVE_JSON_C @@ -108,7 +107,6 @@ named_LDADD = \ $(MAXMINDDB_LIBS) \ $(DNSTAP_LIBS) \ $(LIBUV_LIBS) \ - $(LIBSYSTEMD_LIBS) \ $(ZLIB_LIBS) if HAVE_JSON_C diff --git a/bin/named/include/named/os.h b/bin/named/include/named/os.h index a150872f47..b38ebfad72 100644 --- a/bin/named/include/named/os.h +++ b/bin/named/include/named/os.h @@ -18,6 +18,7 @@ #include #include +#include #include void @@ -73,3 +74,15 @@ named_os_started(void); const char * named_os_uname(void); + +#ifdef __linux__ +void +named_os_notify_systemd(const char *restrict format, ...) + ISC_FORMAT_PRINTF(1, 2); + +void +named_os_notify_close(void); +#else /* __linux__ */ +#define named_os_notify_systemd(...) +#define named_os_notify_close(...) +#endif /* __linux__ */ diff --git a/bin/named/os.c b/bin/named/os.c index 91f2d52ead..52e13680a9 100644 --- a/bin/named/os.c +++ b/bin/named/os.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -60,6 +61,7 @@ static int devnullfd = -1; static struct passwd *runas_pw = NULL; static bool done_setuid = false; static int dfd[2] = { -1, -1 }; +static int notify_fd = -1; static uid_t saved_uid = (uid_t)-1; static gid_t saved_gid = (gid_t)-1; @@ -273,6 +275,79 @@ setperms(uid_t uid, gid_t gid) { } } +#ifdef __linux__ +static isc_result_t +connect_systemd_notify_unix(char *path) { + struct sockaddr_un addr; + isc_result_t result = ISC_R_SUCCESS; + size_t len; + + addr.sun_family = AF_UNIX; + + len = strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); + if (len >= sizeof(addr.sun_path)) { + return ISC_R_NOSPACE; + } + + /* Convert abstract unix sockets */ + if (addr.sun_path[0] == '@') { + addr.sun_path[0] = '\0'; + } + + notify_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (notify_fd < 0) { + return isc_errno_toresult(errno); + } + + if (connect(notify_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + result = isc_errno_toresult(errno); + close(notify_fd); + notify_fd = -1; + } + + return result; +} + +static void +setup_systemd_notify(void) { + isc_result_t result; + char *path; + + REQUIRE(notify_fd == -1); + + path = getenv("NOTIFY_SOCKET"); + + /* systemd notification is not set, oh well. */ + if (path == NULL) { + return; + } + + if (path[0] == '/' || path[0] == '@') { + result = connect_systemd_notify_unix(path); + } else if (strncmp(path, "vsock", 5) == 0) { + result = ISC_R_FAMILYNOSUPPORT; + } else { + result = ISC_R_INVALIDPROTO; + } + + if (result != ISC_R_SUCCESS) { + RUNTIME_CHECK(notify_fd == -1); + isc_log_write( + NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN, + ISC_LOG_WARNING, + "failed to connect to notification socket '%s': %s", + path, isc_result_totext(result)); + } else { + RUNTIME_CHECK(notify_fd != -1); + isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN, + ISC_LOG_INFO, + "connected to notification socket '%s'", path); + } +} +#else /* __linux__ */ +#define setup_systemd_notify(...) +#endif /* __linux__ */ + static void setup_syslog(const char *progname) { int options; @@ -287,6 +362,7 @@ setup_syslog(const char *progname) { void named_os_init(const char *progname) { setup_syslog(progname); + setup_systemd_notify(); #if HAVE_LIBCAP linux_initialprivs(); #endif /* HAVE_LIBCAP */ @@ -362,6 +438,13 @@ named_os_daemonize(void) { (void)dup2(devnullfd, STDERR_FILENO); } } + + /* + * Will be closed from SOCK_CLOEXEC but should be set to -1 again before + * reconnecting to the notification socket. + */ + notify_fd = -1; + setup_systemd_notify(); } void @@ -865,3 +948,38 @@ named_os_uname(void) { } return unamep; } + +#ifdef __linux__ +void +named_os_notify_systemd(const char *restrict format, ...) { + char buffer[512]; + va_list ap; + int len; + + if (notify_fd == -1 || format == NULL) { + return; + } + + va_start(ap, format); + len = vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + /* Be very loud if notification is too long */ + RUNTIME_CHECK(len > 0 && len < (int)sizeof(buffer)); + + if (write(notify_fd, buffer, len) != len) { + isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN, + ISC_LOG_ERROR, + "failed writing to notification socket '%s'", + isc_result_totext(isc_errno_toresult(errno))); + } +} + +void +named_os_notify_close(void) { + if (notify_fd != -1) { + close(notify_fd); + notify_fd = -1; + } +} +#endif /* __linux__ */ diff --git a/bin/named/server.c b/bin/named/server.c index bc80f14d69..b67773bd4f 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -28,10 +28,6 @@ #include #endif -#ifdef HAVE_LIBSYSTEMD -#include -#endif - #include #include #include @@ -9402,13 +9398,10 @@ view_loaded(void *arg) { ISC_LOG_NOTICE, "FIPS mode is %s", isc_crypto_fips_mode() ? "enabled" : "disabled"); -#if HAVE_LIBSYSTEMD - sd_notifyf(0, - "READY=1\n" - "STATUS=running\n" - "MAINPID=%" PRId64 "\n", - (int64_t)getpid()); -#endif /* HAVE_LIBSYSTEMD */ + named_os_notify_systemd("READY=1\n" + "STATUS=running\n" + "MAINPID=%" PRId64 "\n", + (int64_t)getpid()); atomic_store(&server->reload_status, NAMED_RELOAD_DONE); @@ -9547,9 +9540,8 @@ shutdown_server(void *arg) { bool flush = server->flushonshutdown; named_cache_t *nsc = NULL; -#if HAVE_LIBSYSTEMD - sd_notify(0, "STOPPING=1\n"); -#endif /* HAVE_LIBSYSTEMD */ + named_os_notify_systemd("STOPPING=1\n"); + named_os_notify_close(); isc_signal_stop(server->sighup); isc_signal_destroy(&server->sighup); @@ -10041,17 +10033,11 @@ reload(named_server_t *server) { isc_result_t result; atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); -#if HAVE_LIBSYSTEMD - char buf[512]; - int n = snprintf(buf, sizeof(buf), - "RELOADING=1\n" - "MONOTONIC_USEC=%" PRIu64 "\n" - "STATUS=reload command received\n", - (uint64_t)isc_time_monotonic() / NS_PER_US); - if (n > 0 && (size_t)n < sizeof(buf)) { - sd_notify(0, buf); - } -#endif /* HAVE_LIBSYSTEMD */ + + named_os_notify_systemd("RELOADING=1\n" + "MONOTONIC_USEC=%" PRIu64 "\n" + "STATUS=reload command received\n", + (uint64_t)isc_time_monotonic() / NS_PER_US); CHECK(loadconfig(server)); @@ -10066,12 +10052,10 @@ reload(named_server_t *server) { atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); } cleanup: -#if HAVE_LIBSYSTEMD - sd_notifyf(0, - "READY=1\n" - "STATUS=reload command finished: %s\n", - isc_result_totext(result)); -#endif /* HAVE_LIBSYSTEMD */ + named_os_notify_systemd("READY=1\n" + "STATUS=reload command finished: %s\n", + isc_result_totext(result)); + return result; } @@ -10542,17 +10526,11 @@ isc_result_t named_server_reconfigcommand(named_server_t *server) { isc_result_t result; atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); -#if HAVE_LIBSYSTEMD - char buf[512]; - int n = snprintf(buf, sizeof(buf), - "RELOADING=1\n" - "MONOTONIC_USEC=%" PRIu64 "\n" - "STATUS=reconfig command received\n", - (uint64_t)isc_time_monotonic() / NS_PER_US); - if (n > 0 && (size_t)n < sizeof(buf)) { - sd_notify(0, buf); - } -#endif /* HAVE_LIBSYSTEMD */ + + named_os_notify_systemd("RELOADING=1\n" + "MONOTONIC_USEC=%" PRIu64 "\n" + "STATUS=reconfig command received\n", + (uint64_t)isc_time_monotonic() / NS_PER_US); CHECK(loadconfig(server)); @@ -10567,12 +10545,10 @@ named_server_reconfigcommand(named_server_t *server) { atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); } cleanup: -#if HAVE_LIBSYSTEMD - sd_notifyf(0, - "READY=1\n" - "STATUS=reconfig command finished: %s\n", - isc_result_totext(result)); -#endif /* HAVE_LIBSYSTEMD */ + named_os_notify_systemd("READY=1\n" + "STATUS=reconfig command finished: %s\n", + isc_result_totext(result)); + return result; } diff --git a/configure.ac b/configure.ac index b742274f00..c3c16f69db 100644 --- a/configure.ac +++ b/configure.ac @@ -859,26 +859,6 @@ AS_CASE([$with_zlib], AC_SUBST([ZLIB_CFLAGS]) AC_SUBST([ZLIB_LIBS]) -# -# was --with-libsystemd specified? -# -# [pairwise: --with-libsystemd=auto, --with-libsystemd=yes, --without-libsystemd] -AC_ARG_WITH([libsystemd], - [AS_HELP_STRING([--with-libsystemd], - [build with libsystemd integration [default=auto]])], - [], [with_libsystemd=auto]) - -AS_CASE([$with_libsystemd], - [no],[], - [auto],[PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], - [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Use libsystemd library])], - [:])], - [yes],[PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], - [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Use libsystemd library])])], - [AC_MSG_ERROR([Specifying libsystemd installation path is not supported, adjust PKG_CONFIG_PATH instead])]) -AC_SUBST([LIBSYSTEMD_CFLAGS]) -AC_SUBST([LIBSYSTEMD_LIBS]) - # # Check if the system supports glibc-compatible backtrace() function. #