summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-mdns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve/resolved-mdns.c')
-rw-r--r--src/resolve/resolved-mdns.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c
index b13b1d0144..c40e8f75f0 100644
--- a/src/resolve/resolved-mdns.c
+++ b/src/resolve/resolved-mdns.c
@@ -67,6 +67,50 @@ eaddrinuse:
return 0;
}
+static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
+ _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+ _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
+ DnsResourceKey *key = NULL;
+ bool tentative = false;
+ int r;
+
+ assert(s);
+ assert(p);
+
+ r = dns_packet_extract(p);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to extract resource records from incoming packet: %m");
+
+ /* TODO: there might be more than one question in mDNS queries. */
+ assert_return((dns_question_size(p->question) > 0), -EINVAL);
+ key = p->question->keys[0];
+
+ r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to lookup key: %m");
+ return r;
+ }
+ if (r == 0)
+ return 0;
+
+ r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, NULL, answer, NULL, false, &reply);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to build reply packet: %m");
+ return r;
+ }
+
+ if (!ratelimit_test(&s->ratelimit))
+ return 0;
+
+ r = dns_scope_emit_udp(s, -1, reply);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to send reply packet: %m");
+ return r;
+ }
+
+ 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;
@@ -77,6 +121,9 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
if (r <= 0)
return r;
+ if (manager_our_packet(m, p))
+ return 0;
+
scope = manager_find_scope(m, p);
if (!scope) {
log_warning("Got mDNS UDP packet on unknown scope. Ignoring.");
@@ -115,9 +162,28 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
dns_name_endswith(name, "local") > 0))
return 0;
+ if (rr->ttl == 0) {
+ log_debug("Got a goodbye packet");
+ /* See the section 10.1 of RFC6762 */
+ rr->ttl = 1;
+ }
+
t = dns_scope_find_transaction(scope, rr->key, false);
if (t)
dns_transaction_process_reply(t, p);
+
+ /* Also look for the various types of ANY transactions */
+ t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false);
+ if (t)
+ dns_transaction_process_reply(t, p);
+
+ t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), false);
+ if (t)
+ dns_transaction_process_reply(t, p);
+
+ t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false);
+ if (t)
+ dns_transaction_process_reply(t, p);
}
dns_cache_put(&scope->cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender);
@@ -125,7 +191,11 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
} else if (dns_packet_validate_query(p) > 0) {
log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));
- dns_scope_process_query(scope, NULL, p);
+ r = mdns_scope_process_query(scope, p);
+ if (r < 0) {
+ log_debug_errno(r, "mDNS query processing failed: %m");
+ return 0;
+ }
} else
log_debug("Invalid mDNS UDP packet.");