]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
resolved: make sure order of dns servers is stable
[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) {
1c4baffc
TG
196 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
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
78c6a153
LP
354 r = dns_label_escape(label, r, &n);
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
TG
480
481 r = sd_event_default(&m->event);
482 if (r < 0)
483 return r;
484
485 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
486 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
487
488 sd_event_set_watchdog(m->event, true);
489
eb60f9cd
LP
490 r = manager_watch_hostname(m);
491 if (r < 0)
492 return r;
493
1716f6dc 494 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
495 if (r < 0)
496 return r;
497
498 r = manager_network_monitor_listen(m);
499 if (r < 0)
500 return r;
501
502 r = manager_rtnl_listen(m);
503 if (r < 0)
504 return r;
505
506 r = manager_connect_bus(m);
507 if (r < 0)
508 return r;
509
4d506d6b
LP
510 (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
511
091a364c
TG
512 *ret = m;
513 m = NULL;
514
515 return 0;
516}
517
edc501d4
LP
518int manager_start(Manager *m) {
519 int r;
520
521 assert(m);
522
523 r = manager_llmnr_start(m);
524 if (r < 0)
525 return r;
526
527 return 0;
528}
529
74b2466e
LP
530Manager *manager_free(Manager *m) {
531 Link *l;
091a364c
TG
532
533 if (!m)
74b2466e
LP
534 return NULL;
535
0eac4623
LP
536 manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
537 manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
538
74b2466e
LP
539 while ((l = hashmap_first(m->links)))
540 link_free(l);
f0e15467
LP
541
542 while (m->dns_queries)
543 dns_query_free(m->dns_queries);
74b2466e 544
cab5b059
LP
545 dns_scope_free(m->unicast_scope);
546
f0e15467
LP
547 hashmap_free(m->links);
548 hashmap_free(m->dns_transactions);
549
096b6773
LP
550 sd_event_source_unref(m->network_event_source);
551 sd_network_monitor_unref(m->network_monitor);
091a364c 552
a564ca2f
LP
553 sd_netlink_unref(m->rtnl);
554 sd_event_source_unref(m->rtnl_event_source);
555
edc501d4 556 manager_llmnr_stop(m);
623a4c97 557
902bb5d8 558 sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e
LP
559 sd_event_source_unref(m->bus_retry_event_source);
560 sd_bus_unref(m->bus);
091a364c 561
4d506d6b
LP
562 sd_event_source_unref(m->sigusr1_event_source);
563
74b2466e 564 sd_event_unref(m->event);
623a4c97 565
78c6a153
LP
566 dns_resource_key_unref(m->llmnr_host_ipv4_key);
567 dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd 568
eb60f9cd 569 sd_event_source_unref(m->hostname_event_source);
d9fcf2ba 570 safe_close(m->hostname_fd);
78c6a153
LP
571 free(m->llmnr_hostname);
572 free(m->mdns_hostname);
eb60f9cd 573
091a364c 574 free(m);
74b2466e
LP
575
576 return NULL;
091a364c
TG
577}
578
1716f6dc 579int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 580 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
581 union {
582 struct cmsghdr header; /* For alignment */
40a1eebd 583 uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
1716f6dc 584 + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97 585 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dc
LP
586 } control;
587 union sockaddr_union sa;
74b2466e 588 struct msghdr mh = {};
1716f6dc 589 struct cmsghdr *cmsg;
74b2466e 590 struct iovec iov;
1716f6dc 591 int ms = 0, r;
74b2466e
LP
592 ssize_t l;
593
594 assert(m);
1716f6dc 595 assert(fd >= 0);
74b2466e
LP
596 assert(ret);
597
74b2466e
LP
598 r = ioctl(fd, FIONREAD, &ms);
599 if (r < 0)
600 return -errno;
601 if (ms < 0)
602 return -EIO;
603
1716f6dc 604 r = dns_packet_new(&p, protocol, ms);
74b2466e
LP
605 if (r < 0)
606 return r;
607
608 iov.iov_base = DNS_PACKET_DATA(p);
609 iov.iov_len = p->allocated;
610
1716f6dc
LP
611 mh.msg_name = &sa.sa;
612 mh.msg_namelen = sizeof(sa);
74b2466e
LP
613 mh.msg_iov = &iov;
614 mh.msg_iovlen = 1;
1716f6dc
LP
615 mh.msg_control = &control;
616 mh.msg_controllen = sizeof(control);
74b2466e 617
a38d9945 618 l = recvmsg(fd, &mh, 0);
74b2466e 619 if (l < 0) {
ad867662 620 if (errno == EAGAIN || errno == EINTR)
74b2466e
LP
621 return 0;
622
623 return -errno;
091a364c
TG
624 }
625
74b2466e
LP
626 if (l <= 0)
627 return -EIO;
091a364c 628
1716f6dc
LP
629 assert(!(mh.msg_flags & MSG_CTRUNC));
630 assert(!(mh.msg_flags & MSG_TRUNC));
631
74b2466e 632 p->size = (size_t) l;
091a364c 633
1716f6dc 634 p->family = sa.sa.sa_family;
623a4c97
LP
635 p->ipproto = IPPROTO_UDP;
636 if (p->family == AF_INET) {
1716f6dc 637 p->sender.in = sa.in.sin_addr;
623a4c97
LP
638 p->sender_port = be16toh(sa.in.sin_port);
639 } else if (p->family == AF_INET6) {
1716f6dc 640 p->sender.in6 = sa.in6.sin6_addr;
623a4c97
LP
641 p->sender_port = be16toh(sa.in6.sin6_port);
642 p->ifindex = sa.in6.sin6_scope_id;
643 } else
1716f6dc 644 return -EAFNOSUPPORT;
74b2466e 645
2a1288ff 646 CMSG_FOREACH(cmsg, &mh) {
74b2466e 647
1716f6dc
LP
648 if (cmsg->cmsg_level == IPPROTO_IPV6) {
649 assert(p->family == AF_INET6);
74b2466e 650
1716f6dc 651 switch (cmsg->cmsg_type) {
74b2466e 652
1716f6dc
LP
653 case IPV6_PKTINFO: {
654 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 655
623a4c97
LP
656 if (p->ifindex <= 0)
657 p->ifindex = i->ipi6_ifindex;
658
1716f6dc
LP
659 p->destination.in6 = i->ipi6_addr;
660 break;
661 }
74b2466e 662
1716f6dc
LP
663 case IPV6_HOPLIMIT:
664 p->ttl = *(int *) CMSG_DATA(cmsg);
665 break;
74b2466e 666
1716f6dc
LP
667 }
668 } else if (cmsg->cmsg_level == IPPROTO_IP) {
669 assert(p->family == AF_INET);
74b2466e 670
1716f6dc 671 switch (cmsg->cmsg_type) {
74b2466e 672
1716f6dc
LP
673 case IP_PKTINFO: {
674 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 675
623a4c97
LP
676 if (p->ifindex <= 0)
677 p->ifindex = i->ipi_ifindex;
678
1716f6dc
LP
679 p->destination.in = i->ipi_addr;
680 break;
681 }
74b2466e 682
623a4c97 683 case IP_TTL:
1716f6dc
LP
684 p->ttl = *(int *) CMSG_DATA(cmsg);
685 break;
686 }
687 }
688 }
74b2466e 689
623a4c97
LP
690 /* The Linux kernel sets the interface index to the loopback
691 * device if the packet came from the local host since it
692 * avoids the routing table in such a case. Let's unset the
693 * interface index in such a case. */
a5f03596 694 if (p->ifindex == LOOPBACK_IFINDEX)
623a4c97
LP
695 p->ifindex = 0;
696
86ad4cd7
TG
697 if (protocol != DNS_PROTOCOL_DNS) {
698 /* If we don't know the interface index still, we look for the
699 * first local interface with a matching address. Yuck! */
700 if (p->ifindex <= 0)
701 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
702 }
623a4c97 703
74b2466e
LP
704 *ret = p;
705 p = NULL;
706
707 return 1;
708}
709
74b2466e
LP
710static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
711 int r;
712
713 assert(fd >= 0);
714 assert(mh);
715
716 for (;;) {
717 if (sendmsg(fd, mh, flags) >= 0)
718 return 0;
719
720 if (errno == EINTR)
721 continue;
722
723 if (errno != EAGAIN)
724 return -errno;
725
726 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
727 if (r < 0)
728 return r;
729 if (r == 0)
730 return -ETIMEDOUT;
731 }
732}
733
72290734
TG
734static int write_loop(int fd, void *message, size_t length) {
735 int r;
736
737 assert(fd >= 0);
738 assert(message);
739
740 for (;;) {
741 if (write(fd, message, length) >= 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
758int manager_write(Manager *m, int fd, DnsPacket *p) {
759 int r;
760
761 log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
762
763 r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
764 if (r < 0)
765 return r;
766
767 return 0;
768}
769
623a4c97 770static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
771 union sockaddr_union sa = {
772 .in.sin_family = AF_INET,
74b2466e 773 };
1716f6dc
LP
774 union {
775 struct cmsghdr header; /* For alignment */
776 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
777 } control;
74b2466e
LP
778 struct msghdr mh = {};
779 struct iovec iov;
74b2466e
LP
780
781 assert(m);
1716f6dc
LP
782 assert(fd >= 0);
783 assert(addr);
784 assert(port > 0);
74b2466e
LP
785 assert(p);
786
74b2466e
LP
787 iov.iov_base = DNS_PACKET_DATA(p);
788 iov.iov_len = p->size;
091a364c 789
1716f6dc
LP
790 sa.in.sin_addr = *addr;
791 sa.in.sin_port = htobe16(port),
091a364c 792
74b2466e
LP
793 mh.msg_iov = &iov;
794 mh.msg_iovlen = 1;
795 mh.msg_name = &sa.sa;
796 mh.msg_namelen = sizeof(sa.in);
091a364c 797
74b2466e
LP
798 if (ifindex > 0) {
799 struct cmsghdr *cmsg;
800 struct in_pktinfo *pi;
801
802 zero(control);
803
1716f6dc 804 mh.msg_control = &control;
74b2466e
LP
805 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
806
807 cmsg = CMSG_FIRSTHDR(&mh);
808 cmsg->cmsg_len = mh.msg_controllen;
809 cmsg->cmsg_level = IPPROTO_IP;
810 cmsg->cmsg_type = IP_PKTINFO;
811
812 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
813 pi->ipi_ifindex = ifindex;
814 }
815
816 return sendmsg_loop(fd, &mh, 0);
817}
818
623a4c97 819static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
820 union sockaddr_union sa = {
821 .in6.sin6_family = AF_INET6,
74b2466e 822 };
1716f6dc
LP
823 union {
824 struct cmsghdr header; /* For alignment */
825 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
826 } control;
74b2466e
LP
827 struct msghdr mh = {};
828 struct iovec iov;
74b2466e
LP
829
830 assert(m);
1716f6dc
LP
831 assert(fd >= 0);
832 assert(addr);
833 assert(port > 0);
74b2466e
LP
834 assert(p);
835
74b2466e
LP
836 iov.iov_base = DNS_PACKET_DATA(p);
837 iov.iov_len = p->size;
838
1716f6dc
LP
839 sa.in6.sin6_addr = *addr;
840 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
841 sa.in6.sin6_scope_id = ifindex;
842
843 mh.msg_iov = &iov;
844 mh.msg_iovlen = 1;
845 mh.msg_name = &sa.sa;
846 mh.msg_namelen = sizeof(sa.in6);
847
848 if (ifindex > 0) {
849 struct cmsghdr *cmsg;
850 struct in6_pktinfo *pi;
851
852 zero(control);
853
1716f6dc 854 mh.msg_control = &control;
74b2466e
LP
855 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
856
857 cmsg = CMSG_FIRSTHDR(&mh);
858 cmsg->cmsg_len = mh.msg_controllen;
859 cmsg->cmsg_level = IPPROTO_IPV6;
860 cmsg->cmsg_type = IPV6_PKTINFO;
861
862 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
863 pi->ipi6_ifindex = ifindex;
864 }
865
866 return sendmsg_loop(fd, &mh, 0);
867}
868
623a4c97 869int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dc
LP
870 assert(m);
871 assert(fd >= 0);
872 assert(addr);
873 assert(port > 0);
874 assert(p);
875
a2a416f7
LP
876 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));
877
1716f6dc
LP
878 if (family == AF_INET)
879 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
880 else if (family == AF_INET6)
881 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
882
883 return -EAFNOSUPPORT;
884}
885
e1c95994
LP
886uint32_t manager_find_mtu(Manager *m) {
887 uint32_t mtu = 0;
888 Link *l;
889 Iterator i;
890
891 /* If we don't know on which link a DNS packet would be
892 * delivered, let's find the largest MTU that works on all
893 * interfaces we know of */
894
895 HASHMAP_FOREACH(l, m->links, i) {
896 if (l->mtu <= 0)
897 continue;
898
899 if (mtu <= 0 || l->mtu < mtu)
900 mtu = l->mtu;
901 }
902
903 return mtu;
904}
1716f6dc 905
623a4c97 906int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
907 LinkAddress *a;
908
909 assert(m);
910
4e945a6f 911 a = manager_find_link_address(m, family, in_addr);
ec2c5e43
LP
912 if (a)
913 return a->link->ifindex;
914
915 return 0;
916}
917
eb60f9cd
LP
918void manager_refresh_rrs(Manager *m) {
919 Iterator i;
920 Link *l;
921
922 assert(m);
923
78c6a153
LP
924 m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
925 m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd
LP
926
927 HASHMAP_FOREACH(l, m->links, i) {
928 link_add_rrs(l, true);
929 link_add_rrs(l, false);
930 }
931}
932
ec2c5e43
LP
933int manager_next_hostname(Manager *m) {
934 const char *p;
556a2294 935 uint64_t u, a;
78c6a153
LP
936 char *h, *k;
937 int r;
623a4c97
LP
938
939 assert(m);
940
78c6a153 941 p = strchr(m->llmnr_hostname, 0);
ec2c5e43
LP
942 assert(p);
943
78c6a153 944 while (p > m->llmnr_hostname) {
ec2c5e43
LP
945 if (!strchr("0123456789", p[-1]))
946 break;
947
948 p--;
949 }
950
951 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
952 u = 1;
953
556a2294
LP
954 /* Add a random number to the old value. This way we can avoid
955 * that two hosts pick the same hostname, win on IPv4 and lose
956 * on IPv6 (or vice versa), and pick the same hostname
957 * replacement hostname, ad infinitum. We still want the
958 * numbers to go up monotonically, hence we just add a random
959 * value 1..10 */
960
961 random_bytes(&a, sizeof(a));
962 u += 1 + a % 10;
ec2c5e43 963
78c6a153 964 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
ec2c5e43
LP
965 return -ENOMEM;
966
78c6a153
LP
967 r = dns_name_concat(h, "local", &k);
968 if (r < 0) {
969 free(h);
970 return r;
971 }
972
973 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
974
975 free(m->llmnr_hostname);
976 m->llmnr_hostname = h;
ec2c5e43 977
78c6a153
LP
978 free(m->mdns_hostname);
979 m->mdns_hostname = k;
ec2c5e43 980
eb60f9cd 981 manager_refresh_rrs(m);
623a4c97
LP
982
983 return 0;
984}
ec2c5e43 985
4e945a6f 986LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
987 Iterator i;
988 Link *l;
989
990 assert(m);
991
992 HASHMAP_FOREACH(l, m->links, i) {
993 LinkAddress *a;
994
995 a = link_find_address(l, family, in_addr);
996 if (a)
997 return a;
998 }
999
1000 return NULL;
1001}
1002
a4076574 1003bool manager_our_packet(Manager *m, DnsPacket *p) {
ec2c5e43
LP
1004 assert(m);
1005 assert(p);
1006
4e945a6f 1007 return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e43 1008}
4e945a6f 1009
a4076574
LP
1010DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
1011 Link *l;
1012
1013 assert(m);
1014 assert(p);
1015
1016 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1017 if (!l)
1018 return NULL;
1019
1020 if (p->protocol == DNS_PROTOCOL_LLMNR) {
1021 if (p->family == AF_INET)
1022 return l->llmnr_ipv4_scope;
1023 else if (p->family == AF_INET6)
1024 return l->llmnr_ipv6_scope;
1025 }
1026
1027 return NULL;
1028}
1029
902bb5d8
LP
1030void manager_verify_all(Manager *m) {
1031 DnsScope *s;
1032
1033 assert(m);
1034
1035 LIST_FOREACH(scopes, s, m->dns_scopes)
1036 dns_zone_verify_all(&s->zone);
1037}
1038
78c6a153 1039int manager_is_own_hostname(Manager *m, const char *name) {
78c6a153
LP
1040 int r;
1041
1042 assert(m);
1043 assert(name);
1044
1045 if (m->llmnr_hostname) {
1046 r = dns_name_equal(name, m->llmnr_hostname);
1047 if (r != 0)
1048 return r;
1049 }
1050
1051 if (m->mdns_hostname)
1052 return dns_name_equal(name, m->mdns_hostname);
1053
1054 return 0;
1055}
1056
4e945a6f
LP
1057static const char* const support_table[_SUPPORT_MAX] = {
1058 [SUPPORT_NO] = "no",
1059 [SUPPORT_YES] = "yes",
1060 [SUPPORT_RESOLVE] = "resolve",
1061};
1062DEFINE_STRING_TABLE_LOOKUP(support, Support);