chiark / gitweb /
resolve: add distinct bus error code for hosts that exist but lack A or AAAA records
[elogind.git] / src / resolve / resolved-dns-scope.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include "strv.h"
23 #include "resolved-dns-domain.h"
24 #include "resolved-dns-scope.h"
25
26 #define SEND_TIMEOUT_USEC (2*USEC_PER_SEC)
27
28 int dns_scope_new(Manager *m, DnsScope **ret, DnsScopeType t) {
29         DnsScope *s;
30
31         assert(m);
32         assert(ret);
33
34         s = new0(DnsScope, 1);
35         if (!s)
36                 return -ENOMEM;
37
38         s->manager = m;
39         s->type = t;
40
41         LIST_PREPEND(scopes, m->dns_scopes, s);
42
43         *ret = s;
44         return 0;
45 }
46
47 DnsScope* dns_scope_free(DnsScope *s) {
48         if (!s)
49                 return NULL;
50
51         while (s->transactions) {
52                 DnsQuery *q;
53
54                 q = s->transactions->query;
55                 dns_query_transaction_free(s->transactions);
56
57                 dns_query_finish(q);
58         }
59
60         LIST_REMOVE(scopes, s->manager->dns_scopes, s);
61         strv_free(s->domains);
62         free(s);
63
64         return NULL;
65 }
66
67 DnsServer *dns_scope_get_server(DnsScope *s) {
68         assert(s);
69
70         if (s->link)
71                 return link_get_dns_server(s->link);
72         else
73                 return manager_get_dns_server(s->manager);
74 }
75
76 void dns_scope_next_dns_server(DnsScope *s) {
77         assert(s);
78
79         if (s->link)
80                 link_next_dns_server(s->link);
81         else
82                 manager_next_dns_server(s->manager);
83 }
84
85 int dns_scope_send(DnsScope *s, DnsPacket *p) {
86         int ifindex = 0;
87         DnsServer *srv;
88         int r;
89
90         assert(s);
91         assert(p);
92
93         srv = dns_scope_get_server(s);
94         if (!srv)
95                 return 0;
96
97         if (s->link)
98                 ifindex = s->link->ifindex;
99
100         if (srv->family == AF_INET)
101                 r = manager_dns_ipv4_send(s->manager, srv, ifindex, p);
102         else if (srv->family == AF_INET6)
103                 r = manager_dns_ipv6_send(s->manager, srv, ifindex, p);
104         else
105                 return -EAFNOSUPPORT;
106
107         if (r < 0)
108                 return r;
109
110         return 1;
111 }
112
113 DnsScopeMatch dns_scope_test(DnsScope *s, const char *domain) {
114         char **i;
115
116         assert(s);
117         assert(domain);
118
119         STRV_FOREACH(i, s->domains)
120                 if (dns_name_endswith(domain, *i))
121                         return DNS_SCOPE_YES;
122
123         if (dns_name_root(domain))
124                 return DNS_SCOPE_NO;
125
126         if (s->type == DNS_SCOPE_MDNS) {
127                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") ||
128                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa"))
129                         return DNS_SCOPE_YES;
130                 else if (dns_name_endswith(domain, "local") ||
131                          !dns_name_single_label(domain))
132                         return DNS_SCOPE_MAYBE;
133
134                 return DNS_SCOPE_NO;
135         }
136
137         if (s->type == DNS_SCOPE_DNS) {
138                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") ||
139                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa") ||
140                     dns_name_single_label(domain))
141                         return DNS_SCOPE_NO;
142
143                 return DNS_SCOPE_MAYBE;
144         }
145
146         assert_not_reached("Unknown scope type");
147 }