* Note that we usually encode the empty DnsAnswer object as a simple NULL. */
typedef enum DnsAnswerFlags {
- DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */
- DNS_ANSWER_CACHEABLE = 2, /* Item is subject to caching */
- DNS_ANSWER_SHARED_OWNER = 4, /* For mDNS: RRset may be owner by multiple peers */
- DNS_ANSWER_CACHE_FLUSH = 8, /* For mDNS: sets cache-flush bit in the rrclass of response records */
+ DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */
+ DNS_ANSWER_CACHEABLE = 2, /* Item is subject to caching */
+ DNS_ANSWER_SHARED_OWNER = 4, /* For mDNS: RRset may be owner by multiple peers */
+ DNS_ANSWER_CACHE_FLUSH = 8, /* For mDNS: sets cache-flush bit in the rrclass of response records */
+ DNS_ANSWER_GOODBYE = 16, /* For mDNS: item is subject to disappear */
} DnsAnswerFlags;
struct DnsAnswerItem {
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start) {
size_t saved_size, rdlength_offset, end, rdlength, rds;
+ uint32_t ttl;
int r;
assert(p);
if (r < 0)
goto fail;
- r = dns_packet_append_uint32(p, rr->ttl, NULL);
+ ttl = flags & DNS_ANSWER_GOODBYE ? 0 : rr->ttl;
+ r = dns_packet_append_uint32(p, ttl, NULL);
if (r < 0)
goto fail;
scope->announce_event_source = sd_event_source_unref(scope->announce_event_source);
- dns_scope_announce(scope);
+ dns_scope_announce(scope, false);
return 0;
}
-void dns_scope_announce(DnsScope *scope) {
+void dns_scope_announce(DnsScope *scope, bool goodbye) {
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
LinkAddress *a;
answer = dns_answer_new(4);
LIST_FOREACH(addresses, a, scope->link->addresses) {
- r = dns_answer_add(answer, a->mdns_address_rr, 0, DNS_ANSWER_CACHE_FLUSH);
+ r = dns_answer_add(answer, a->mdns_address_rr, 0, goodbye ? DNS_ANSWER_GOODBYE : DNS_ANSWER_CACHE_FLUSH);
if (r < 0) {
log_debug_errno(r, "Failed to add address RR to answer: %m");
return;
}
- r = dns_answer_add(answer, a->mdns_ptr_rr, 0, DNS_ANSWER_CACHE_FLUSH);
+ r = dns_answer_add(answer, a->mdns_ptr_rr, 0, goodbye ? DNS_ANSWER_GOODBYE : DNS_ANSWER_CACHE_FLUSH);
if (r < 0) {
log_debug_errno(r, "Failed to add PTR RR to answer: %m");
return;
int dns_scope_ifindex(DnsScope *s);
-void dns_scope_announce(DnsScope *scope);
+void dns_scope_announce(DnsScope *scope, bool goodbye);
SET_FOREACH_MOVE(z, t->notify_zone_items_done, t->notify_zone_items)
dns_zone_item_notify(z);
SWAP_TWO(t->notify_zone_items, t->notify_zone_items_done);
- if (t->probing) {
- dns_scope_announce(t->scope);
- }
+ if (t->probing)
+ dns_scope_announce(t->scope, false);
SET_FOREACH_MOVE(d, t->notify_transactions_done, t->notify_transactions)
dns_transaction_notify(d, t);
if (!l)
return NULL;
+ /* Send goodbye messages. */
+ dns_scope_announce(l->mdns_ipv4_scope, true);
+ dns_scope_announce(l->mdns_ipv6_scope, true);
+
link_flush_settings(l);
while (l->addresses)