From 906cb2eb74d377c84f3730c9d5f0fed15286d01f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 20 May 2018 01:55:39 +0900 Subject: [PATCH] timesync,shared: move logic requesting bus name to shared Preparation for setting DynamicUser= to other services which request bus names. --- src/shared/bus-util.c | 121 +++++++++++++++++++++++++++++++++++++++++++ src/shared/bus-util.h | 2 + src/timesync/timesyncd-bus.c | 96 +--------------------------------- 3 files changed, 124 insertions(+), 95 deletions(-) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index c80fc4f..1564966 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1726,3 +1726,124 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri return 0; } + +struct request_name_data { + const char *name; + uint64_t flags; + void *userdata; +}; + +static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + _cleanup_free_ struct request_name_data *data = userdata; + const sd_bus_error *e; + int r; + + assert(m); + assert(data); + assert(data->name); + + e = sd_bus_message_get_error(m); + if (e) { + log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message); + return 1; + } + + /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */ + r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, data->name, data->flags, NULL, data->userdata); + if (r < 0) + log_error_errno(r, "Failed to request name: %m"); + + return 1; +} + +static int request_name_handler_may_reload_dbus(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + _cleanup_free_ struct request_name_data *data = userdata; + uint32_t ret; + int r; + + assert(m); + assert(userdata); + + if (sd_bus_message_is_method_error(m, NULL)) { + const sd_bus_error *e = sd_bus_message_get_error(m); + + if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) { + log_debug_errno(sd_bus_error_get_errno(e), + "Unable to request name, failing connection: %s", + e->message); + + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug_errno(sd_bus_error_get_errno(e), + "Unable to request name, retry after reloading DBus configuration: %s", + e->message); + + /* If systemd-timesyncd.service enables DynamicUser= and dbus.service + * started before the dynamic user is realized, then the DBus policy + * about timesyncd has not been enabled yet. So, let's try to reload + * DBus configuration, and after that request name again. Note that it + * seems that no privileges are necessary to call the following method. */ + + r = sd_bus_call_method_async( + sd_bus_message_get_bus(m), + NULL, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ReloadConfig", + reload_dbus_handler, + userdata, NULL); + if (r < 0) { + log_error_errno(r, "Failed to reload DBus configuration: %m"); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + data = NULL; /* Avoid free() */ + return 1; + } + + r = sd_bus_message_read(m, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_ALREADY_OWNER: + log_debug("Already owner of requested service name, ignoring."); + return 1; + + case BUS_NAME_IN_QUEUE: + log_debug("In queue for requested service name."); + return 1; + + case BUS_NAME_PRIMARY_OWNER: + log_debug("Successfully acquired requested service name."); + return 1; + + case BUS_NAME_EXISTS: + log_debug("Requested service name already owned, failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug("Unexpected response from RequestName(), failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; +} + +int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata) { + struct request_name_data *data; + + data = new0(struct request_name_data, 1); + if (!data) + return -ENOMEM; + + data->name = name; + data->flags = flags; + data->userdata = userdata; + + return sd_bus_request_name_async(bus, ret_slot, name, flags, request_name_handler_may_reload_dbus, data); +} diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index a3af8d8..16aeca7 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -182,3 +182,5 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri static inline int bus_open_system_watch_bind(sd_bus **ret) { return bus_open_system_watch_bind_with_description(ret, NULL); } + +int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata); diff --git a/src/timesync/timesyncd-bus.c b/src/timesync/timesyncd-bus.c index 6243deb..f2527f5 100644 --- a/src/timesync/timesyncd-bus.c +++ b/src/timesync/timesyncd-bus.c @@ -169,100 +169,6 @@ static const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_END }; -static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - const sd_bus_error *e; - int r; - - assert(m); - - e = sd_bus_message_get_error(m); - if (e) { - log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message); - return 1; - } - - /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */ - r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, "org.freedesktop.timesync1", 0, NULL, NULL); - if (r < 0) - log_error_errno(r, "Failed to request name: %m"); - - return 1; -} - -static int request_name_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - uint32_t ret; - int r; - - assert(m); - - if (sd_bus_message_is_method_error(m, NULL)) { - const sd_bus_error *e = sd_bus_message_get_error(m); - - if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) { - log_debug_errno(sd_bus_error_get_errno(e), - "Unable to request name, failing connection: %s", - e->message); - - bus_enter_closing(sd_bus_message_get_bus(m)); - return 1; - } - - log_debug_errno(sd_bus_error_get_errno(e), - "Unable to request name, retry after reloading DBus configuration: %s", - e->message); - - /* If systemd-timesyncd.service enables DynamicUser= and dbus.service - * started before the dynamic user is realized, then the DBus policy - * about timesyncd has not been enabled yet. So, let's try to reload - * DBus configuration, and after that request name again. Note that it - * seems that no privileges are necessary to call the following method. */ - - r = sd_bus_call_method_async( - sd_bus_message_get_bus(m), - NULL, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "ReloadConfig", - reload_dbus_handler, - NULL, NULL); - if (r < 0) { - log_error_errno(r, "Failed to reload DBus configuration: %m"); - bus_enter_closing(sd_bus_message_get_bus(m)); - } - - return 1; - } - - r = sd_bus_message_read(m, "u", &ret); - if (r < 0) - return r; - - switch (ret) { - - case BUS_NAME_ALREADY_OWNER: - log_debug("Already owner of requested service name, ignoring."); - return 1; - - case BUS_NAME_IN_QUEUE: - log_debug("In queue for requested service name."); - return 1; - - case BUS_NAME_PRIMARY_OWNER: - log_debug("Successfully acquired requested service name."); - return 1; - - case BUS_NAME_EXISTS: - log_debug("Requested service name already owned, failing connection."); - bus_enter_closing(sd_bus_message_get_bus(m)); - return 1; - } - - log_debug("Unexpected response from RequestName(), failing connection."); - bus_enter_closing(sd_bus_message_get_bus(m)); - return 1; -} - int manager_connect_bus(Manager *m) { int r; @@ -279,7 +185,7 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add manager object vtable: %m"); - r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.timesync1", 0, request_name_handler, NULL); + r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.timesync1", 0, NULL); if (r < 0) return log_error_errno(r, "Failed to request name: %m"); -- 2.7.4