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