Merge pull request #2128 from zonque/resolved-mdns-2

resolved: more mDNS specific bits (2)
This commit is contained in:
Lennart Poettering 2015-12-10 11:10:30 +01:00
commit 59c74f2175
6 changed files with 101 additions and 29 deletions

View file

@ -738,6 +738,7 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
int r;
assert(cache);
assert(p);
HASHMAP_FOREACH(i, cache->by_key, iterator) {
DnsCacheItem *j;
@ -752,6 +753,23 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
continue;
r = dns_packet_append_rr(p, j->rr, NULL, NULL);
if (r == -EMSGSIZE && p->protocol == DNS_PROTOCOL_MDNS) {
/* For mDNS, if we're unable to stuff all known answers into the given packet,
* allocate a new one, push the RR into that one and link it to the current one.
*/
DNS_PACKET_HEADER(p)->ancount = htobe16(ancount);
ancount = 0;
r = dns_packet_new_query(&p->more, p->protocol, 0, true);
if (r < 0)
return r;
/* continue with new packet */
p = p->more;
r = dns_packet_append_rr(p, j->rr, NULL, NULL);
}
if (r < 0)
return r;

View file

@ -65,40 +65,44 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
return 0;
}
int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
DnsPacket *p;
void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
DnsPacketHeader *h;
int r;
assert(ret);
r = dns_packet_new(&p, protocol, mtu);
if (r < 0)
return r;
assert(p);
h = DNS_PACKET_HEADER(p);
if (protocol == DNS_PROTOCOL_LLMNR)
switch(p->protocol) {
case DNS_PROTOCOL_LLMNR:
assert(!truncated);
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
0 /* opcode */,
0 /* c */,
0 /* tc */,
0/* tc */,
0 /* t */,
0 /* ra */,
0 /* ad */,
0 /* cd */,
0 /* rcode */));
else if (protocol == DNS_PROTOCOL_MDNS)
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
0 /* opcode */,
0 /* aa */,
0 /* tc */,
0 /* rd (ask for recursion) */,
0 /* ra */,
0 /* ad */,
0 /* cd */,
0 /* rcode */));
else
break;
case DNS_PROTOCOL_MDNS:
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
0 /* opcode */,
0 /* aa */,
truncated /* tc */,
0 /* rd (ask for recursion) */,
0 /* ra */,
0 /* ad */,
0 /* cd */,
0 /* rcode */));
break;
default:
assert(!truncated);
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
0 /* opcode */,
0 /* aa */,
@ -108,6 +112,23 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool
0 /* ad */,
dnssec_checking_disabled /* cd */,
0 /* rcode */));
}
}
int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
DnsPacket *p;
int r;
assert(ret);
r = dns_packet_new(&p, protocol, mtu);
if (r < 0)
return r;
/* Always set the TC bit to 0 initially.
* If there are multiple packets later, we'll update the bit shortly before sending.
*/
dns_packet_set_flags(p, dnssec_checking_disabled, false);
*ret = p;
return 0;
@ -149,6 +170,9 @@ DnsPacket *dns_packet_unref(DnsPacket *p) {
assert(p->n_ref > 0);
if (p->more)
dns_packet_unref(p->more);
if (p->n_ref == 1)
dns_packet_free(p);
else

View file

@ -88,6 +88,9 @@ struct DnsPacket {
uint16_t sender_port, destination_port;
uint32_t ttl;
/* For support of truncated packets */
DnsPacket *more;
bool on_stack:1;
bool extracted:1;
bool refuse_compression:1;
@ -146,6 +149,8 @@ static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) {
int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu);
int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled);
void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated);
DnsPacket *dns_packet_ref(DnsPacket *p);
DnsPacket *dns_packet_unref(DnsPacket *p);

View file

@ -161,7 +161,7 @@ void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
}
int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
static int dns_scope_emit_one(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
union in_addr_union addr;
int ifindex = 0, r;
int family;
@ -278,6 +278,31 @@ int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
return 1;
}
int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
int r;
assert(s);
assert(p);
assert(p->protocol == s->protocol);
assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
do {
/* If there are multiple linked packets, set the TC bit in all but the last of them */
if (p->more) {
assert(p->protocol == DNS_PROTOCOL_MDNS);
dns_packet_set_flags(p, true, true);
}
r = dns_scope_emit_one(s, fd, server, p);
if (r < 0)
return r;
p = p->more;
} while(p);
return 0;
}
static int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
DnsServer *srv = NULL;
_cleanup_close_ int fd = -1;
@ -433,7 +458,11 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0)
dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
/* If networks use .local in their private setups, they are supposed to also add .local to their search
* domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
* send such queries ordinary DNS servers. */
dns_name_endswith(domain, "local") == 0)
return DNS_SCOPE_MAYBE;
return DNS_SCOPE_NO;

View file

@ -461,10 +461,8 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) {
}
r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
if (r < 0) {
r = -errno;
if (r < 0)
goto fail;
}
return m->llmnr_ipv6_tcp_fd;

View file

@ -275,10 +275,8 @@ int manager_mdns_ipv6_fd(Manager *m) {
}
r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLIN, on_mdns_packet, m);
if (r < 0) {
r = -errno;
if (r < 0)
goto fail;
}
return m->mdns_ipv6_fd;