mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
resolved: remove entry from cache when goodbye packet received
RFC6762 10.1 says that queriers receiving a Multicast DNS response with a TTL of zero SHOULD record a TTL of 1 and then delete the record one second later. Added a timer event to trigger a callback to clean-up the cache one second after a goodbye packet is received. The callback also checks for any cache entries expiring within the next one second and schedules follow-up cleanup callbacks accordingly.
This commit is contained in:
parent
11d1c90c49
commit
d08566fad7
@ -243,6 +243,22 @@ void dns_cache_prune(DnsCache *c) {
|
||||
}
|
||||
}
|
||||
|
||||
bool dns_cache_expiry_in_one_second(DnsCache *c, usec_t t) {
|
||||
DnsCacheItem *i;
|
||||
|
||||
assert(c);
|
||||
|
||||
/* Check if any items expire within the next second */
|
||||
i = prioq_peek(c->by_expiry);
|
||||
if (!i)
|
||||
return false;
|
||||
|
||||
if (i->until <= usec_add(t, USEC_PER_SEC))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int dns_cache_item_prioq_compare_func(const void *a, const void *b) {
|
||||
const DnsCacheItem *x = a, *y = b;
|
||||
|
||||
|
@ -58,3 +58,5 @@ bool dns_cache_is_empty(DnsCache *cache);
|
||||
unsigned dns_cache_size(DnsCache *cache);
|
||||
|
||||
int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p, usec_t ts, unsigned max_rr);
|
||||
|
||||
bool dns_cache_expiry_in_one_second(DnsCache *c, usec_t t);
|
||||
|
@ -41,6 +41,7 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
|
||||
.protocol = protocol,
|
||||
.family = family,
|
||||
.resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC,
|
||||
.mdns_goodbye_event_source = NULL,
|
||||
};
|
||||
|
||||
if (protocol == DNS_PROTOCOL_DNS) {
|
||||
@ -115,6 +116,8 @@ DnsScope* dns_scope_free(DnsScope *s) {
|
||||
|
||||
sd_event_source_disable_unref(s->announce_event_source);
|
||||
|
||||
sd_event_source_disable_unref(s->mdns_goodbye_event_source);
|
||||
|
||||
dns_cache_flush(&s->cache);
|
||||
dns_zone_flush(&s->zone);
|
||||
|
||||
|
@ -45,6 +45,8 @@ struct DnsScope {
|
||||
|
||||
sd_event_source *announce_event_source;
|
||||
|
||||
sd_event_source *mdns_goodbye_event_source;
|
||||
|
||||
RateLimit ratelimit;
|
||||
|
||||
usec_t resend_timeout;
|
||||
|
@ -349,6 +349,33 @@ static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdns_goodbye_callback(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
DnsScope *scope = userdata;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(scope);
|
||||
|
||||
scope->mdns_goodbye_event_source = sd_event_source_disable_unref(scope->mdns_goodbye_event_source);
|
||||
|
||||
dns_cache_prune(&scope->cache);
|
||||
|
||||
if (dns_cache_expiry_in_one_second(&scope->cache, usec)) {
|
||||
r = sd_event_add_time_relative(
|
||||
scope->manager->event,
|
||||
&scope->mdns_goodbye_event_source,
|
||||
CLOCK_BOOTTIME,
|
||||
USEC_PER_SEC,
|
||||
0,
|
||||
mdns_goodbye_callback,
|
||||
scope);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "mDNS: Failed to re-schedule goodbye callback: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
||||
Manager *m = userdata;
|
||||
@ -407,6 +434,22 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
|
||||
log_debug("Got a goodbye packet");
|
||||
/* See the section 10.1 of RFC6762 */
|
||||
rr->ttl = 1;
|
||||
|
||||
/* Look at the cache 1 second later and remove stale entries.
|
||||
* This is particularly useful to keep service browsers updated on service removal,
|
||||
* as there are no other reliable triggers to propogate that info. */
|
||||
if (!scope->mdns_goodbye_event_source) {
|
||||
r = sd_event_add_time_relative(
|
||||
scope->manager->event,
|
||||
&scope->mdns_goodbye_event_source,
|
||||
CLOCK_BOOTTIME,
|
||||
USEC_PER_SEC,
|
||||
0,
|
||||
mdns_goodbye_callback,
|
||||
scope);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user