1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/tcp.h>
26 #include "socket-util.h"
28 #include "resolved-dns-domain.h"
29 #include "resolved-dns-scope.h"
31 #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
32 #define MULTICAST_RATELIMIT_BURST 1000
34 int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
40 s = new0(DnsScope, 1);
46 s->protocol = protocol;
49 LIST_PREPEND(scopes, m->dns_scopes, s);
51 dns_scope_llmnr_membership(s, true);
53 log_debug("New scope on link %s, protocol %s, family %s", l ? l->name : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family));
55 /* Enforce ratelimiting for the multicast protocols */
56 RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
62 DnsScope* dns_scope_free(DnsScope *s) {
68 log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->name : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family));
70 dns_scope_llmnr_membership(s, false);
72 while ((t = s->transactions)) {
74 /* Abort the transaction, but make sure it is not
75 * freed while we still look at it */
78 dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
81 dns_transaction_free(t);
84 dns_cache_flush(&s->cache);
85 dns_zone_flush(&s->zone);
87 LIST_REMOVE(scopes, s->manager->dns_scopes, s);
88 strv_free(s->domains);
94 DnsServer *dns_scope_get_dns_server(DnsScope *s) {
97 if (s->protocol != DNS_PROTOCOL_DNS)
101 return link_get_dns_server(s->link);
103 return manager_get_dns_server(s->manager);
106 void dns_scope_next_dns_server(DnsScope *s) {
109 if (s->protocol != DNS_PROTOCOL_DNS)
113 link_next_dns_server(s->link);
115 manager_next_dns_server(s->manager);
118 int dns_scope_send(DnsScope *s, DnsPacket *p) {
119 union in_addr_union addr;
128 assert(p->protocol == s->protocol);
132 ifindex = s->link->ifindex;
134 mtu = manager_find_mtu(s->manager);
136 if (s->protocol == DNS_PROTOCOL_DNS) {
139 if (DNS_PACKET_QDCOUNT(p) > 1)
142 srv = dns_scope_get_dns_server(s);
146 family = srv->family;
150 if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
156 if (family == AF_INET)
157 fd = manager_dns_ipv4_fd(s->manager);
158 else if (family == AF_INET6)
159 fd = manager_dns_ipv6_fd(s->manager);
161 return -EAFNOSUPPORT;
165 } else if (s->protocol == DNS_PROTOCOL_LLMNR) {
167 if (DNS_PACKET_QDCOUNT(p) > 1)
170 if (!ratelimit_test(&s->ratelimit))
176 if (family == AF_INET) {
177 addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
178 fd = manager_llmnr_ipv4_udp_fd(s->manager);
179 } else if (family == AF_INET6) {
180 addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
181 fd = manager_llmnr_ipv6_udp_fd(s->manager);
183 return -EAFNOSUPPORT;
187 return -EAFNOSUPPORT;
189 r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
196 int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port) {
197 _cleanup_close_ int fd = -1;
198 union sockaddr_union sa = {};
200 static const int one = 1;
204 assert((family == AF_UNSPEC) == !address);
206 if (family == AF_UNSPEC) {
209 srv = dns_scope_get_dns_server(s);
213 sa.sa.sa_family = srv->family;
214 if (srv->family == AF_INET) {
215 sa.in.sin_port = htobe16(port);
216 sa.in.sin_addr = srv->address.in;
217 salen = sizeof(sa.in);
218 } else if (srv->family == AF_INET6) {
219 sa.in6.sin6_port = htobe16(port);
220 sa.in6.sin6_addr = srv->address.in6;
221 sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
222 salen = sizeof(sa.in6);
224 return -EAFNOSUPPORT;
226 sa.sa.sa_family = family;
228 if (family == AF_INET) {
229 sa.in.sin_port = htobe16(port);
230 sa.in.sin_addr = address->in;
231 salen = sizeof(sa.in);
232 } else if (family == AF_INET6) {
233 sa.in6.sin6_port = htobe16(port);
234 sa.in6.sin6_addr = address->in6;
235 sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
236 salen = sizeof(sa.in6);
238 return -EAFNOSUPPORT;
241 fd = socket(sa.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
245 r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
250 uint32_t ifindex = htobe32(s->link->ifindex);
252 if (sa.sa.sa_family == AF_INET) {
253 r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
256 } else if (sa.sa.sa_family == AF_INET6) {
257 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
263 if (s->protocol == DNS_PROTOCOL_LLMNR) {
264 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
266 if (sa.sa.sa_family == AF_INET) {
267 r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
270 } else if (sa.sa.sa_family == AF_INET6) {
271 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
277 r = connect(fd, &sa.sa, salen);
278 if (r < 0 && errno != EINPROGRESS)
287 DnsScopeMatch dns_scope_good_domain(DnsScope *s, const char *domain) {
293 STRV_FOREACH(i, s->domains)
294 if (dns_name_endswith(domain, *i) > 0)
295 return DNS_SCOPE_YES;
297 if (dns_name_root(domain) != 0)
300 if (is_localhost(domain))
303 if (s->protocol == DNS_PROTOCOL_DNS) {
304 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
305 dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 &&
306 dns_name_single_label(domain) == 0)
307 return DNS_SCOPE_MAYBE;
312 if (s->protocol == DNS_PROTOCOL_MDNS) {
313 if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0 ||
314 dns_name_endswith(domain, "0.8.e.f.ip6.arpa") > 0 ||
315 (dns_name_endswith(domain, "local") > 0 && dns_name_equal(domain, "local") == 0))
316 return DNS_SCOPE_MAYBE;
321 if (s->protocol == DNS_PROTOCOL_LLMNR) {
322 if (dns_name_endswith(domain, "in-addr.arpa") > 0 ||
323 dns_name_endswith(domain, "ip6.arpa") > 0 ||
324 dns_name_single_label(domain) > 0)
325 return DNS_SCOPE_MAYBE;
330 assert_not_reached("Unknown scope protocol");
333 int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
337 if (s->protocol == DNS_PROTOCOL_DNS)
340 /* On mDNS and LLMNR, send A and AAAA queries only on the
341 * respective scopes */
343 if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
346 if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
352 int dns_scope_llmnr_membership(DnsScope *s, bool b) {
355 if (s->family == AF_INET) {
356 struct ip_mreqn mreqn = {
357 .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
358 .imr_ifindex = s->link->ifindex,
361 fd = manager_llmnr_ipv4_udp_fd(s->manager);
365 /* Always first try to drop membership before we add
366 * one. This is necessary on some devices, such as
369 setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
371 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
374 } else if (s->family == AF_INET6) {
375 struct ipv6_mreq mreq = {
376 .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
377 .ipv6mr_interface = s->link->ifindex,
380 fd = manager_llmnr_ipv6_udp_fd(s->manager);
385 setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
387 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
390 return -EAFNOSUPPORT;
395 int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address) {
399 if (s->protocol != DNS_PROTOCOL_DNS)
403 return !!link_find_dns_server(s->link, family, address);
405 return !!manager_find_dns_server(s->manager, family, address);
408 static int dns_scope_make_reply_packet(
418 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
424 if ((!q || q->n_keys <= 0)
425 && (!answer || answer->n_rrs <= 0)
426 && (!soa || soa->n_rrs <= 0))
429 r = dns_packet_new(&p, s->protocol, 0);
433 DNS_PACKET_HEADER(p)->id = id;
434 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
446 for (i = 0; i < q->n_keys; i++) {
447 r = dns_packet_append_key(p, q->keys[i], NULL);
452 DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
456 for (i = 0; i < answer->n_rrs; i++) {
457 r = dns_packet_append_rr(p, answer->rrs[i], NULL);
462 DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
466 for (i = 0; i < soa->n_rrs; i++) {
467 r = dns_packet_append_rr(p, soa->rrs[i], NULL);
472 DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
481 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
482 _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
483 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
484 bool tentative = false;
490 if (p->protocol != DNS_PROTOCOL_LLMNR)
493 if (p->ipproto == IPPROTO_UDP) {
494 /* Don't accept UDP queries directed to anything but
495 * the LLMNR multicast addresses. See RFC 4795,
498 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
501 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
505 r = dns_packet_extract(p);
507 log_debug("Failed to extract resources from incoming packet: %s", strerror(-r));
511 if (DNS_PACKET_C(p)) {
512 /* FIXME: Somebody notified us about a likely conflict */
516 r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
518 log_debug("Failed to lookup key: %s", strerror(-r));
525 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
527 r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
529 log_debug("Failed to build reply packet: %s", strerror(-r));
534 r = dns_stream_write_packet(stream, reply);
536 if (!ratelimit_test(&s->ratelimit))
539 if (p->family == AF_INET)
540 fd = manager_llmnr_ipv4_udp_fd(s->manager);
541 else if (p->family == AF_INET6)
542 fd = manager_llmnr_ipv6_udp_fd(s->manager);
544 log_debug("Unknown protocol");
548 log_debug("Failed to get reply socket: %s", strerror(-fd));
552 /* Note that we always immediately reply to all LLMNR
553 * requests, and do not wait any time, since we
554 * verified uniqueness for all records. Also see RFC
555 * 4795, Section 2.7 */
557 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
561 log_debug("Failed to send reply packet: %s", strerror(-r));
566 DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *question, bool cache_ok) {
572 /* Try to find an ongoing transaction that is a equal or a
573 * superset of the specified question */
575 LIST_FOREACH(transactions_by_scope, t, scope->transactions) {
577 /* Refuse reusing transactions that completed based on
578 * cached data instead of a real packet, if that's
581 IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
585 if (dns_question_is_superset(t->question, question) > 0)