$(MAXMINDDB_CFLAGS) \
$(DNSTAP_CFLAGS) \
$(LIBUV_CFLAGS) \
- $(LIBSYSTEMD_CFLAGS) \
$(ZLIB_CFLAGS)
if HAVE_JSON_C
$(MAXMINDDB_LIBS) \
$(DNSTAP_LIBS) \
$(LIBUV_LIBS) \
- $(LIBSYSTEMD_LIBS) \
$(ZLIB_LIBS)
if HAVE_JSON_C
#include <pwd.h>
#include <stdbool.h>
+#include <isc/formatcheck.h>
#include <isc/types.h>
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__ */
#include <unistd.h>
#include <isc/buffer.h>
+#include <isc/errno.h>
#include <isc/file.h>
#include <isc/result.h>
#include <isc/strerr.h>
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;
}
}
+#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;
void
named_os_init(const char *progname) {
setup_syslog(progname);
+ setup_systemd_notify();
#if HAVE_LIBCAP
linux_initialprivs();
#endif /* HAVE_LIBCAP */
(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
}
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__ */
#include <fstrm.h>
#endif
-#ifdef HAVE_LIBSYSTEMD
-#include <systemd/sd-daemon.h>
-#endif
-
#include <isc/async.h>
#include <isc/attributes.h>
#include <isc/base64.h>
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);
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);
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));
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;
}
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));
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;
}
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.
#