chiark / gitweb /
resolved: enforce limit on concurrent outstanding queries
[elogind.git] / src / resolve / resolved-dns-scope.c
index 4e0a74276830f8ca76869158ea429c73b1cb4641..1fa8401ed50f738388c4d9bc89fc2374a0135163 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <netinet/tcp.h>
+
 #include "strv.h"
+#include "socket-util.h"
 #include "resolved-dns-domain.h"
 #include "resolved-dns-scope.h"
 
@@ -92,10 +95,25 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) {
 
         srv = dns_scope_get_server(s);
         if (!srv)
-                return 0;
+                return -ESRCH;
+
+        if (s->link) {
+                if (p->size > s->link->mtu)
+                        return -EMSGSIZE;
 
-        if (s->link)
                 ifindex = s->link->ifindex;
+        } else {
+                uint32_t mtu;
+
+                mtu = manager_find_mtu(s->manager);
+                if (mtu > 0) {
+                        if (p->size > mtu)
+                                return -EMSGSIZE;
+                }
+        }
+
+        if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
+                return -EMSGSIZE;
 
         if (srv->family == AF_INET)
                 r = manager_dns_ipv4_send(s->manager, srv, ifindex, p);
@@ -110,6 +128,52 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) {
         return 1;
 }
 
+int dns_scope_tcp_socket(DnsScope *s) {
+        _cleanup_close_ int fd = -1;
+        union sockaddr_union sa = {};
+        socklen_t salen;
+        int one, ifindex, ret;
+        DnsServer *srv;
+        int r;
+
+        assert(s);
+
+        srv = dns_scope_get_server(s);
+        if (!srv)
+                return -ESRCH;
+
+        if (s->link)
+                ifindex = s->link->ifindex;
+
+        sa.sa.sa_family = srv->family;
+        if (srv->family == AF_INET) {
+                sa.in.sin_port = htobe16(53);
+                sa.in.sin_addr = srv->address.in;
+                salen = sizeof(sa.in);
+        } else if (srv->family == AF_INET6) {
+                sa.in6.sin6_port = htobe16(53);
+                sa.in6.sin6_addr = srv->address.in6;
+                sa.in6.sin6_scope_id = ifindex;
+                salen = sizeof(sa.in6);
+        } else
+                return -EAFNOSUPPORT;
+
+        fd = socket(srv->family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0)
+                return -errno;
+
+        one = 1;
+        setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
+
+        r = connect(fd, &sa.sa, salen);
+        if (r < 0 && errno != EINPROGRESS)
+                return -errno;
+
+        ret = fd;
+        fd = -1;
+        return ret;
+}
+
 DnsScopeMatch dns_scope_test(DnsScope *s, const char *domain) {
         char **i;
 
@@ -123,11 +187,14 @@ DnsScopeMatch dns_scope_test(DnsScope *s, const char *domain) {
         if (dns_name_root(domain))
                 return DNS_SCOPE_NO;
 
+        if (is_localhost(domain))
+                return DNS_SCOPE_NO;
+
         if (s->type == DNS_SCOPE_MDNS) {
                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") ||
                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa"))
                         return DNS_SCOPE_YES;
-                else if (dns_name_endswith(domain, "local") ||
+                else if (dns_name_endswith(domain, "local") &&
                          !dns_name_single_label(domain))
                         return DNS_SCOPE_MAYBE;