diff --git a/src/knot/common/systemd.c b/src/knot/common/systemd.c index c3ee68f362bc121d3877f118142091ff13e726e2..0c37a0740ce1d499b111990f3ee0c9a478b1b8dc 100644 --- a/src/knot/common/systemd.c +++ b/src/knot/common/systemd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,6 +14,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -82,3 +83,58 @@ void systemd_stopping_notify(void) sd_notify(0, "STOPPING=1\nSTATUS="); #endif } + +#define DBUS_NAME "cz.nic.knotd" + +static sd_bus *_dbus = NULL; + +int systemd_dbus_open(void) +{ +#ifdef ENABLE_SYSTEMD + if (_dbus != NULL) { + return KNOT_EOK; + } + + int ret = 0; + if ((ret = sd_bus_open_system(&_dbus)) < 0) { + return ret; + } + + /* Take a well-known service name so that clients can find us */ + if ((ret = sd_bus_request_name(_dbus, DBUS_NAME, 0)) < 0) { + systemd_dbus_close(); + return ret; + } +#endif + return KNOT_EOK; +} + +void systemd_dbus_close(void) +{ +#ifdef ENABLE_SYSTEMD + _dbus = sd_bus_unref(_dbus); +#endif +} + +static int emit_generic_event(const char * event, const char *types, ...) { + int ret; + if (_dbus == NULL) { + return KNOT_EOK; + } +#ifdef ENABLE_SYSTEMD + va_list args; + va_start(args, types); + if ((ret = sd_bus_emit_signalv(_dbus, "/cz/nic/knotd", DBUS_NAME".events", event, types, args)) < 0) { + va_end(args); + return ret; + } + va_end(args); + return KNOT_EOK; +#endif + return KNOT_ENOTSUP; +} + +int systemd_dbus_emit_xfr_done(unsigned char *zone) +{ + return emit_generic_event("On_XFR_Done", "s", zone); +} diff --git a/src/knot/common/systemd.h b/src/knot/common/systemd.h index efa4044175f4fea2eac7c58d23b8b528c402f7a6..d3e31d1bad0737e3fe0eefc8c41d098d1559cd05 100644 --- a/src/knot/common/systemd.h +++ b/src/knot/common/systemd.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,3 +46,29 @@ void systemd_reloading_notify(void); * \brief Notify systemd about service is stopping. */ void systemd_stopping_notify(void); + +#ifdef ENABLE_SYSTEMD +#include <systemd/sd-bus.h> +#else +#define sd_bus void +#endif + +/*! + * \brief Creates unique D-Bus sender reference (common for whole process). + * \retval KNOT_EOK on successful create of reference. + * \retval Negative value on error. + */ +int systemd_dbus_open(void); + +/*! + * \brief Closes D-Bus. + */ +void systemd_dbus_close(void); + +/*! + * \brief Emit event signal in specific format. + * \param zone Zone name. + * \retval KNOT_EOK on successful send. + * \retval Negative value on error. + */ +int systemd_dbus_emit_xfr_done(unsigned char *zone); diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c index a8a14777c3cd8efbd49d31cb91b576c9e2027212..2ebc56fd2dc5094af2b83c2298902e92c81629f7 100644 --- a/src/utils/knotd/main.c +++ b/src/utils/knotd/main.c @@ -466,9 +466,14 @@ int main(int argc, char **argv) log_levels_add(LOG_TARGET_STDOUT, LOG_SOURCE_ANY, LOG_MASK(LOG_DEBUG)); } + if (systemd_dbus_open() != KNOT_EOK) { + log_warning("failed to open system dbus, check the permissions"); + } + /* Set up the configuration */ int ret = set_config(confdb, config, max_conf_size); if (ret != KNOT_EOK) { + systemd_dbus_close(); log_close(); return EXIT_FAILURE; } @@ -482,6 +487,7 @@ int main(int argc, char **argv) if (ret != KNOT_EOK) { log_fatal("failed to initialize server (%s)", knot_strerror(ret)); conf_free(conf()); + systemd_dbus_close(); log_close(); return EXIT_FAILURE; } @@ -494,6 +500,7 @@ int main(int argc, char **argv) server_wait(&server); server_deinit(&server); conf_free(conf()); + systemd_dbus_close(); log_close(); return EXIT_FAILURE; } @@ -507,6 +514,7 @@ int main(int argc, char **argv) server_wait(&server); server_deinit(&server); conf_free(conf()); + systemd_dbus_close(); log_close(); return EXIT_FAILURE; } @@ -524,6 +532,7 @@ int main(int argc, char **argv) server_wait(&server); server_deinit(&server); conf_free(conf()); + systemd_dbus_close(); log_close(); return EXIT_FAILURE; } @@ -562,6 +571,7 @@ int main(int argc, char **argv) server_deinit(&server); rcu_unregister_thread(); pid_cleanup(); + systemd_dbus_close(); log_close(); conf_free(conf()); return EXIT_FAILURE; @@ -591,6 +601,8 @@ int main(int argc, char **argv) /* Unhook from RCU. */ rcu_unregister_thread(); + systemd_dbus_close(); + log_info("shutting down"); log_close();