]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
Merge pull request #2104 from evverx/rlimit-util-test
[thirdparty/systemd.git] / src / resolve / resolved-manager.c
CommitLineData
091a364c
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Tom Gundersen <teg@jklm.no>
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
07630cea
LP
22#include <netinet/in.h>
23#include <poll.h>
74b2466e 24#include <sys/ioctl.h>
091a364c 25
a2a416f7 26#include "af-list.h"
b5efdb8a 27#include "alloc-util.h"
07630cea 28#include "dns-domain.h"
3ffd4af2 29#include "fd-util.h"
a5a807e6 30#include "fileio-label.h"
07630cea 31#include "hostname-util.h"
c004493c 32#include "io-util.h"
07630cea
LP
33#include "netlink-util.h"
34#include "network-internal.h"
822db23c 35#include "ordered-set.h"
6bedfcbb 36#include "parse-util.h"
3df3e884 37#include "random-util.h"
39d8db04 38#include "resolved-bus.h"
07630cea 39#include "resolved-conf.h"
5f402ae8 40#include "resolved-llmnr.h"
07630cea 41#include "resolved-manager.h"
f8dc7e34 42#include "resolved-resolv-conf.h"
07630cea 43#include "socket-util.h"
8b43440b 44#include "string-table.h"
07630cea
LP
45#include "string-util.h"
46#include "utf8.h"
74b2466e
LP
47
48#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
49
1c4baffc 50static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e
LP
51 Manager *m = userdata;
52 uint16_t type;
53 Link *l;
54 int ifindex, r;
55
56 assert(rtnl);
57 assert(m);
58 assert(mm);
59
1c4baffc 60 r = sd_netlink_message_get_type(mm, &type);
74b2466e
LP
61 if (r < 0)
62 goto fail;
63
64 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
65 if (r < 0)
66 goto fail;
67
68 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
69
70 switch (type) {
71
a2a416f7
LP
72 case RTM_NEWLINK:{
73 bool is_new = !l;
74b2466e 74
a2a416f7 75 if (!l) {
74b2466e
LP
76 r = link_new(m, &l, ifindex);
77 if (r < 0)
78 goto fail;
79 }
80
81 r = link_update_rtnl(l, mm);
82 if (r < 0)
83 goto fail;
84
21d73c87
LP
85 r = link_update_monitor(l);
86 if (r < 0)
87 goto fail;
88
a2a416f7
LP
89 if (is_new)
90 log_debug("Found new link %i/%s", ifindex, l->name);
91
74b2466e 92 break;
a2a416f7 93 }
74b2466e
LP
94
95 case RTM_DELLINK:
96 if (l) {
a2a416f7 97 log_debug("Removing link %i/%s", l->ifindex, l->name);
74b2466e
LP
98 link_free(l);
99 }
100
101 break;
102 }
103
104 return 0;
105
106fail:
da927ba9 107 log_warning_errno(r, "Failed to process RTNL link message: %m");
74b2466e
LP
108 return 0;
109}
110
1c4baffc 111static int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e
LP
112 Manager *m = userdata;
113 union in_addr_union address;
74b2466e 114 uint16_t type;
0dd25fb9 115 int r, ifindex, family;
74b2466e
LP
116 LinkAddress *a;
117 Link *l;
118
119 assert(rtnl);
120 assert(mm);
121 assert(m);
122
1c4baffc 123 r = sd_netlink_message_get_type(mm, &type);
74b2466e
LP
124 if (r < 0)
125 goto fail;
126
127 r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
128 if (r < 0)
129 goto fail;
130
131 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
132 if (!l)
133 return 0;
134
135 r = sd_rtnl_message_addr_get_family(mm, &family);
136 if (r < 0)
137 goto fail;
138
139 switch (family) {
140
141 case AF_INET:
1c4baffc 142 r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
74b2466e 143 if (r < 0) {
1c4baffc 144 r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
74b2466e
LP
145 if (r < 0)
146 goto fail;
147 }
148
149 break;
150
151 case AF_INET6:
1c4baffc 152 r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
74b2466e 153 if (r < 0) {
1c4baffc 154 r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e
LP
155 if (r < 0)
156 goto fail;
157 }
158
159 break;
160
161 default:
162 return 0;
163 }
164
165 a = link_find_address(l, family, &address);
166
167 switch (type) {
168
169 case RTM_NEWADDR:
170
171 if (!a) {
172 r = link_address_new(l, &a, family, &address);
173 if (r < 0)
174 return r;
175 }
176
177 r = link_address_update_rtnl(a, mm);
178 if (r < 0)
179 return r;
180
181 break;
182
183 case RTM_DELADDR:
3e044c49 184 link_address_free(a);
74b2466e
LP
185 break;
186 }
187
188 return 0;
189
190fail:
da927ba9 191 log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e
LP
192 return 0;
193}
194
74b2466e 195static int manager_rtnl_listen(Manager *m) {
4afd3348 196 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
1c4baffc 197 sd_netlink_message *i;
74b2466e
LP
198 int r;
199
200 assert(m);
201
cc98b302 202 /* First, subscribe to interfaces coming and going */
1c4baffc 203 r = sd_netlink_open(&m->rtnl);
74b2466e
LP
204 if (r < 0)
205 return r;
206
1c4baffc 207 r = sd_netlink_attach_event(m->rtnl, m->event, 0);
74b2466e
LP
208 if (r < 0)
209 return r;
210
1c4baffc 211 r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
74b2466e
LP
212 if (r < 0)
213 return r;
214
1c4baffc 215 r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
74b2466e
LP
216 if (r < 0)
217 return r;
218
1c4baffc 219 r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e
LP
220 if (r < 0)
221 return r;
091a364c 222
1c4baffc 223 r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e
LP
224 if (r < 0)
225 return r;
226
227 /* Then, enumerate all links */
228 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
229 if (r < 0)
230 return r;
231
1c4baffc 232 r = sd_netlink_message_request_dump(req, true);
74b2466e
LP
233 if (r < 0)
234 return r;
235
1c4baffc 236 r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e
LP
237 if (r < 0)
238 return r;
239
1c4baffc 240 for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e
LP
241 r = manager_process_link(m->rtnl, i, m);
242 if (r < 0)
243 return r;
244 }
245
1c4baffc
TG
246 req = sd_netlink_message_unref(req);
247 reply = sd_netlink_message_unref(reply);
74b2466e
LP
248
249 /* Finally, enumerate all addresses, too */
250 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
251 if (r < 0)
252 return r;
253
1c4baffc 254 r = sd_netlink_message_request_dump(req, true);
74b2466e
LP
255 if (r < 0)
256 return r;
257
1c4baffc 258 r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e
LP
259 if (r < 0)
260 return r;
261
1c4baffc 262 for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e
LP
263 r = manager_process_address(m->rtnl, i, m);
264 if (r < 0)
265 return r;
266 }
267
268 return r;
269}
270
271static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
272 Manager *m = userdata;
273 Iterator i;
274 Link *l;
275 int r;
276
277 assert(m);
278
279 sd_network_monitor_flush(m->network_monitor);
280
281 HASHMAP_FOREACH(l, m->links, i) {
282 r = link_update_monitor(l);
283 if (r < 0)
da927ba9 284 log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
74b2466e
LP
285 }
286
287 r = manager_write_resolv_conf(m);
288 if (r < 0)
da927ba9 289 log_warning_errno(r, "Could not update resolv.conf: %m");
74b2466e
LP
290
291 return 0;
292}
293
294static int manager_network_monitor_listen(Manager *m) {
295 int r, fd, events;
296
297 assert(m);
298
0014a4ad 299 r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e
LP
300 if (r < 0)
301 return r;
302
303 fd = sd_network_monitor_get_fd(m->network_monitor);
304 if (fd < 0)
305 return fd;
306
307 events = sd_network_monitor_get_events(m->network_monitor);
308 if (events < 0)
309 return events;
310
311 r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
312 if (r < 0)
313 return r;
314
315 return 0;
316}
317
78c6a153 318static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
eb60f9cd 319 _cleanup_free_ char *h = NULL, *n = NULL;
78c6a153
LP
320 char label[DNS_LABEL_MAX];
321 const char *p;
322 int r, k;
eb60f9cd 323
78c6a153
LP
324 assert(llmnr_hostname);
325 assert(mdns_hostname);
326
327 /* Extract and normalize the first label of the locally
328 * configured hostname, and check it's not "localhost". */
eb60f9cd
LP
329
330 h = gethostname_malloc();
331 if (!h)
332 return log_oom();
333
78c6a153
LP
334 p = h;
335 r = dns_label_unescape(&p, label, sizeof(label));
336 if (r < 0)
337 return log_error_errno(r, "Failed to unescape host name: %m");
338 if (r == 0) {
339 log_error("Couldn't find a single label in hosntame.");
340 return -EINVAL;
341 }
342
343 k = dns_label_undo_idna(label, r, label, sizeof(label));
344 if (k < 0)
345 return log_error_errno(k, "Failed to undo IDNA: %m");
346 if (k > 0)
347 r = k;
348
349 if (!utf8_is_valid(label)) {
eb60f9cd
LP
350 log_error("System hostname is not UTF-8 clean.");
351 return -EINVAL;
352 }
353
422baca0 354 r = dns_label_escape_new(label, r, &n);
78c6a153
LP
355 if (r < 0)
356 return log_error_errno(r, "Failed to escape host name: %m");
357
358 if (is_localhost(n)) {
359 log_debug("System hostname is 'localhost', ignoring.");
360 return -EINVAL;
eb60f9cd
LP
361 }
362
78c6a153
LP
363 r = dns_name_concat(n, "local", mdns_hostname);
364 if (r < 0)
365 return log_error_errno(r, "Failed to determine mDNS hostname: %m");
366
367 *llmnr_hostname = n;
eb60f9cd
LP
368 n = NULL;
369
370 return 0;
371}
372
373static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
78c6a153 374 _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
eb60f9cd
LP
375 Manager *m = userdata;
376 int r;
377
378 assert(m);
379
78c6a153 380 r = determine_hostname(&llmnr_hostname, &mdns_hostname);
eb60f9cd
LP
381 if (r < 0)
382 return 0; /* ignore invalid hostnames */
383
78c6a153 384 if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
eb60f9cd
LP
385 return 0;
386
78c6a153
LP
387 log_info("System hostname changed to '%s'.", llmnr_hostname);
388
389 free(m->llmnr_hostname);
390 free(m->mdns_hostname);
391
392 m->llmnr_hostname = llmnr_hostname;
393 m->mdns_hostname = mdns_hostname;
394
395 llmnr_hostname = mdns_hostname = NULL;
eb60f9cd
LP
396
397 manager_refresh_rrs(m);
398
399 return 0;
400}
401
402static int manager_watch_hostname(Manager *m) {
eb60f9cd
LP
403 int r;
404
405 assert(m);
406
407 m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
408 if (m->hostname_fd < 0) {
56f64d95 409 log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd
LP
410 return 0;
411 }
412
413 r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
414 if (r < 0) {
415 if (r == -EPERM)
416 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
417 m->hostname_fd = safe_close(m->hostname_fd);
8d3d7072
MS
418 else
419 return log_error_errno(r, "Failed to add hostname event source: %m");
eb60f9cd
LP
420 }
421
78c6a153 422 r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
eb60f9cd
LP
423 if (r < 0) {
424 log_info("Defaulting to hostname 'linux'.");
78c6a153
LP
425 m->llmnr_hostname = strdup("linux");
426 if (!m->llmnr_hostname)
427 return log_oom();
428
429 m->mdns_hostname = strdup("linux.local");
430 if (!m->mdns_hostname)
eb60f9cd
LP
431 return log_oom();
432 } else
78c6a153 433 log_info("Using system hostname '%s'.", m->llmnr_hostname);
eb60f9cd
LP
434
435 return 0;
436}
437
4d506d6b
LP
438static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
439 _cleanup_free_ char *buffer = NULL;
440 _cleanup_fclose_ FILE *f = NULL;
441 Manager *m = userdata;
442 size_t size = 0;
443 DnsScope *scope;
444
445 assert(s);
446 assert(si);
447 assert(m);
448
449 f = open_memstream(&buffer, &size);
450 if (!f)
451 return log_oom();
452
453 LIST_FOREACH(scopes, scope, m->dns_scopes)
454 dns_scope_dump(scope, f);
455
456 if (fflush_and_check(f) < 0)
457 return log_oom();
458
459 log_dump(LOG_INFO, buffer);
460 return 0;
461}
462
091a364c 463int manager_new(Manager **ret) {
74b2466e 464 _cleanup_(manager_freep) Manager *m = NULL;
091a364c
TG
465 int r;
466
c92e531c
LP
467 assert(ret);
468
091a364c
TG
469 m = new0(Manager, 1);
470 if (!m)
471 return -ENOMEM;
472
1716f6dc 473 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97 474 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
eb60f9cd 475 m->hostname_fd = -1;
1716f6dc 476
4e945a6f 477 m->llmnr_support = SUPPORT_YES;
5cb36f41 478 m->read_resolv_conf = true;
00fa60ae 479 m->need_builtin_fallbacks = true;
091a364c 480
0d2cd476
LP
481 r = dns_trust_anchor_load(&m->trust_anchor);
482 if (r < 0)
483 return r;
484
091a364c
TG
485 r = sd_event_default(&m->event);
486 if (r < 0)
487 return r;
488
489 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
490 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
491
492 sd_event_set_watchdog(m->event, true);
493
eb60f9cd
LP
494 r = manager_watch_hostname(m);
495 if (r < 0)
496 return r;
497
1716f6dc 498 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
499 if (r < 0)
500 return r;
501
502 r = manager_network_monitor_listen(m);
503 if (r < 0)
504 return r;
505
506 r = manager_rtnl_listen(m);
507 if (r < 0)
508 return r;
509
510 r = manager_connect_bus(m);
511 if (r < 0)
512 return r;
513
4d506d6b
LP
514 (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
515
091a364c
TG
516 *ret = m;
517 m = NULL;
518
519 return 0;
520}
521
edc501d4
LP
522int manager_start(Manager *m) {
523 int r;
524
525 assert(m);
526
527 r = manager_llmnr_start(m);
528 if (r < 0)
529 return r;
530
531 return 0;
532}
533
74b2466e
LP
534Manager *manager_free(Manager *m) {
535 Link *l;
091a364c
TG
536
537 if (!m)
74b2466e
LP
538 return NULL;
539
4b95f179
LP
540 dns_server_unlink_all(m->dns_servers);
541 dns_server_unlink_all(m->fallback_dns_servers);
a51c1048
LP
542 dns_search_domain_unlink_all(m->search_domains);
543
74b2466e
LP
544 while ((l = hashmap_first(m->links)))
545 link_free(l);
f0e15467
LP
546
547 while (m->dns_queries)
548 dns_query_free(m->dns_queries);
74b2466e 549
cab5b059
LP
550 dns_scope_free(m->unicast_scope);
551
f0e15467
LP
552 hashmap_free(m->links);
553 hashmap_free(m->dns_transactions);
554
096b6773
LP
555 sd_event_source_unref(m->network_event_source);
556 sd_network_monitor_unref(m->network_monitor);
091a364c 557
a564ca2f
LP
558 sd_netlink_unref(m->rtnl);
559 sd_event_source_unref(m->rtnl_event_source);
560
edc501d4 561 manager_llmnr_stop(m);
623a4c97 562
902bb5d8 563 sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e
LP
564 sd_event_source_unref(m->bus_retry_event_source);
565 sd_bus_unref(m->bus);
091a364c 566
4d506d6b
LP
567 sd_event_source_unref(m->sigusr1_event_source);
568
74b2466e 569 sd_event_unref(m->event);
623a4c97 570
78c6a153
LP
571 dns_resource_key_unref(m->llmnr_host_ipv4_key);
572 dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd 573
eb60f9cd 574 sd_event_source_unref(m->hostname_event_source);
d9fcf2ba 575 safe_close(m->hostname_fd);
78c6a153
LP
576 free(m->llmnr_hostname);
577 free(m->mdns_hostname);
eb60f9cd 578
0d2cd476
LP
579 dns_trust_anchor_flush(&m->trust_anchor);
580
091a364c 581 free(m);
74b2466e
LP
582
583 return NULL;
091a364c
TG
584}
585
1716f6dc 586int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 587 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
588 union {
589 struct cmsghdr header; /* For alignment */
40a1eebd 590 uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
1716f6dc 591 + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97 592 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dc
LP
593 } control;
594 union sockaddr_union sa;
74b2466e 595 struct msghdr mh = {};
1716f6dc 596 struct cmsghdr *cmsg;
74b2466e 597 struct iovec iov;
1716f6dc 598 int ms = 0, r;
74b2466e
LP
599 ssize_t l;
600
601 assert(m);
1716f6dc 602 assert(fd >= 0);
74b2466e
LP
603 assert(ret);
604
74b2466e
LP
605 r = ioctl(fd, FIONREAD, &ms);
606 if (r < 0)
607 return -errno;
608 if (ms < 0)
609 return -EIO;
610
1716f6dc 611 r = dns_packet_new(&p, protocol, ms);
74b2466e
LP
612 if (r < 0)
613 return r;
614
615 iov.iov_base = DNS_PACKET_DATA(p);
616 iov.iov_len = p->allocated;
617
1716f6dc
LP
618 mh.msg_name = &sa.sa;
619 mh.msg_namelen = sizeof(sa);
74b2466e
LP
620 mh.msg_iov = &iov;
621 mh.msg_iovlen = 1;
1716f6dc
LP
622 mh.msg_control = &control;
623 mh.msg_controllen = sizeof(control);
74b2466e 624
a38d9945 625 l = recvmsg(fd, &mh, 0);
74b2466e 626 if (l < 0) {
ad867662 627 if (errno == EAGAIN || errno == EINTR)
74b2466e
LP
628 return 0;
629
630 return -errno;
091a364c
TG
631 }
632
74b2466e
LP
633 if (l <= 0)
634 return -EIO;
091a364c 635
1716f6dc
LP
636 assert(!(mh.msg_flags & MSG_CTRUNC));
637 assert(!(mh.msg_flags & MSG_TRUNC));
638
74b2466e 639 p->size = (size_t) l;
091a364c 640
1716f6dc 641 p->family = sa.sa.sa_family;
623a4c97
LP
642 p->ipproto = IPPROTO_UDP;
643 if (p->family == AF_INET) {
1716f6dc 644 p->sender.in = sa.in.sin_addr;
623a4c97
LP
645 p->sender_port = be16toh(sa.in.sin_port);
646 } else if (p->family == AF_INET6) {
1716f6dc 647 p->sender.in6 = sa.in6.sin6_addr;
623a4c97
LP
648 p->sender_port = be16toh(sa.in6.sin6_port);
649 p->ifindex = sa.in6.sin6_scope_id;
650 } else
1716f6dc 651 return -EAFNOSUPPORT;
74b2466e 652
2a1288ff 653 CMSG_FOREACH(cmsg, &mh) {
74b2466e 654
1716f6dc
LP
655 if (cmsg->cmsg_level == IPPROTO_IPV6) {
656 assert(p->family == AF_INET6);
74b2466e 657
1716f6dc 658 switch (cmsg->cmsg_type) {
74b2466e 659
1716f6dc
LP
660 case IPV6_PKTINFO: {
661 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 662
623a4c97
LP
663 if (p->ifindex <= 0)
664 p->ifindex = i->ipi6_ifindex;
665
1716f6dc
LP
666 p->destination.in6 = i->ipi6_addr;
667 break;
668 }
74b2466e 669
1716f6dc
LP
670 case IPV6_HOPLIMIT:
671 p->ttl = *(int *) CMSG_DATA(cmsg);
672 break;
74b2466e 673
1716f6dc
LP
674 }
675 } else if (cmsg->cmsg_level == IPPROTO_IP) {
676 assert(p->family == AF_INET);
74b2466e 677
1716f6dc 678 switch (cmsg->cmsg_type) {
74b2466e 679
1716f6dc
LP
680 case IP_PKTINFO: {
681 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 682
623a4c97
LP
683 if (p->ifindex <= 0)
684 p->ifindex = i->ipi_ifindex;
685
1716f6dc
LP
686 p->destination.in = i->ipi_addr;
687 break;
688 }
74b2466e 689
623a4c97 690 case IP_TTL:
1716f6dc
LP
691 p->ttl = *(int *) CMSG_DATA(cmsg);
692 break;
693 }
694 }
695 }
74b2466e 696
623a4c97
LP
697 /* The Linux kernel sets the interface index to the loopback
698 * device if the packet came from the local host since it
699 * avoids the routing table in such a case. Let's unset the
700 * interface index in such a case. */
a5f03596 701 if (p->ifindex == LOOPBACK_IFINDEX)
623a4c97
LP
702 p->ifindex = 0;
703
86ad4cd7
TG
704 if (protocol != DNS_PROTOCOL_DNS) {
705 /* If we don't know the interface index still, we look for the
706 * first local interface with a matching address. Yuck! */
707 if (p->ifindex <= 0)
708 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
709 }
623a4c97 710
74b2466e
LP
711 *ret = p;
712 p = NULL;
713
714 return 1;
715}
716
74b2466e
LP
717static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
718 int r;
719
720 assert(fd >= 0);
721 assert(mh);
722
723 for (;;) {
724 if (sendmsg(fd, mh, flags) >= 0)
725 return 0;
726
727 if (errno == EINTR)
728 continue;
729
730 if (errno != EAGAIN)
731 return -errno;
732
733 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
734 if (r < 0)
735 return r;
736 if (r == 0)
737 return -ETIMEDOUT;
738 }
739}
740
72290734
TG
741static int write_loop(int fd, void *message, size_t length) {
742 int r;
743
744 assert(fd >= 0);
745 assert(message);
746
747 for (;;) {
748 if (write(fd, message, length) >= 0)
749 return 0;
750
751 if (errno == EINTR)
752 continue;
753
754 if (errno != EAGAIN)
755 return -errno;
756
757 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
758 if (r < 0)
759 return r;
760 if (r == 0)
761 return -ETIMEDOUT;
762 }
763}
764
765int manager_write(Manager *m, int fd, DnsPacket *p) {
766 int r;
767
768 log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
769
770 r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
771 if (r < 0)
772 return r;
773
774 return 0;
775}
776
623a4c97 777static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
778 union sockaddr_union sa = {
779 .in.sin_family = AF_INET,
74b2466e 780 };
1716f6dc
LP
781 union {
782 struct cmsghdr header; /* For alignment */
783 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
784 } control;
74b2466e
LP
785 struct msghdr mh = {};
786 struct iovec iov;
74b2466e
LP
787
788 assert(m);
1716f6dc
LP
789 assert(fd >= 0);
790 assert(addr);
791 assert(port > 0);
74b2466e
LP
792 assert(p);
793
74b2466e
LP
794 iov.iov_base = DNS_PACKET_DATA(p);
795 iov.iov_len = p->size;
091a364c 796
1716f6dc
LP
797 sa.in.sin_addr = *addr;
798 sa.in.sin_port = htobe16(port),
091a364c 799
74b2466e
LP
800 mh.msg_iov = &iov;
801 mh.msg_iovlen = 1;
802 mh.msg_name = &sa.sa;
803 mh.msg_namelen = sizeof(sa.in);
091a364c 804
74b2466e
LP
805 if (ifindex > 0) {
806 struct cmsghdr *cmsg;
807 struct in_pktinfo *pi;
808
809 zero(control);
810
1716f6dc 811 mh.msg_control = &control;
74b2466e
LP
812 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
813
814 cmsg = CMSG_FIRSTHDR(&mh);
815 cmsg->cmsg_len = mh.msg_controllen;
816 cmsg->cmsg_level = IPPROTO_IP;
817 cmsg->cmsg_type = IP_PKTINFO;
818
819 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
820 pi->ipi_ifindex = ifindex;
821 }
822
823 return sendmsg_loop(fd, &mh, 0);
824}
825
623a4c97 826static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
827 union sockaddr_union sa = {
828 .in6.sin6_family = AF_INET6,
74b2466e 829 };
1716f6dc
LP
830 union {
831 struct cmsghdr header; /* For alignment */
832 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
833 } control;
74b2466e
LP
834 struct msghdr mh = {};
835 struct iovec iov;
74b2466e
LP
836
837 assert(m);
1716f6dc
LP
838 assert(fd >= 0);
839 assert(addr);
840 assert(port > 0);
74b2466e
LP
841 assert(p);
842
74b2466e
LP
843 iov.iov_base = DNS_PACKET_DATA(p);
844 iov.iov_len = p->size;
845
1716f6dc
LP
846 sa.in6.sin6_addr = *addr;
847 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
848 sa.in6.sin6_scope_id = ifindex;
849
850 mh.msg_iov = &iov;
851 mh.msg_iovlen = 1;
852 mh.msg_name = &sa.sa;
853 mh.msg_namelen = sizeof(sa.in6);
854
855 if (ifindex > 0) {
856 struct cmsghdr *cmsg;
857 struct in6_pktinfo *pi;
858
859 zero(control);
860
1716f6dc 861 mh.msg_control = &control;
74b2466e
LP
862 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
863
864 cmsg = CMSG_FIRSTHDR(&mh);
865 cmsg->cmsg_len = mh.msg_controllen;
866 cmsg->cmsg_level = IPPROTO_IPV6;
867 cmsg->cmsg_type = IPV6_PKTINFO;
868
869 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
870 pi->ipi6_ifindex = ifindex;
871 }
872
873 return sendmsg_loop(fd, &mh, 0);
874}
875
623a4c97 876int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dc
LP
877 assert(m);
878 assert(fd >= 0);
879 assert(addr);
880 assert(port > 0);
881 assert(p);
882
a2a416f7
LP
883 log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
884
1716f6dc
LP
885 if (family == AF_INET)
886 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
887 else if (family == AF_INET6)
888 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
889
890 return -EAFNOSUPPORT;
891}
892
e1c95994
LP
893uint32_t manager_find_mtu(Manager *m) {
894 uint32_t mtu = 0;
895 Link *l;
896 Iterator i;
897
898 /* If we don't know on which link a DNS packet would be
899 * delivered, let's find the largest MTU that works on all
900 * interfaces we know of */
901
902 HASHMAP_FOREACH(l, m->links, i) {
903 if (l->mtu <= 0)
904 continue;
905
906 if (mtu <= 0 || l->mtu < mtu)
907 mtu = l->mtu;
908 }
909
910 return mtu;
911}
1716f6dc 912
623a4c97 913int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
914 LinkAddress *a;
915
916 assert(m);
917
4e945a6f 918 a = manager_find_link_address(m, family, in_addr);
ec2c5e43
LP
919 if (a)
920 return a->link->ifindex;
921
922 return 0;
923}
924
eb60f9cd
LP
925void manager_refresh_rrs(Manager *m) {
926 Iterator i;
927 Link *l;
928
929 assert(m);
930
78c6a153
LP
931 m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
932 m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd
LP
933
934 HASHMAP_FOREACH(l, m->links, i) {
935 link_add_rrs(l, true);
936 link_add_rrs(l, false);
937 }
938}
939
ec2c5e43
LP
940int manager_next_hostname(Manager *m) {
941 const char *p;
556a2294 942 uint64_t u, a;
78c6a153
LP
943 char *h, *k;
944 int r;
623a4c97
LP
945
946 assert(m);
947
78c6a153 948 p = strchr(m->llmnr_hostname, 0);
ec2c5e43
LP
949 assert(p);
950
78c6a153 951 while (p > m->llmnr_hostname) {
ec2c5e43
LP
952 if (!strchr("0123456789", p[-1]))
953 break;
954
955 p--;
956 }
957
958 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
959 u = 1;
960
556a2294
LP
961 /* Add a random number to the old value. This way we can avoid
962 * that two hosts pick the same hostname, win on IPv4 and lose
963 * on IPv6 (or vice versa), and pick the same hostname
964 * replacement hostname, ad infinitum. We still want the
965 * numbers to go up monotonically, hence we just add a random
966 * value 1..10 */
967
968 random_bytes(&a, sizeof(a));
969 u += 1 + a % 10;
ec2c5e43 970
78c6a153 971 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
ec2c5e43
LP
972 return -ENOMEM;
973
78c6a153
LP
974 r = dns_name_concat(h, "local", &k);
975 if (r < 0) {
976 free(h);
977 return r;
978 }
979
980 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
981
982 free(m->llmnr_hostname);
983 m->llmnr_hostname = h;
ec2c5e43 984
78c6a153
LP
985 free(m->mdns_hostname);
986 m->mdns_hostname = k;
ec2c5e43 987
eb60f9cd 988 manager_refresh_rrs(m);
623a4c97
LP
989
990 return 0;
991}
ec2c5e43 992
4e945a6f 993LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
994 Iterator i;
995 Link *l;
996
997 assert(m);
998
999 HASHMAP_FOREACH(l, m->links, i) {
1000 LinkAddress *a;
1001
1002 a = link_find_address(l, family, in_addr);
1003 if (a)
1004 return a;
1005 }
1006
1007 return NULL;
1008}
1009
a4076574 1010bool manager_our_packet(Manager *m, DnsPacket *p) {
ec2c5e43
LP
1011 assert(m);
1012 assert(p);
1013
4e945a6f 1014 return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e43 1015}
4e945a6f 1016
a4076574
LP
1017DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
1018 Link *l;
1019
1020 assert(m);
1021 assert(p);
1022
1023 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1024 if (!l)
1025 return NULL;
1026
1027 if (p->protocol == DNS_PROTOCOL_LLMNR) {
1028 if (p->family == AF_INET)
1029 return l->llmnr_ipv4_scope;
1030 else if (p->family == AF_INET6)
1031 return l->llmnr_ipv6_scope;
1032 }
1033
1034 return NULL;
1035}
1036
902bb5d8
LP
1037void manager_verify_all(Manager *m) {
1038 DnsScope *s;
1039
1040 assert(m);
1041
1042 LIST_FOREACH(scopes, s, m->dns_scopes)
1043 dns_zone_verify_all(&s->zone);
1044}
1045
78c6a153 1046int manager_is_own_hostname(Manager *m, const char *name) {
78c6a153
LP
1047 int r;
1048
1049 assert(m);
1050 assert(name);
1051
1052 if (m->llmnr_hostname) {
1053 r = dns_name_equal(name, m->llmnr_hostname);
1054 if (r != 0)
1055 return r;
1056 }
1057
1058 if (m->mdns_hostname)
1059 return dns_name_equal(name, m->mdns_hostname);
1060
1061 return 0;
1062}
1063
9176a57c
LP
1064int manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
1065 DnsServer *s;
1066 Iterator i;
1067 Link *l;
1068 int r;
1069
1070 assert(m);
1071 assert(dns);
1072
1073 r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
1074 if (r < 0)
1075 return r;
1076
1077 /* First add the system-wide servers and domains */
1078 LIST_FOREACH(servers, s, m->dns_servers) {
1079 r = ordered_set_put(*dns, s);
1080 if (r == -EEXIST)
1081 continue;
1082 if (r < 0)
1083 return r;
1084 }
1085
1086 /* Then, add the per-link servers */
1087 HASHMAP_FOREACH(l, m->links, i) {
1088 LIST_FOREACH(servers, s, l->dns_servers) {
1089 r = ordered_set_put(*dns, s);
1090 if (r == -EEXIST)
1091 continue;
1092 if (r < 0)
1093 return r;
1094 }
1095 }
1096
1097 /* If we found nothing, add the fallback servers */
1098 if (ordered_set_isempty(*dns)) {
1099 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1100 r = ordered_set_put(*dns, s);
1101 if (r == -EEXIST)
1102 continue;
1103 if (r < 0)
1104 return r;
1105 }
1106 }
1107
1108 return 0;
1109}
1110
1111int manager_compile_search_domains(Manager *m, OrderedSet **domains) {
1112 DnsSearchDomain *d;
1113 Iterator i;
1114 Link *l;
1115 int r;
1116
1117 assert(m);
1118 assert(domains);
1119
1120 r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops);
1121 if (r < 0)
1122 return r;
1123
1124 LIST_FOREACH(domains, d, m->search_domains) {
1125 r = ordered_set_put(*domains, d->name);
1126 if (r == -EEXIST)
1127 continue;
1128 if (r < 0)
1129 return r;
1130 }
1131
1132 HASHMAP_FOREACH(l, m->links, i) {
1133
1134 LIST_FOREACH(domains, d, l->search_domains) {
1135 r = ordered_set_put(*domains, d->name);
1136 if (r == -EEXIST)
1137 continue;
1138 if (r < 0)
1139 return r;
1140 }
1141 }
1142
1143 return 0;
1144}
1145
4e945a6f
LP
1146static const char* const support_table[_SUPPORT_MAX] = {
1147 [SUPPORT_NO] = "no",
1148 [SUPPORT_YES] = "yes",
1149 [SUPPORT_RESOLVE] = "resolve",
1150};
1151DEFINE_STRING_TABLE_LOOKUP(support, Support);