mirror of
https://github.com/systemd/systemd.git
synced 2025-01-12 13:18:14 +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;
|
int r;
|
||||||
|
|
||||||
assert(cache);
|
assert(cache);
|
||||||
|
assert(p);
|
||||||
|
|
||||||
HASHMAP_FOREACH(i, cache->by_key, iterator) {
|
HASHMAP_FOREACH(i, cache->by_key, iterator) {
|
||||||
DnsCacheItem *j;
|
DnsCacheItem *j;
|
||||||
@ -752,6 +753,23 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = dns_packet_append_rr(p, j->rr, NULL, NULL);
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -65,40 +65,44 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
|
void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
|
||||||
DnsPacket *p;
|
|
||||||
DnsPacketHeader *h;
|
DnsPacketHeader *h;
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(ret);
|
assert(p);
|
||||||
|
|
||||||
r = dns_packet_new(&p, protocol, mtu);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
h = DNS_PACKET_HEADER(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 */,
|
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
|
||||||
0 /* opcode */,
|
0 /* opcode */,
|
||||||
0 /* c */,
|
0 /* c */,
|
||||||
0 /* tc */,
|
0/* tc */,
|
||||||
0 /* t */,
|
0 /* t */,
|
||||||
0 /* ra */,
|
0 /* ra */,
|
||||||
0 /* ad */,
|
0 /* ad */,
|
||||||
0 /* cd */,
|
0 /* cd */,
|
||||||
0 /* rcode */));
|
0 /* rcode */));
|
||||||
else if (protocol == DNS_PROTOCOL_MDNS)
|
break;
|
||||||
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
|
|
||||||
0 /* opcode */,
|
case DNS_PROTOCOL_MDNS:
|
||||||
0 /* aa */,
|
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
|
||||||
0 /* tc */,
|
0 /* opcode */,
|
||||||
0 /* rd (ask for recursion) */,
|
0 /* aa */,
|
||||||
0 /* ra */,
|
truncated /* tc */,
|
||||||
0 /* ad */,
|
0 /* rd (ask for recursion) */,
|
||||||
0 /* cd */,
|
0 /* ra */,
|
||||||
0 /* rcode */));
|
0 /* ad */,
|
||||||
else
|
0 /* cd */,
|
||||||
|
0 /* rcode */));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!truncated);
|
||||||
|
|
||||||
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
|
h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
|
||||||
0 /* opcode */,
|
0 /* opcode */,
|
||||||
0 /* aa */,
|
0 /* aa */,
|
||||||
@ -108,6 +112,23 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool
|
|||||||
0 /* ad */,
|
0 /* ad */,
|
||||||
dnssec_checking_disabled /* cd */,
|
dnssec_checking_disabled /* cd */,
|
||||||
0 /* rcode */));
|
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;
|
*ret = p;
|
||||||
return 0;
|
return 0;
|
||||||
@ -149,6 +170,9 @@ DnsPacket *dns_packet_unref(DnsPacket *p) {
|
|||||||
|
|
||||||
assert(p->n_ref > 0);
|
assert(p->n_ref > 0);
|
||||||
|
|
||||||
|
if (p->more)
|
||||||
|
dns_packet_unref(p->more);
|
||||||
|
|
||||||
if (p->n_ref == 1)
|
if (p->n_ref == 1)
|
||||||
dns_packet_free(p);
|
dns_packet_free(p);
|
||||||
else
|
else
|
||||||
|
@ -88,6 +88,9 @@ struct DnsPacket {
|
|||||||
uint16_t sender_port, destination_port;
|
uint16_t sender_port, destination_port;
|
||||||
uint32_t ttl;
|
uint32_t ttl;
|
||||||
|
|
||||||
|
/* For support of truncated packets */
|
||||||
|
DnsPacket *more;
|
||||||
|
|
||||||
bool on_stack:1;
|
bool on_stack:1;
|
||||||
bool extracted:1;
|
bool extracted:1;
|
||||||
bool refuse_compression: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(DnsPacket **p, DnsProtocol protocol, size_t mtu);
|
||||||
int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled);
|
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_ref(DnsPacket *p);
|
||||||
DnsPacket *dns_packet_unref(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);
|
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;
|
union in_addr_union addr;
|
||||||
int ifindex = 0, r;
|
int ifindex = 0, r;
|
||||||
int family;
|
int family;
|
||||||
@ -278,6 +278,31 @@ int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
|
|||||||
return 1;
|
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) {
|
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;
|
DnsServer *srv = NULL;
|
||||||
_cleanup_close_ int fd = -1;
|
_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, "8.e.f.ip6.arpa") == 0 &&
|
||||||
dns_name_endswith(domain, "9.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, "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_MAYBE;
|
||||||
|
|
||||||
return DNS_SCOPE_NO;
|
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);
|
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) {
|
if (r < 0)
|
||||||
r = -errno;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
return m->llmnr_ipv6_tcp_fd;
|
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);
|
r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLIN, on_mdns_packet, m);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
r = -errno;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
return m->mdns_ipv6_fd;
|
return m->mdns_ipv6_fd;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user