resolved-dns-scope.c revision faec72d5dedae93f43c2dd624de1392ed9bacd80
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt/***
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt This file is part of systemd.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Copyright 2014 Lennart Poettering
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is free software; you can redistribute it and/or modify it
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt under the terms of the GNU Lesser General Public License as published by
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt (at your option) any later version.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is distributed in the hope that it will be useful, but
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Lesser General Public License for more details.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt You should have received a copy of the GNU Lesser General Public License
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt***/
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt#include <netinet/tcp.h>
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt#include "strv.h"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt#include "socket-util.h"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt#include "resolved-dns-domain.h"
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt#include "resolved-dns-scope.h"
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt#define SEND_TIMEOUT_USEC (2*USEC_PER_SEC)
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktint dns_scope_new(Manager *m, DnsScope **ret, DnsScopeType t) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt DnsScope *s;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt assert(m);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt assert(ret);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt s = new0(DnsScope, 1);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (!s)
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt return -ENOMEM;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt s->manager = m;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt s->type = t;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt LIST_PREPEND(scopes, m->dns_scopes, s);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt *ret = s;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt return 0;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt}
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik FlyktDnsScope* dns_scope_free(DnsScope *s) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt if (!s)
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt return NULL;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt while (s->transactions) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt DnsQuery *q;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt q = s->transactions->query;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt dns_query_transaction_free(s->transactions);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt dns_query_finish(q);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt }
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt LIST_REMOVE(scopes, s->manager->dns_scopes, s);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt strv_free(s->domains);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt free(s);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt return NULL;
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt}
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik FlyktDnsServer *dns_scope_get_server(DnsScope *s) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(s);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (s->link)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return link_get_dns_server(s->link);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt else
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return manager_get_dns_server(s->manager);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktvoid dns_scope_next_dns_server(DnsScope *s) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt assert(s);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt if (s->link)
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt link_next_dns_server(s->link);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt else
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt manager_next_dns_server(s->manager);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt}
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flyktint dns_scope_send(DnsScope *s, DnsPacket *p) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt int ifindex = 0;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt DnsServer *srv;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt int r;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert(s);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert(p);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt srv = dns_scope_get_server(s);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (!srv)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return -ESRCH;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (s->link) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (p->size > s->link->mtu)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return -EMSGSIZE;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt ifindex = s->link->ifindex;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt } else {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt uint32_t mtu;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt mtu = manager_find_mtu(s->manager);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (mtu > 0) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (p->size > mtu)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return -EMSGSIZE;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt }
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt }
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return -EMSGSIZE;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (srv->family == AF_INET)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt r = manager_dns_ipv4_send(s->manager, srv, ifindex, p);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt else if (srv->family == AF_INET6)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt r = manager_dns_ipv6_send(s->manager, srv, ifindex, p);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt else
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return -EAFNOSUPPORT;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (r < 0)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return r;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return 1;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt}
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flyktint dns_scope_tcp_socket(DnsScope *s) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt _cleanup_close_ int fd = -1;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt union sockaddr_union sa = {};
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt socklen_t salen;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt int one, ifindex, ret;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt DnsServer *srv;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt int r;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt assert(s);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt srv = dns_scope_get_server(s);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (!srv)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt return -ESRCH;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (s->link)
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt ifindex = s->link->ifindex;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt sa.sa.sa_family = srv->family;
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt if (srv->family == AF_INET) {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt sa.in.sin_port = htobe16(53);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt sa.in.sin_addr = srv->address.in;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt salen = sizeof(sa.in);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt } else if (srv->family == AF_INET6) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt sa.in6.sin6_port = htobe16(53);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt sa.in6.sin6_addr = srv->address.in6;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt sa.in6.sin6_scope_id = ifindex;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt salen = sizeof(sa.in6);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt } else
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt return -EAFNOSUPPORT;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt fd = socket(srv->family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (fd < 0)
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt return -errno;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt one = 1;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = connect(fd, &sa.sa, salen);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0 && errno != EINPROGRESS)
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt return -errno;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt ret = fd;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt fd = -1;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt return ret;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt}
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik FlyktDnsScopeMatch dns_scope_test(DnsScope *s, const char *domain) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt char **i;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt assert(s);
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt assert(domain);
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt STRV_FOREACH(i, s->domains)
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt if (dns_name_endswith(domain, *i))
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt return DNS_SCOPE_YES;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt if (dns_name_root(domain))
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt return DNS_SCOPE_NO;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt if (is_localhost(domain))
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt return DNS_SCOPE_NO;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt if (s->type == DNS_SCOPE_MDNS) {
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt if (dns_name_endswith(domain, "254.169.in-addr.arpa") ||
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt dns_name_endswith(domain, "0.8.e.f.ip6.arpa"))
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt return DNS_SCOPE_YES;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt else if (dns_name_endswith(domain, "local") ||
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt !dns_name_single_label(domain))
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt return DNS_SCOPE_MAYBE;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt return DNS_SCOPE_NO;
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt }
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt if (s->type == DNS_SCOPE_DNS) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (dns_name_endswith(domain, "254.169.in-addr.arpa") ||
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt dns_name_endswith(domain, "0.8.e.f.ip6.arpa") ||
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt dns_name_single_label(domain))
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek return DNS_SCOPE_NO;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
d182960ae974a0074010a058d0d909846a2f3f79Patrik Flykt return DNS_SCOPE_MAYBE;
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt }
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt assert_not_reached("Unknown scope type");
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt}
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt