summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Mack <daniel@zonque.org>2015-07-10 20:44:59 -0400
committerDaniel Mack <daniel@zonque.org>2015-12-08 16:51:40 +0100
commit124602aea81a27dda02e898798a18f95bf03734e (patch)
tree6e5852fda0e18a221539cfbdcf633cda7a7450af /src
parentd84e543d927926fbcc6a5eec730b4db97d9272c7 (diff)
resolved: add mDNS packet dispatcher
Add the packet dispatching routine for mDNS. It differs to what LLMNR and DNS dispatchers do in the way it matches incoming packets. In mDNS, we actually handle all incoming packets, regardless whether we asked for them earlier or not.
Diffstat (limited to 'src')
-rw-r--r--src/resolve/resolved-mdns.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c
index 6767706f6e..096a4b1fe5 100644
--- a/src/resolve/resolved-mdns.c
+++ b/src/resolve/resolved-mdns.c
@@ -70,7 +70,64 @@ eaddrinuse:
}
static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- /* TODO */
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ Manager *m = userdata;
+ DnsScope *scope;
+ int r;
+
+ r = manager_recv(m, fd, DNS_PROTOCOL_MDNS, &p);
+ if (r <= 0)
+ return r;
+
+ scope = manager_find_scope(m, p);
+ if (!scope) {
+ log_warning("Got mDNS UDP packet on unknown scope. Ignoring.");
+ return 0;
+ }
+
+ if (dns_packet_validate_reply(p) > 0) {
+ unsigned i;
+
+ log_debug("Got mDNS reply packet");
+
+ /*
+ * mDNS is different from regular DNS and LLMNR with regard to handling responses.
+ * While on other protocols, we can ignore every answer that doesn't match a question
+ * we broadcast earlier, RFC6762, section 18.1 recommends looking at and caching all
+ * incoming information, regardless of the DNS packet ID.
+ *
+ * Hence, extract the packet here, and try to find a transaction for answer the we got
+ * and complete it. Also store the new information in scope's cache.
+ */
+ r = dns_packet_extract(p);
+ if (r < 0) {
+ log_debug("mDNS packet extraction failed.");
+ return 0;
+ }
+
+ dns_scope_check_conflicts(scope, p);
+
+ for (i = 0; i < p->answer->n_rrs; i++) {
+ DnsResourceRecord *rr;
+ DnsTransaction *t;
+
+ rr = p->answer->items[i].rr;
+
+ t = dns_scope_find_transaction(scope, rr->key, false);
+ if (t)
+ dns_transaction_process_reply(t, p);
+ }
+
+ dns_cache_put(&scope->cache, NULL, DNS_PACKET_RCODE(p), p->answer,
+ p->answer->n_rrs, false, 0, p->family, &p->sender);
+
+ } 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);
+ } else
+ log_debug("Invalid mDNS UDP packet.");
+
return 0;
}