mirror of
https://github.com/systemd/systemd.git
synced 2024-11-01 09:21:26 +03:00
Merge pull request #2128 from zonque/resolved-mdns-2
resolved: more mDNS specific bits (2)
This commit is contained in:
commit
59c74f2175
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user