assert(sb);
assert(sb->manager);
- /* ifindex=0 means "all interfaces" */
+ /* ifindex=0 means "all interfaces". Collect the cached answers from
+ * every matching mDNS scope into a single combined answer and reconcile
+ * once. Reconciling per-scope would be wrong: mdns_manage_services_answer()
+ * derives removals by diffing the browser's global service list against
+ * the answer it is handed, so a single scope's answer would spuriously
+ * "remove" (and then, on the next scope/pass, re-"add") services that are
+ * still present on other interfaces — resulting in a continuous
+ * added/removed event flap for services seen on more than the current
+ * scope. */
if (sb->ifindex == 0) {
+ _cleanup_(dns_answer_unrefp) DnsAnswer *combined = NULL;
+
LIST_FOREACH(scopes, scope, sb->manager->dns_scopes) {
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+ DnsAnswerItem *item;
if (scope->protocol != DNS_PROTOCOL_MDNS)
continue;
return log_error_errno(r, "Failed to look up DNS cache for service browser key on scope %s: %m",
dns_scope_ifname(scope) ?: "global");
- r = mdns_manage_services_answer(sb, answer, owner_family);
- if (r < 0)
- return log_error_errno(r, "Failed to manage mDNS services after cache lookup on scope %s: %m",
- dns_scope_ifname(scope) ?: "global");
+ /* Merge preserving each item's ifindex, flags, rrsig and
+ * cache-expiry 'until'. (dns_answer_extend()/merge() would
+ * reset 'until' to USEC_INFINITY, which would skew the RFC
+ * 6762 §5.2 TTL-maintenance schedule that
+ * mdns_manage_services_answer() derives from item->until.) */
+ DNS_ANSWER_FOREACH_ITEM(item, answer) {
+ r = dns_answer_add_extend_full(&combined, item->rr, item->ifindex,
+ item->flags, item->rrsig, item->until);
+ if (r < 0)
+ return log_error_errno(r, "Failed to merge mDNS cache answer from scope %s: %m",
+ dns_scope_ifname(scope) ?: "global");
+ }
}
+
+ r = mdns_manage_services_answer(sb, combined, owner_family);
+ if (r < 0)
+ return log_error_errno(r, "Failed to manage mDNS services after cache lookup for all interfaces: %m");
+
return 0;
}