diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2018-05-20 01:55:39 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2018-05-22 22:20:17 +0900 |
commit | 906cb2eb74d377c84f3730c9d5f0fed15286d01f (patch) | |
tree | 40b994b5d17a1f76865da66982b88079daa2eeb1 /src/shared/bus-util.c | |
parent | be80154827100b19b6cc79a59323791b4f1a409f (diff) | |
download | systemd-906cb2eb74d377c84f3730c9d5f0fed15286d01f.tar.gz |
timesync,shared: move logic requesting bus name to shared
Preparation for setting DynamicUser= to other services which
request bus names.
Diffstat (limited to 'src/shared/bus-util.c')
-rw-r--r-- | src/shared/bus-util.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index c80fc4fcbb..1564966e52 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); +} |