chiark / gitweb /
resolved: we don't need the DNS server "source" concept anymore, remove it
[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 <netinet/tcp.h>
23
24 #include "missing.h"
25 #include "strv.h"
26 #include "socket-util.h"
27 #include "af-list.h"
28 #include "resolved-dns-domain.h"
29 #include "resolved-dns-scope.h"
30
31 #define SEND_TIMEOUT_USEC (2*USEC_PER_SEC)
32
33 int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
34         DnsScope *s;
35
36         assert(m);
37         assert(ret);
38
39         s = new0(DnsScope, 1);
40         if (!s)
41                 return -ENOMEM;
42
43         s->manager = m;
44         s->link = l;
45         s->protocol = protocol;
46         s->family = family;
47
48         LIST_PREPEND(scopes, m->dns_scopes, s);
49
50         dns_scope_llmnr_membership(s, true);
51
52         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));
53
54         *ret = s;
55         return 0;
56 }
57
58 DnsScope* dns_scope_free(DnsScope *s) {
59         DnsQueryTransaction *t;
60
61         if (!s)
62                 return NULL;
63
64         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));
65
66         dns_scope_llmnr_membership(s, false);
67
68         while ((t = s->transactions)) {
69
70                 /* Abort the transaction, but make sure it is not
71                  * freed while we still look at it */
72
73                 t->block_gc++;
74                 dns_query_transaction_complete(t, DNS_QUERY_ABORTED);
75                 t->block_gc--;
76
77                 dns_query_transaction_free(t);
78         }
79
80         dns_cache_flush(&s->cache);
81         dns_zone_flush(&s->zone);
82
83         LIST_REMOVE(scopes, s->manager->dns_scopes, s);
84         strv_free(s->domains);
85         free(s);
86
87         return NULL;
88 }
89
90 DnsServer *dns_scope_get_server(DnsScope *s) {
91         assert(s);
92
93         if (s->protocol != DNS_PROTOCOL_DNS)
94                 return NULL;
95
96         if (s->link)
97                 return link_get_dns_server(s->link);
98         else
99                 return manager_get_dns_server(s->manager);
100 }
101
102 void dns_scope_next_dns_server(DnsScope *s) {
103         assert(s);
104
105         if (s->protocol != DNS_PROTOCOL_DNS)
106                 return;
107
108         if (s->link)
109                 link_next_dns_server(s->link);
110         else
111                 manager_next_dns_server(s->manager);
112 }
113
114 int dns_scope_send(DnsScope *s, DnsPacket *p) {
115         union in_addr_union addr;
116         int ifindex = 0, r;
117         int family;
118         uint16_t port;
119         uint32_t mtu;
120         int fd;
121
122         assert(s);
123         assert(p);
124         assert(p->protocol == s->protocol);
125
126         if (s->link) {
127                 mtu = s->link->mtu;
128                 ifindex = s->link->ifindex;
129         } else
130                 mtu = manager_find_mtu(s->manager);
131
132         if (s->protocol == DNS_PROTOCOL_DNS) {
133                 DnsServer *srv;
134
135                 if (DNS_PACKET_QDCOUNT(p) > 1)
136                         return -ENOTSUP;
137
138                 srv = dns_scope_get_server(s);
139                 if (!srv)
140                         return -ESRCH;
141
142                 family = srv->family;
143                 addr = srv->address;
144                 port = 53;
145
146                 if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
147                         return -EMSGSIZE;
148
149                 if (p->size > mtu)
150                         return -EMSGSIZE;
151
152                 if (family == AF_INET)
153                         fd = manager_dns_ipv4_fd(s->manager);
154                 else if (family == AF_INET6)
155                         fd = manager_dns_ipv6_fd(s->manager);
156                 else
157                         return -EAFNOSUPPORT;
158                 if (fd < 0)
159                         return fd;
160
161         } else if (s->protocol == DNS_PROTOCOL_LLMNR) {
162
163                 if (DNS_PACKET_QDCOUNT(p) > 1)
164                         return -ENOTSUP;
165
166                 family = s->family;
167                 port = 5355;
168
169                 if (family == AF_INET) {
170                         addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
171                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
172                 } else if (family == AF_INET6) {
173                         addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
174                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
175                 } else
176                         return -EAFNOSUPPORT;
177                 if (fd < 0)
178                         return fd;
179         } else
180                 return -EAFNOSUPPORT;
181
182         r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
183         if (r < 0)
184                 return r;
185
186         return 1;
187 }
188
189 int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port) {
190         _cleanup_close_ int fd = -1;
191         union sockaddr_union sa = {};
192         socklen_t salen;
193         static const int one = 1;
194         int ret, r;
195
196         assert(s);
197         assert((family == AF_UNSPEC) == !address);
198
199         if (family == AF_UNSPEC) {
200                 DnsServer *srv;
201
202                 srv = dns_scope_get_server(s);
203                 if (!srv)
204                         return -ESRCH;
205
206                 sa.sa.sa_family = srv->family;
207                 if (srv->family == AF_INET) {
208                         sa.in.sin_port = htobe16(port);
209                         sa.in.sin_addr = srv->address.in;
210                         salen = sizeof(sa.in);
211                 } else if (srv->family == AF_INET6) {
212                         sa.in6.sin6_port = htobe16(port);
213                         sa.in6.sin6_addr = srv->address.in6;
214                         sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
215                         salen = sizeof(sa.in6);
216                 } else
217                         return -EAFNOSUPPORT;
218         } else {
219                 sa.sa.sa_family = family;
220
221                 if (family == AF_INET) {
222                         sa.in.sin_port = htobe16(port);
223                         sa.in.sin_addr = address->in;
224                         salen = sizeof(sa.in);
225                 } else if (family == AF_INET6) {
226                         sa.in6.sin6_port = htobe16(port);
227                         sa.in6.sin6_addr = address->in6;
228                         sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
229                         salen = sizeof(sa.in6);
230                 } else
231                         return -EAFNOSUPPORT;
232         }
233
234         fd = socket(sa.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
235         if (fd < 0)
236                 return -errno;
237
238         r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
239         if (r < 0)
240                 return -errno;
241
242         if (s->link) {
243                 uint32_t ifindex = htobe32(s->link->ifindex);
244
245                 if (sa.sa.sa_family == AF_INET) {
246                         r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
247                         if (r < 0)
248                                 return -errno;
249                 } else if (sa.sa.sa_family == AF_INET6) {
250                         r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
251                         if (r < 0)
252                                 return -errno;
253                 }
254         }
255
256         if (s->protocol == DNS_PROTOCOL_LLMNR) {
257                 /* RFC 4795, section 2.5 suggests the TTL to be set to 1 */
258
259                 if (sa.sa.sa_family == AF_INET) {
260                         r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
261                         if (r < 0)
262                                 return -errno;
263                 } else if (sa.sa.sa_family == AF_INET6) {
264                         r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
265                         if (r < 0)
266                                 return -errno;
267                 }
268         }
269
270         r = connect(fd, &sa.sa, salen);
271         if (r < 0 && errno != EINPROGRESS)
272                 return -errno;
273
274         ret = fd;
275         fd = -1;
276
277         return ret;
278 }
279
280 DnsScopeMatch dns_scope_good_domain(DnsScope *s, const char *domain) {
281         char **i;
282
283         assert(s);
284         assert(domain);
285
286         STRV_FOREACH(i, s->domains)
287                 if (dns_name_endswith(domain, *i) > 0)
288                         return DNS_SCOPE_YES;
289
290         if (dns_name_root(domain) != 0)
291                 return DNS_SCOPE_NO;
292
293         if (is_localhost(domain))
294                 return DNS_SCOPE_NO;
295
296         if (s->protocol == DNS_PROTOCOL_DNS) {
297                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
298                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 &&
299                     dns_name_single_label(domain) == 0)
300                         return DNS_SCOPE_MAYBE;
301
302                 return DNS_SCOPE_NO;
303         }
304
305         if (s->protocol == DNS_PROTOCOL_MDNS) {
306                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0 ||
307                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa") > 0 ||
308                     (dns_name_endswith(domain, "local") > 0 && dns_name_equal(domain, "local") == 0))
309                         return DNS_SCOPE_MAYBE;
310
311                 return DNS_SCOPE_NO;
312         }
313
314         if (s->protocol == DNS_PROTOCOL_LLMNR) {
315                 if (dns_name_endswith(domain, "in-addr.arpa") > 0 ||
316                     dns_name_endswith(domain, "ip6.arpa") > 0 ||
317                     dns_name_single_label(domain) > 0)
318                         return DNS_SCOPE_MAYBE;
319
320                 return DNS_SCOPE_NO;
321         }
322
323         assert_not_reached("Unknown scope protocol");
324 }
325
326 int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
327         assert(s);
328         assert(key);
329
330         if (s->protocol == DNS_PROTOCOL_DNS)
331                 return true;
332
333         /* On mDNS and LLMNR, send A and AAAA queries only on the
334          * respective scopes */
335
336         if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
337                 return false;
338
339         if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
340                 return false;
341
342         return true;
343 }
344
345 int dns_scope_llmnr_membership(DnsScope *s, bool b) {
346         int fd;
347
348         if (s->family == AF_INET) {
349                 struct ip_mreqn mreqn = {
350                         .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
351                         .imr_ifindex = s->link->ifindex,
352                 };
353
354                 fd = manager_llmnr_ipv4_udp_fd(s->manager);
355                 if (fd < 0)
356                         return fd;
357
358                 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
359                         return -errno;
360
361         } else if (s->family == AF_INET6) {
362                 struct ipv6_mreq mreq = {
363                         .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
364                         .ipv6mr_interface = s->link->ifindex,
365                 };
366
367                 fd = manager_llmnr_ipv6_udp_fd(s->manager);
368                 if (fd < 0)
369                         return fd;
370
371                 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
372                         return -errno;
373         } else
374                 return -EAFNOSUPPORT;
375
376         return 0;
377 }
378
379 int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address) {
380         assert(s);
381         assert(address);
382
383         if (s->protocol != DNS_PROTOCOL_DNS)
384                 return 1;
385
386         if (s->link)
387                 return !!link_find_dns_server(s->link,  family, address);
388         else
389                 return !!manager_find_dns_server(s->manager, family, address);
390 }
391
392 static int dns_scope_make_reply_packet(DnsScope *s, uint16_t id, int rcode, DnsQuestion *q, DnsAnswer *a, DnsPacket **ret) {
393         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
394         unsigned i;
395         int r;
396
397         assert(s);
398
399         if (q->n_keys <= 0 && a->n_rrs <= 0)
400                 return -EINVAL;
401
402         r = dns_packet_new(&p, s->protocol, 0);
403         if (r < 0)
404                 return r;
405
406         DNS_PACKET_HEADER(p)->id = id;
407         DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
408                                                               1 /* qr */,
409                                                               0 /* opcode */,
410                                                               0 /* c */,
411                                                               0 /* tc */,
412                                                               0 /* t */,
413                                                               0 /* (ra) */,
414                                                               0 /* (ad) */,
415                                                               0 /* (cd) */,
416                                                               rcode));
417
418         if (q) {
419                 for (i = 0; i < q->n_keys; i++) {
420                         r = dns_packet_append_key(p, q->keys[i], NULL);
421                         if (r < 0)
422                                 return r;
423                 }
424
425                 DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
426         }
427
428         if (a) {
429                 for (i = 0; i < a->n_rrs; i++) {
430                         r = dns_packet_append_rr(p, a->rrs[i], NULL);
431                         if (r < 0)
432                                 return r;
433                 }
434
435                 DNS_PACKET_HEADER(p)->ancount = htobe16(a->n_rrs);
436         }
437
438         *ret = p;
439         p = NULL;
440
441         return 0;
442 }
443
444 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
445         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
446         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
447         int r, fd;
448
449         assert(s);
450         assert(p);
451
452         if (p->protocol != DNS_PROTOCOL_LLMNR)
453                 return;
454
455         r = dns_packet_extract(p);
456         if (r < 0) {
457                 log_debug("Failed to extract resources from incoming packet: %s", strerror(-r));
458                 return;
459         }
460
461         if (DNS_PACKET_C(p)) {
462                 /* FIXME: Somebody notified us about a likely conflict */
463                 return;
464         }
465
466         r = dns_zone_lookup(&s->zone, p->question, &answer);
467         if (r < 0) {
468                 log_debug("Failed to lookup key: %s", strerror(-r));
469                 return;
470         }
471         if (r == 0)
472                 return;
473
474         r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, &reply);
475         if (r < 0) {
476                 log_debug("Failed to build reply packet: %s", strerror(-r));
477                 return;
478         }
479
480         if (stream)
481                 r = dns_stream_write_packet(stream, reply);
482         else {
483                 if (p->family == AF_INET)
484                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
485                 else if (p->family == AF_INET6)
486                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
487                 else {
488                         log_debug("Unknown protocol");
489                         return;
490                 }
491                 if (fd < 0) {
492                         log_debug("Failed to get reply socket: %s", strerror(-fd));
493                         return;
494                 }
495
496                 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
497         }
498
499         if (r < 0) {
500                 log_debug("Failed to send reply packet: %s", strerror(-r));
501                 return;
502         }
503 }