chiark / gitweb /
5141a8d8047920a37c8e071848c8c0c6002f700b
[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 requires 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 *answer, DnsAnswer *soa, 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 && answer->n_rrs <= 0 && soa->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 (answer) {
429                 for (i = 0; i < answer->n_rrs; i++) {
430                         r = dns_packet_append_rr(p, answer->rrs[i], NULL);
431                         if (r < 0)
432                                 return r;
433                 }
434
435                 DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
436         }
437
438         if (soa) {
439                 for (i = 0; i < soa->n_rrs; i++) {
440                         r = dns_packet_append_rr(p, soa->rrs[i], NULL);
441                         if (r < 0)
442                                 return r;
443                 }
444
445                 DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
446         }
447
448         *ret = p;
449         p = NULL;
450
451         return 0;
452 }
453
454 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
455         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
456         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
457         int r, fd;
458
459         assert(s);
460         assert(p);
461
462         if (p->protocol != DNS_PROTOCOL_LLMNR)
463                 return;
464
465         if (p->ipproto == IPPROTO_UDP) {
466                 /* Don't accept UDP queries directed to anything but
467                  * the LLMNR multicast addresses. See RFC 4795,
468                  * section 2.5.*/
469
470                 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
471                         return;
472
473                 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
474                         return;
475         }
476
477         r = dns_packet_extract(p);
478         if (r < 0) {
479                 log_debug("Failed to extract resources from incoming packet: %s", strerror(-r));
480                 return;
481         }
482
483         if (DNS_PACKET_C(p)) {
484                 /* FIXME: Somebody notified us about a likely conflict */
485                 return;
486         }
487
488         r = dns_zone_lookup(&s->zone, p->question, &answer, &soa);
489         if (r < 0) {
490                 log_debug("Failed to lookup key: %s", strerror(-r));
491                 return;
492         }
493         if (r == 0)
494                 return;
495
496         dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
497
498         r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, &reply);
499         if (r < 0) {
500                 log_debug("Failed to build reply packet: %s", strerror(-r));
501                 return;
502         }
503
504         if (stream)
505                 r = dns_stream_write_packet(stream, reply);
506         else {
507                 if (p->family == AF_INET)
508                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
509                 else if (p->family == AF_INET6)
510                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
511                 else {
512                         log_debug("Unknown protocol");
513                         return;
514                 }
515                 if (fd < 0) {
516                         log_debug("Failed to get reply socket: %s", strerror(-fd));
517                         return;
518                 }
519
520                 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
521         }
522
523         if (r < 0) {
524                 log_debug("Failed to send reply packet: %s", strerror(-r));
525                 return;
526         }
527 }