2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

rem: pkg: Implement the systemd notification protocol manually to remove dependency on libsystemd.

Merge branch 'aydin/standalone-notification' into 'main'

See merge request isc-projects/bind9!10263
This commit is contained in:
Aydın Mercan
2025-03-27 19:54:49 +00:00
5 changed files with 155 additions and 70 deletions

View File

@@ -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

View File

@@ -18,6 +18,7 @@
#include <pwd.h>
#include <stdbool.h>
#include <isc/formatcheck.h>
#include <isc/types.h>
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__ */

View File

@@ -36,6 +36,7 @@
#include <unistd.h>
#include <isc/buffer.h>
#include <isc/errno.h>
#include <isc/file.h>
#include <isc/result.h>
#include <isc/strerr.h>
@@ -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__ */

View File

@@ -28,10 +28,6 @@
#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>
@@ -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;
}

View File

@@ -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.
#