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