diff --git a/NEWS b/NEWS
index 84998aa28a..9d4cde0f24 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,19 @@ CHANGES WITH 262:
Feature Removals and Incompatible Changes:
+ * DNS-SD services registered via systemd-resolved's D-Bus method
+ org.freedesktop.resolve1.Manager.RegisterService() are now
+ unregistered automatically when the client that registered them
+ disconnects from the bus, as originally intended and matching the
+ behavior of the equivalent Avahi API. Due to a bug the client
+ tracking never worked, and such services used to stay registered
+ until systemd-resolved exited (but did not survive a restart of the
+ daemon either). Clients must now keep their bus connection open for
+ as long as the service shall remain registered; one-shot
+ registrations, e.g. via busctl or gdbus, will be withdrawn again as
+ soon as the tool exits. To register a DNS-SD service independently
+ of a client's lifetime, use *.dnssd files, see systemd.dnssd(5).
+
* Meson options '-Dlibiptc=' (deprecated in v259), '-Dlibidn=',
'-Drc-local=', '-Dsysvinit-path=', and '-Dsysvrcnd-path=' (deprecated
in v260) have been removed.
diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml
index a1240cbe80..bed947f33b 100644
--- a/man/org.freedesktop.resolve1.xml
+++ b/man/org.freedesktop.resolve1.xml
@@ -450,6 +450,18 @@ node /org/freedesktop/resolve1 {
DNS-SD SRV record. Finally, it takes an array of TXT record data. It returns an object path which may be
used as handle to the registered service.
+ The lifetime of a service registered via this method is bound to the D-Bus connection of the
+ client that registered it: when the client disconnects from the bus the service is automatically
+ unregistered and goodbye packets are sent out, as if UnregisterService() had been
+ called. Clients hence must keep their bus connection open for as long as the service shall remain
+ registered. The registration also does not survive systemd-resolved losing its
+ own bus connection, in which case tracking clients is not possible anymore and all services registered
+ via this method are unregistered. To register a DNS-SD service independently of a client's lifetime,
+ use *.dnssd files, see
+ systemd.dnssd5. Note
+ that prior to version 262, due to a bug, the client's connection was not tracked and services
+ registered via this method stayed registered until the daemon exited.
+
The UnregisterService() method undoes the effect of
RegisterService() and deletes a DNS-SD service previously created via IPC
again.
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index 53092bd6d3..650259a8c0 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -1894,8 +1894,8 @@ static int dnssd_registered_service_on_bus_track(sd_bus_track *t, void *userdata
assert(t);
- log_debug("Client of active request vanished, destroying DNS-SD service.");
- dnssd_registered_service_free(s);
+ log_debug("Client of DNS-SD service '%s' vanished, unregistering.", s->id);
+ dnssd_registered_service_unregister(s);
return 0;
}
@@ -2063,6 +2063,10 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
if (r < 0)
return r;
+ /* The service is unregistered automatically when the client that registered it disconnects from the
+ * bus, hence keep the bus track object pinned for the lifetime of the service. */
+ service->bus_track = TAKE_PTR(bus_track);
+
service->manager = m;
r = hashmap_ensure_put(&m->dnssd_registered_services, &string_hash_ops, service->id, service);
diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c
index 5617293cb7..1d9d8f6635 100644
--- a/src/resolve/resolved-dnssd.c
+++ b/src/resolve/resolved-dnssd.c
@@ -57,6 +57,8 @@ DnssdRegisteredService *dnssd_registered_service_free(DnssdRegisteredService *se
if (service->manager)
hashmap_remove(service->manager->dnssd_registered_services, service->id);
+ sd_bus_track_unref(service->bus_track);
+
dns_resource_record_unref(service->ptr_rr);
dns_resource_record_unref(service->sub_ptr_rr);
dns_resource_record_unref(service->srv_rr);
diff --git a/src/resolve/resolved-dnssd.h b/src/resolve/resolved-dnssd.h
index d931b88a49..d19024e972 100644
--- a/src/resolve/resolved-dnssd.h
+++ b/src/resolve/resolved-dnssd.h
@@ -39,6 +39,10 @@ typedef struct DnssdRegisteredService {
Manager *manager;
+ /* Tracks the D-Bus client that registered the service, so that it can be unregistered when the
+ * client disconnects from the bus. Only set for services registered via D-Bus. */
+ sd_bus_track *bus_track;
+
/* Services registered via D-Bus are not removed on reload */
ResolveConfigSource config_source;