diff options
author | Daniel Mack <daniel@zonque.org> | 2015-07-10 20:44:59 -0400 |
---|---|---|
committer | Daniel Mack <daniel@zonque.org> | 2015-12-08 16:51:40 +0100 |
commit | 124602aea81a27dda02e898798a18f95bf03734e (patch) | |
tree | 6e5852fda0e18a221539cfbdcf633cda7a7450af /src/resolve/resolved-mdns.c | |
parent | d84e543d927926fbcc6a5eec730b4db97d9272c7 (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/resolve/resolved-mdns.c')
-rw-r--r-- | src/resolve/resolved-mdns.c | 59 |
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; } |