]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-manager.c
resolved: properly check return value of dns_resource_record_equal()
[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
22#include <arpa/inet.h>
23#include <resolv.h>
1716f6dc 24#include <net/if.h>
74b2466e
LP
25#include <sys/ioctl.h>
26#include <sys/poll.h>
27#include <netinet/in.h>
091a364c 28
74b2466e 29#include "rtnl-util.h"
091a364c
TG
30#include "event-util.h"
31#include "network-util.h"
091a364c
TG
32#include "network-internal.h"
33#include "conf-parser.h"
74b2466e 34#include "socket-util.h"
a2a416f7 35#include "af-list.h"
eb60f9cd 36#include "utf8.h"
4e945a6f 37
eb60f9cd 38#include "resolved-dns-domain.h"
39d8db04
LP
39#include "resolved-conf.h"
40#include "resolved-bus.h"
41#include "resolved-manager.h"
74b2466e
LP
42
43#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
44
45static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
46 Manager *m = userdata;
47 uint16_t type;
48 Link *l;
49 int ifindex, r;
50
51 assert(rtnl);
52 assert(m);
53 assert(mm);
54
55 r = sd_rtnl_message_get_type(mm, &type);
56 if (r < 0)
57 goto fail;
58
59 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
60 if (r < 0)
61 goto fail;
62
63 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
64
65 switch (type) {
66
a2a416f7
LP
67 case RTM_NEWLINK:{
68 bool is_new = !l;
74b2466e 69
a2a416f7 70 if (!l) {
74b2466e
LP
71 r = link_new(m, &l, ifindex);
72 if (r < 0)
73 goto fail;
74 }
75
76 r = link_update_rtnl(l, mm);
77 if (r < 0)
78 goto fail;
79
21d73c87
LP
80 r = link_update_monitor(l);
81 if (r < 0)
82 goto fail;
83
a2a416f7
LP
84 if (is_new)
85 log_debug("Found new link %i/%s", ifindex, l->name);
86
74b2466e 87 break;
a2a416f7 88 }
74b2466e
LP
89
90 case RTM_DELLINK:
91 if (l) {
a2a416f7 92 log_debug("Removing link %i/%s", l->ifindex, l->name);
74b2466e
LP
93 link_free(l);
94 }
95
96 break;
97 }
98
99 return 0;
100
101fail:
102 log_warning("Failed to process RTNL link message: %s", strerror(-r));
103 return 0;
104}
105
106static int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
107 Manager *m = userdata;
108 union in_addr_union address;
74b2466e 109 uint16_t type;
0dd25fb9 110 int r, ifindex, family;
74b2466e
LP
111 LinkAddress *a;
112 Link *l;
113
114 assert(rtnl);
115 assert(mm);
116 assert(m);
117
118 r = sd_rtnl_message_get_type(mm, &type);
119 if (r < 0)
120 goto fail;
121
122 r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
123 if (r < 0)
124 goto fail;
125
126 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
127 if (!l)
128 return 0;
129
130 r = sd_rtnl_message_addr_get_family(mm, &family);
131 if (r < 0)
132 goto fail;
133
134 switch (family) {
135
136 case AF_INET:
137 r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
138 if (r < 0) {
139 r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
140 if (r < 0)
141 goto fail;
142 }
143
144 break;
145
146 case AF_INET6:
147 r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
148 if (r < 0) {
149 r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
150 if (r < 0)
151 goto fail;
152 }
153
154 break;
155
156 default:
157 return 0;
158 }
159
160 a = link_find_address(l, family, &address);
161
162 switch (type) {
163
164 case RTM_NEWADDR:
165
166 if (!a) {
167 r = link_address_new(l, &a, family, &address);
168 if (r < 0)
169 return r;
170 }
171
172 r = link_address_update_rtnl(a, mm);
173 if (r < 0)
174 return r;
175
176 break;
177
178 case RTM_DELADDR:
179 if (a)
180 link_address_free(a);
181 break;
182 }
183
184 return 0;
185
186fail:
187 log_warning("Failed to process RTNL address message: %s", strerror(-r));
188 return 0;
189}
190
74b2466e
LP
191static int manager_rtnl_listen(Manager *m) {
192 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
193 sd_rtnl_message *i;
194 int r;
195
196 assert(m);
197
198 /* First, subscibe to interfaces coming and going */
199 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
200 if (r < 0)
201 return r;
202
203 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
204 if (r < 0)
205 return r;
206
207 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
208 if (r < 0)
209 return r;
210
211 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
212 if (r < 0)
213 return r;
214
215 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
216 if (r < 0)
217 return r;
091a364c 218
74b2466e
LP
219 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
220 if (r < 0)
221 return r;
222
223 /* Then, enumerate all links */
224 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
225 if (r < 0)
226 return r;
227
228 r = sd_rtnl_message_request_dump(req, true);
229 if (r < 0)
230 return r;
231
232 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
233 if (r < 0)
234 return r;
235
236 for (i = reply; i; i = sd_rtnl_message_next(i)) {
237 r = manager_process_link(m->rtnl, i, m);
238 if (r < 0)
239 return r;
240 }
241
242 req = sd_rtnl_message_unref(req);
243 reply = sd_rtnl_message_unref(reply);
244
245 /* Finally, enumerate all addresses, too */
246 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
247 if (r < 0)
248 return r;
249
250 r = sd_rtnl_message_request_dump(req, true);
251 if (r < 0)
252 return r;
253
254 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
255 if (r < 0)
256 return r;
257
258 for (i = reply; i; i = sd_rtnl_message_next(i)) {
259 r = manager_process_address(m->rtnl, i, m);
260 if (r < 0)
261 return r;
262 }
263
264 return r;
265}
266
267static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
268 Manager *m = userdata;
269 Iterator i;
270 Link *l;
271 int r;
272
273 assert(m);
274
275 sd_network_monitor_flush(m->network_monitor);
276
277 HASHMAP_FOREACH(l, m->links, i) {
278 r = link_update_monitor(l);
279 if (r < 0)
280 log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
281 }
282
283 r = manager_write_resolv_conf(m);
284 if (r < 0)
285 log_warning("Could not update resolv.conf: %s", strerror(-r));
286
287 return 0;
288}
289
290static int manager_network_monitor_listen(Manager *m) {
291 int r, fd, events;
292
293 assert(m);
294
0014a4ad 295 r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e
LP
296 if (r < 0)
297 return r;
298
299 fd = sd_network_monitor_get_fd(m->network_monitor);
300 if (fd < 0)
301 return fd;
302
303 events = sd_network_monitor_get_events(m->network_monitor);
304 if (events < 0)
305 return events;
306
307 r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
308 if (r < 0)
309 return r;
310
311 return 0;
312}
313
eb60f9cd
LP
314static int determine_hostname(char **ret) {
315 _cleanup_free_ char *h = NULL, *n = NULL;
316 int r;
317
318 assert(ret);
319
320 h = gethostname_malloc();
321 if (!h)
322 return log_oom();
323
324 if (!utf8_is_valid(h)) {
325 log_error("System hostname is not UTF-8 clean.");
326 return -EINVAL;
327 }
328
329 r = dns_name_normalize(h, &n);
330 if (r < 0) {
331 log_error("System hostname '%s' cannot be normalized.", h);
332 return r;
333 }
334
335 *ret = n;
336 n = NULL;
337
338 return 0;
339}
340
341static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
342 _cleanup_free_ char *h = NULL;
343 Manager *m = userdata;
344 int r;
345
346 assert(m);
347
348 r = determine_hostname(&h);
349 if (r < 0)
350 return 0; /* ignore invalid hostnames */
351
352 if (streq(h, m->hostname))
353 return 0;
354
355 log_info("System hostname changed to '%s'.", h);
356 free(m->hostname);
357 m->hostname = h;
358 h = NULL;
359
360 manager_refresh_rrs(m);
361
362 return 0;
363}
364
365static int manager_watch_hostname(Manager *m) {
eb60f9cd
LP
366 int r;
367
368 assert(m);
369
370 m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
371 if (m->hostname_fd < 0) {
372 log_warning("Failed to watch hostname: %m");
373 return 0;
374 }
375
376 r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
377 if (r < 0) {
378 if (r == -EPERM)
379 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
380 m->hostname_fd = safe_close(m->hostname_fd);
381 else {
382 log_error("Failed to add hostname event source: %s", strerror(-r));
383 return r;
384 }
385 }
386
387 r = determine_hostname(&m->hostname);
388 if (r < 0) {
389 log_info("Defaulting to hostname 'linux'.");
390 m->hostname = strdup("linux");
391 if (!m->hostname)
392 return log_oom();
393 } else
394 log_info("Using system hostname '%s'.", m->hostname);
395
396 return 0;
397}
398
edc501d4
LP
399static void manager_llmnr_stop(Manager *m) {
400 assert(m);
401
402 m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
403 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
404
405 m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
406 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
407
408 m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
409 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
410
411 m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
412 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
413}
414
415static int manager_llmnr_start(Manager *m) {
416 int r;
417
418 assert(m);
419
420 if (m->llmnr_support == SUPPORT_NO)
421 return 0;
422
423 r = manager_llmnr_ipv4_udp_fd(m);
424 if (r == -EADDRINUSE)
425 goto eaddrinuse;
426 if (r < 0)
427 return r;
428
429 r = manager_llmnr_ipv6_udp_fd(m);
430 if (r == -EADDRINUSE)
431 goto eaddrinuse;
432 if (r < 0)
433 return r;
434
435 r = manager_llmnr_ipv4_tcp_fd(m);
436 if (r == -EADDRINUSE)
437 goto eaddrinuse;
438 if (r < 0)
439 return r;
440
441 r = manager_llmnr_ipv6_tcp_fd(m);
442 if (r == -EADDRINUSE)
443 goto eaddrinuse;
444 if (r < 0)
445 return r;
446
447 return 0;
448
449eaddrinuse:
450 log_warning("There appears to be another LLMNR respondering running. Turning off LLMNR support.");
451 m->llmnr_support = SUPPORT_NO;
452 manager_llmnr_stop(m);
453 return 0;
454}
455
091a364c 456int manager_new(Manager **ret) {
74b2466e 457 _cleanup_(manager_freep) Manager *m = NULL;
091a364c
TG
458 int r;
459
c92e531c
LP
460 assert(ret);
461
091a364c
TG
462 m = new0(Manager, 1);
463 if (!m)
464 return -ENOMEM;
465
74b2466e 466 m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
1716f6dc 467 m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97 468 m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
eb60f9cd 469 m->hostname_fd = -1;
1716f6dc 470
4e945a6f 471 m->llmnr_support = SUPPORT_YES;
5cb36f41 472 m->read_resolv_conf = true;
091a364c 473
4e945a6f 474 r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
091a364c
TG
475 if (r < 0)
476 return r;
477
478 r = sd_event_default(&m->event);
479 if (r < 0)
480 return r;
481
482 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
483 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
484
485 sd_event_set_watchdog(m->event, true);
486
eb60f9cd
LP
487 r = manager_watch_hostname(m);
488 if (r < 0)
489 return r;
490
1716f6dc 491 r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e
LP
492 if (r < 0)
493 return r;
494
495 r = manager_network_monitor_listen(m);
496 if (r < 0)
497 return r;
498
499 r = manager_rtnl_listen(m);
500 if (r < 0)
501 return r;
502
503 r = manager_connect_bus(m);
504 if (r < 0)
505 return r;
506
091a364c
TG
507 *ret = m;
508 m = NULL;
509
510 return 0;
511}
512
edc501d4
LP
513int manager_start(Manager *m) {
514 int r;
515
516 assert(m);
517
518 r = manager_llmnr_start(m);
519 if (r < 0)
520 return r;
521
522 return 0;
523}
524
74b2466e
LP
525Manager *manager_free(Manager *m) {
526 Link *l;
091a364c
TG
527
528 if (!m)
74b2466e
LP
529 return NULL;
530
74b2466e
LP
531 while ((l = hashmap_first(m->links)))
532 link_free(l);
f0e15467
LP
533
534 while (m->dns_queries)
535 dns_query_free(m->dns_queries);
74b2466e
LP
536
537 dns_scope_free(m->unicast_scope);
538
539 while (m->dns_servers)
540 dns_server_free(m->dns_servers);
4e945a6f
LP
541 while (m->fallback_dns_servers)
542 dns_server_free(m->fallback_dns_servers);
091a364c 543
f0e15467
LP
544 hashmap_free(m->links);
545 hashmap_free(m->dns_transactions);
546
096b6773
LP
547 sd_event_source_unref(m->network_event_source);
548 sd_network_monitor_unref(m->network_monitor);
091a364c 549
74b2466e
LP
550 sd_event_source_unref(m->dns_ipv4_event_source);
551 sd_event_source_unref(m->dns_ipv6_event_source);
74b2466e
LP
552 safe_close(m->dns_ipv4_fd);
553 safe_close(m->dns_ipv6_fd);
554
edc501d4 555 manager_llmnr_stop(m);
623a4c97 556
74b2466e
LP
557 sd_event_source_unref(m->bus_retry_event_source);
558 sd_bus_unref(m->bus);
091a364c 559
74b2466e 560 sd_event_unref(m->event);
623a4c97
LP
561
562 dns_resource_key_unref(m->host_ipv4_key);
563 dns_resource_key_unref(m->host_ipv6_key);
eb60f9cd
LP
564
565 safe_close(m->hostname_fd);
566 sd_event_source_unref(m->hostname_event_source);
623a4c97 567 free(m->hostname);
eb60f9cd 568
091a364c 569 free(m);
74b2466e
LP
570
571 return NULL;
091a364c
TG
572}
573
5cb36f41
LP
574int manager_read_resolv_conf(Manager *m) {
575 _cleanup_fclose_ FILE *f = NULL;
576 struct stat st, own;
577 char line[LINE_MAX];
578 DnsServer *s, *nx;
579 usec_t t;
580 int r;
581
582 assert(m);
583
584 /* Reads the system /etc/resolv.conf, if it exists and is not
585 * symlinked to our own resolv.conf instance */
586
587 if (!m->read_resolv_conf)
588 return 0;
589
590 r = stat("/etc/resolv.conf", &st);
591 if (r < 0) {
592 if (errno != ENOENT)
593 log_warning("Failed to open /etc/resolv.conf: %m");
594 r = -errno;
595 goto clear;
596 }
597
598 /* Have we already seen the file? */
599 t = timespec_load(&st.st_mtim);
600 if (t == m->resolv_conf_mtime)
601 return 0;
602
603 m->resolv_conf_mtime = t;
604
605 /* Is it symlinked to our own file? */
606 if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
607 st.st_dev == own.st_dev &&
608 st.st_ino == own.st_ino) {
609 r = 0;
610 goto clear;
611 }
612
613 f = fopen("/etc/resolv.conf", "re");
614 if (!f) {
615 if (errno != ENOENT)
616 log_warning("Failed to open /etc/resolv.conf: %m");
617 r = -errno;
618 goto clear;
619 }
620
621 if (fstat(fileno(f), &st) < 0) {
622 log_error("Failed to stat open file: %m");
623 r = -errno;
624 goto clear;
625 }
626
627 LIST_FOREACH(servers, s, m->dns_servers)
628 s->marked = true;
629
630 FOREACH_LINE(line, f, r = -errno; goto clear) {
631 union in_addr_union address;
632 int family;
633 char *l;
634 const char *a;
635
636 truncate_nl(line);
637
638 l = strstrip(line);
639 if (*l == '#' || *l == ';')
640 continue;
641
642 a = first_word(l, "nameserver");
643 if (!a)
644 continue;
645
646 r = in_addr_from_string_auto(a, &family, &address);
647 if (r < 0) {
648 log_warning("Failed to parse name server %s.", a);
649 continue;
650 }
651
652 LIST_FOREACH(servers, s, m->dns_servers)
653 if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
654 break;
655
656 if (s)
657 s->marked = false;
658 else {
659 r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
660 if (r < 0)
661 goto clear;
662 }
663 }
664
665 LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
666 if (s->marked)
667 dns_server_free(s);
668
669 return 0;
670
671clear:
672 while (m->dns_servers)
673 dns_server_free(m->dns_servers);
674
675 return r;
676}
677
74b2466e
LP
678static void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
679 _cleanup_free_ char *t = NULL;
680 int r;
091a364c 681
74b2466e 682 assert(s);
091a364c 683 assert(f);
091a364c
TG
684 assert(count);
685
74b2466e 686 r = in_addr_to_string(s->family, &s->address, &t);
4e945a6f
LP
687 if (r < 0) {
688 log_warning("Invalid DNS address. Ignoring: %s", strerror(-r));
091a364c
TG
689 return;
690 }
691
692 if (*count == MAXNS)
74b2466e 693 fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
091a364c 694
74b2466e 695 fprintf(f, "nameserver %s\n", t);
091a364c
TG
696 (*count) ++;
697}
698
74b2466e 699int manager_write_resolv_conf(Manager *m) {
4e945a6f 700 static const char path[] = "/run/systemd/resolve/resolv.conf";
091a364c
TG
701 _cleanup_free_ char *temp_path = NULL;
702 _cleanup_fclose_ FILE *f = NULL;
091a364c 703 unsigned count = 0;
74b2466e
LP
704 DnsServer *s;
705 Iterator i;
706 Link *l;
707 int r;
091a364c
TG
708
709 assert(m);
710
5cb36f41
LP
711 /* Read the system /etc/resolv.conf first */
712 manager_read_resolv_conf(m);
713
b686acb2 714 r = fopen_temporary(path, &f, &temp_path);
091a364c
TG
715 if (r < 0)
716 return r;
717
718 fchmod(fileno(f), 0644);
719
720 fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
721 "# Third party programs must not access this file directly, but\n"
722 "# only through the symlink at /etc/resolv.conf. To manage\n"
723 "# resolv.conf(5) in a different way, replace the symlink by a\n"
724 "# static file or a different symlink.\n\n", f);
725
4e945a6f
LP
726 LIST_FOREACH(servers, s, m->dns_servers)
727 write_resolve_conf_server(s, f, &count);
728
6073b6f2
TG
729 HASHMAP_FOREACH(l, m->links, i)
730 LIST_FOREACH(servers, s, l->dns_servers)
74b2466e 731 write_resolve_conf_server(s, f, &count);
091a364c 732
4e945a6f
LP
733 if (count == 0) {
734 LIST_FOREACH(servers, s, m->fallback_dns_servers)
735 write_resolve_conf_server(s, f, &count);
736 }
091a364c 737
74b2466e
LP
738 r = fflush_and_check(f);
739 if (r < 0)
740 goto fail;
741
742 if (rename(temp_path, path) < 0) {
743 r = -errno;
744 goto fail;
745 }
091a364c 746
74b2466e 747 return 0;
091a364c 748
74b2466e
LP
749fail:
750 unlink(path);
751 unlink(temp_path);
752 return r;
753}
091a364c 754
1716f6dc 755int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e 756 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dc
LP
757 union {
758 struct cmsghdr header; /* For alignment */
759 uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
760 + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97 761 + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dc
LP
762 } control;
763 union sockaddr_union sa;
74b2466e 764 struct msghdr mh = {};
1716f6dc 765 struct cmsghdr *cmsg;
74b2466e 766 struct iovec iov;
1716f6dc 767 int ms = 0, r;
74b2466e
LP
768 ssize_t l;
769
770 assert(m);
1716f6dc 771 assert(fd >= 0);
74b2466e
LP
772 assert(ret);
773
74b2466e
LP
774 r = ioctl(fd, FIONREAD, &ms);
775 if (r < 0)
776 return -errno;
777 if (ms < 0)
778 return -EIO;
779
1716f6dc 780 r = dns_packet_new(&p, protocol, ms);
74b2466e
LP
781 if (r < 0)
782 return r;
783
784 iov.iov_base = DNS_PACKET_DATA(p);
785 iov.iov_len = p->allocated;
786
1716f6dc
LP
787 mh.msg_name = &sa.sa;
788 mh.msg_namelen = sizeof(sa);
74b2466e
LP
789 mh.msg_iov = &iov;
790 mh.msg_iovlen = 1;
1716f6dc
LP
791 mh.msg_control = &control;
792 mh.msg_controllen = sizeof(control);
74b2466e
LP
793
794 l = recvmsg(fd, &mh, 0);
795 if (l < 0) {
ad867662 796 if (errno == EAGAIN || errno == EINTR)
74b2466e
LP
797 return 0;
798
799 return -errno;
091a364c
TG
800 }
801
74b2466e
LP
802 if (l <= 0)
803 return -EIO;
091a364c 804
1716f6dc
LP
805 assert(!(mh.msg_flags & MSG_CTRUNC));
806 assert(!(mh.msg_flags & MSG_TRUNC));
807
74b2466e 808 p->size = (size_t) l;
091a364c 809
1716f6dc 810 p->family = sa.sa.sa_family;
623a4c97
LP
811 p->ipproto = IPPROTO_UDP;
812 if (p->family == AF_INET) {
1716f6dc 813 p->sender.in = sa.in.sin_addr;
623a4c97
LP
814 p->sender_port = be16toh(sa.in.sin_port);
815 } else if (p->family == AF_INET6) {
1716f6dc 816 p->sender.in6 = sa.in6.sin6_addr;
623a4c97
LP
817 p->sender_port = be16toh(sa.in6.sin6_port);
818 p->ifindex = sa.in6.sin6_scope_id;
819 } else
1716f6dc 820 return -EAFNOSUPPORT;
74b2466e 821
1716f6dc 822 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
74b2466e 823
1716f6dc
LP
824 if (cmsg->cmsg_level == IPPROTO_IPV6) {
825 assert(p->family == AF_INET6);
74b2466e 826
1716f6dc 827 switch (cmsg->cmsg_type) {
74b2466e 828
1716f6dc
LP
829 case IPV6_PKTINFO: {
830 struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e 831
623a4c97
LP
832 if (p->ifindex <= 0)
833 p->ifindex = i->ipi6_ifindex;
834
1716f6dc
LP
835 p->destination.in6 = i->ipi6_addr;
836 break;
837 }
74b2466e 838
1716f6dc
LP
839 case IPV6_HOPLIMIT:
840 p->ttl = *(int *) CMSG_DATA(cmsg);
841 break;
74b2466e 842
1716f6dc
LP
843 }
844 } else if (cmsg->cmsg_level == IPPROTO_IP) {
845 assert(p->family == AF_INET);
74b2466e 846
1716f6dc 847 switch (cmsg->cmsg_type) {
74b2466e 848
1716f6dc
LP
849 case IP_PKTINFO: {
850 struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c 851
623a4c97
LP
852 if (p->ifindex <= 0)
853 p->ifindex = i->ipi_ifindex;
854
1716f6dc
LP
855 p->destination.in = i->ipi_addr;
856 break;
857 }
74b2466e 858
623a4c97 859 case IP_TTL:
1716f6dc
LP
860 p->ttl = *(int *) CMSG_DATA(cmsg);
861 break;
862 }
863 }
864 }
74b2466e 865
623a4c97
LP
866 /* The Linux kernel sets the interface index to the loopback
867 * device if the packet came from the local host since it
868 * avoids the routing table in such a case. Let's unset the
869 * interface index in such a case. */
870 if (p->ifindex > 0 && manager_ifindex_is_loopback(m, p->ifindex) != 0)
871 p->ifindex = 0;
872
873 /* If we don't know the interface index still, we look for the
874 * first local interface with a matching address. Yuck! */
875 if (p->ifindex <= 0)
876 p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
877
74b2466e
LP
878 *ret = p;
879 p = NULL;
880
881 return 1;
882}
883
1716f6dc 884static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e 885 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ec2c5e43 886 DnsTransaction *t = NULL;
74b2466e
LP
887 Manager *m = userdata;
888 int r;
889
1716f6dc 890 r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
74b2466e
LP
891 if (r <= 0)
892 return r;
893
623a4c97 894 if (dns_packet_validate_reply(p) > 0) {
ec2c5e43 895 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
1716f6dc
LP
896 if (!t)
897 return 0;
74b2466e 898
ec2c5e43 899 dns_transaction_process_reply(t, p);
623a4c97 900
1716f6dc 901 } else
623a4c97 902 log_debug("Invalid DNS packet.");
74b2466e 903
ad867662 904 return 0;
74b2466e
LP
905}
906
907int manager_dns_ipv4_fd(Manager *m) {
1716f6dc 908 const int one = 1;
74b2466e
LP
909 int r;
910
091a364c
TG
911 assert(m);
912
74b2466e
LP
913 if (m->dns_ipv4_fd >= 0)
914 return m->dns_ipv4_fd;
091a364c 915
74b2466e
LP
916 m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
917 if (m->dns_ipv4_fd < 0)
918 return -errno;
091a364c 919
1716f6dc
LP
920 r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
921 if (r < 0) {
922 r = -errno;
923 goto fail;
924 }
925
926 r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
74b2466e 927 if (r < 0)
1716f6dc 928 goto fail;
74b2466e
LP
929
930 return m->dns_ipv4_fd;
1716f6dc
LP
931
932fail:
933 m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
934 return r;
091a364c
TG
935}
936
74b2466e 937int manager_dns_ipv6_fd(Manager *m) {
1716f6dc 938 const int one = 1;
74b2466e
LP
939 int r;
940
941 assert(m);
091a364c 942
74b2466e
LP
943 if (m->dns_ipv6_fd >= 0)
944 return m->dns_ipv6_fd;
945
946 m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
947 if (m->dns_ipv6_fd < 0)
948 return -errno;
949
1716f6dc
LP
950 r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
951 if (r < 0) {
952 r = -errno;
953 goto fail;
954 }
955
956 r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
091a364c 957 if (r < 0)
1716f6dc 958 goto fail;
091a364c 959
74b2466e 960 return m->dns_ipv6_fd;
1716f6dc
LP
961
962fail:
963 m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
964 return r;
74b2466e
LP
965}
966
967static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
968 int r;
969
970 assert(fd >= 0);
971 assert(mh);
972
973 for (;;) {
974 if (sendmsg(fd, mh, flags) >= 0)
975 return 0;
976
977 if (errno == EINTR)
978 continue;
979
980 if (errno != EAGAIN)
981 return -errno;
982
983 r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
984 if (r < 0)
985 return r;
986 if (r == 0)
987 return -ETIMEDOUT;
988 }
989}
990
623a4c97 991static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
992 union sockaddr_union sa = {
993 .in.sin_family = AF_INET,
74b2466e 994 };
1716f6dc
LP
995 union {
996 struct cmsghdr header; /* For alignment */
997 uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
998 } control;
74b2466e
LP
999 struct msghdr mh = {};
1000 struct iovec iov;
74b2466e
LP
1001
1002 assert(m);
1716f6dc
LP
1003 assert(fd >= 0);
1004 assert(addr);
1005 assert(port > 0);
74b2466e
LP
1006 assert(p);
1007
74b2466e
LP
1008 iov.iov_base = DNS_PACKET_DATA(p);
1009 iov.iov_len = p->size;
091a364c 1010
1716f6dc
LP
1011 sa.in.sin_addr = *addr;
1012 sa.in.sin_port = htobe16(port),
091a364c 1013
74b2466e
LP
1014 mh.msg_iov = &iov;
1015 mh.msg_iovlen = 1;
1016 mh.msg_name = &sa.sa;
1017 mh.msg_namelen = sizeof(sa.in);
091a364c 1018
74b2466e
LP
1019 if (ifindex > 0) {
1020 struct cmsghdr *cmsg;
1021 struct in_pktinfo *pi;
1022
1023 zero(control);
1024
1716f6dc 1025 mh.msg_control = &control;
74b2466e
LP
1026 mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
1027
1028 cmsg = CMSG_FIRSTHDR(&mh);
1029 cmsg->cmsg_len = mh.msg_controllen;
1030 cmsg->cmsg_level = IPPROTO_IP;
1031 cmsg->cmsg_type = IP_PKTINFO;
1032
1033 pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
1034 pi->ipi_ifindex = ifindex;
1035 }
1036
1037 return sendmsg_loop(fd, &mh, 0);
1038}
1039
623a4c97 1040static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e
LP
1041 union sockaddr_union sa = {
1042 .in6.sin6_family = AF_INET6,
74b2466e 1043 };
1716f6dc
LP
1044 union {
1045 struct cmsghdr header; /* For alignment */
1046 uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1047 } control;
74b2466e
LP
1048 struct msghdr mh = {};
1049 struct iovec iov;
74b2466e
LP
1050
1051 assert(m);
1716f6dc
LP
1052 assert(fd >= 0);
1053 assert(addr);
1054 assert(port > 0);
74b2466e
LP
1055 assert(p);
1056
74b2466e
LP
1057 iov.iov_base = DNS_PACKET_DATA(p);
1058 iov.iov_len = p->size;
1059
1716f6dc
LP
1060 sa.in6.sin6_addr = *addr;
1061 sa.in6.sin6_port = htobe16(port),
74b2466e
LP
1062 sa.in6.sin6_scope_id = ifindex;
1063
1064 mh.msg_iov = &iov;
1065 mh.msg_iovlen = 1;
1066 mh.msg_name = &sa.sa;
1067 mh.msg_namelen = sizeof(sa.in6);
1068
1069 if (ifindex > 0) {
1070 struct cmsghdr *cmsg;
1071 struct in6_pktinfo *pi;
1072
1073 zero(control);
1074
1716f6dc 1075 mh.msg_control = &control;
74b2466e
LP
1076 mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
1077
1078 cmsg = CMSG_FIRSTHDR(&mh);
1079 cmsg->cmsg_len = mh.msg_controllen;
1080 cmsg->cmsg_level = IPPROTO_IPV6;
1081 cmsg->cmsg_type = IPV6_PKTINFO;
1082
1083 pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
1084 pi->ipi6_ifindex = ifindex;
1085 }
1086
1087 return sendmsg_loop(fd, &mh, 0);
1088}
1089
623a4c97 1090int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dc
LP
1091 assert(m);
1092 assert(fd >= 0);
1093 assert(addr);
1094 assert(port > 0);
1095 assert(p);
1096
a2a416f7
LP
1097 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));
1098
1716f6dc
LP
1099 if (family == AF_INET)
1100 return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1101 else if (family == AF_INET6)
1102 return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
1103
1104 return -EAFNOSUPPORT;
1105}
1106
2c27fbca 1107DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
74b2466e
LP
1108 DnsServer *s;
1109
1110 assert(m);
1111 assert(in_addr);
1112
4e945a6f 1113 LIST_FOREACH(servers, s, m->dns_servers)
5cb36f41 1114 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca 1115 return s;
74b2466e 1116
4e945a6f 1117 LIST_FOREACH(servers, s, m->fallback_dns_servers)
5cb36f41 1118 if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca 1119 return s;
74b2466e 1120
2c27fbca 1121 return NULL;
4e945a6f
LP
1122}
1123
2c27fbca 1124DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
4e945a6f
LP
1125 assert(m);
1126
1127 if (m->current_dns_server == s)
1128 return s;
1129
1130 if (s) {
1131 _cleanup_free_ char *ip = NULL;
1132
1133 in_addr_to_string(s->family, &s->address, &ip);
1134 log_info("Switching to system DNS server %s.", strna(ip));
2c27fbca 1135 }
4e945a6f
LP
1136
1137 m->current_dns_server = s;
2c27fbca
LP
1138
1139 if (m->unicast_scope)
1140 dns_cache_flush(&m->unicast_scope->cache);
1141
4e945a6f 1142 return s;
74b2466e
LP
1143}
1144
1145DnsServer *manager_get_dns_server(Manager *m) {
4e945a6f 1146 Link *l;
74b2466e
LP
1147 assert(m);
1148
5cb36f41
LP
1149 /* Try to read updates resolv.conf */
1150 manager_read_resolv_conf(m);
1151
74b2466e 1152 if (!m->current_dns_server)
4e945a6f
LP
1153 manager_set_dns_server(m, m->dns_servers);
1154
1155 if (!m->current_dns_server) {
1156 bool found = false;
1157 Iterator i;
1158
1159 /* No DNS servers configured, let's see if there are
1160 * any on any links. If not, we use the fallback
1161 * servers */
1162
1163 HASHMAP_FOREACH(l, m->links, i)
1164 if (l->dns_servers) {
1165 found = true;
1166 break;
1167 }
1168
1169 if (!found)
1170 manager_set_dns_server(m, m->fallback_dns_servers);
1171 }
74b2466e
LP
1172
1173 return m->current_dns_server;
1174}
1175
1176void manager_next_dns_server(Manager *m) {
1177 assert(m);
1178
4e945a6f
LP
1179 /* If there's currently no DNS server set, then the next
1180 * manager_get_dns_server() will find one */
74b2466e
LP
1181 if (!m->current_dns_server)
1182 return;
1183
4e945a6f 1184 /* Change to the next one */
74b2466e 1185 if (m->current_dns_server->servers_next) {
4e945a6f 1186 manager_set_dns_server(m, m->current_dns_server->servers_next);
74b2466e
LP
1187 return;
1188 }
1189
4e945a6f
LP
1190 /* If there was no next one, then start from the beginning of
1191 * the list */
1192 if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
1193 manager_set_dns_server(m, m->fallback_dns_servers);
1194 else
1195 manager_set_dns_server(m, m->dns_servers);
091a364c 1196}
e1c95994
LP
1197
1198uint32_t manager_find_mtu(Manager *m) {
1199 uint32_t mtu = 0;
1200 Link *l;
1201 Iterator i;
1202
1203 /* If we don't know on which link a DNS packet would be
1204 * delivered, let's find the largest MTU that works on all
1205 * interfaces we know of */
1206
1207 HASHMAP_FOREACH(l, m->links, i) {
1208 if (l->mtu <= 0)
1209 continue;
1210
1211 if (mtu <= 0 || l->mtu < mtu)
1212 mtu = l->mtu;
1213 }
1214
1215 return mtu;
1216}
1716f6dc
LP
1217
1218static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1219 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ec2c5e43 1220 DnsTransaction *t = NULL;
1716f6dc
LP
1221 Manager *m = userdata;
1222 int r;
1223
1224 r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
1225 if (r <= 0)
1226 return r;
1227
623a4c97 1228 if (dns_packet_validate_reply(p) > 0) {
a2a416f7
LP
1229 log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
1230
ec2c5e43 1231 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
1716f6dc
LP
1232 if (!t)
1233 return 0;
1234
ec2c5e43 1235 dns_transaction_process_reply(t, p);
623a4c97
LP
1236
1237 } else if (dns_packet_validate_query(p) > 0) {
1238 Link *l;
1239
1240 l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
1241 if (l) {
1242 DnsScope *scope = NULL;
1243
1244 if (p->family == AF_INET)
1245 scope = l->llmnr_ipv4_scope;
1246 else if (p->family == AF_INET6)
1247 scope = l->llmnr_ipv6_scope;
1248
1249 if (scope)
1250 dns_scope_process_query(scope, NULL, p);
1251 }
1252 } else
1253 log_debug("Invalid LLMNR packet.");
1716f6dc
LP
1254
1255 return 0;
1256}
1257
1258int manager_llmnr_ipv4_udp_fd(Manager *m) {
1259 union sockaddr_union sa = {
1260 .in.sin_family = AF_INET,
1261 .in.sin_port = htobe16(5355),
1262 };
bf3f1271 1263 static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
1716f6dc
LP
1264 int r;
1265
1266 assert(m);
1267
1268 if (m->llmnr_ipv4_udp_fd >= 0)
1269 return m->llmnr_ipv4_udp_fd;
1270
1271 m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1272 if (m->llmnr_ipv4_udp_fd < 0)
1273 return -errno;
1274
bf3f1271
LP
1275 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
1276 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
1716f6dc
LP
1277 if (r < 0) {
1278 r = -errno;
1279 goto fail;
1280 }
1281
bf3f1271 1282 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
1716f6dc
LP
1283 if (r < 0) {
1284 r = -errno;
1285 goto fail;
1286 }
1287
1288 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
1289 if (r < 0) {
1290 r = -errno;
1291 goto fail;
1292 }
1293
1294 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1295 if (r < 0) {
1296 r = -errno;
1297 goto fail;
1298 }
1299
1300 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1301 if (r < 0) {
1302 r = -errno;
1303 goto fail;
1304 }
1305
1306 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1307 if (r < 0) {
1308 r = -errno;
1309 goto fail;
1310 }
1311
1312 /* Disable Don't-Fragment bit in the IP header */
1313 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1314 if (r < 0) {
1315 r = -errno;
1316 goto fail;
1317 }
1318
1319 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
1320 if (r < 0) {
1321 r = -errno;
1322 goto fail;
1323 }
1324
1325 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
1326 if (r < 0)
1327 goto fail;
1328
1329 return m->llmnr_ipv4_udp_fd;
1330
1331fail:
1332 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
1333 return r;
1334}
1335
1336int manager_llmnr_ipv6_udp_fd(Manager *m) {
1337 union sockaddr_union sa = {
1338 .in6.sin6_family = AF_INET6,
1339 .in6.sin6_port = htobe16(5355),
1340 };
bf3f1271 1341 static const int one = 1, ttl = 255;
1716f6dc
LP
1342 int r;
1343
1344 assert(m);
1345
1346 if (m->llmnr_ipv6_udp_fd >= 0)
1347 return m->llmnr_ipv6_udp_fd;
1348
1349 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1350 if (m->llmnr_ipv6_udp_fd < 0)
1351 return -errno;
1352
bf3f1271 1353 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
1716f6dc
LP
1354 if (r < 0) {
1355 r = -errno;
1356 goto fail;
1357 }
1358
bf3f1271
LP
1359 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
1360 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
1716f6dc
LP
1361 if (r < 0) {
1362 r = -errno;
1363 goto fail;
1364 }
1365
1366 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
1367 if (r < 0) {
1368 r = -errno;
1369 goto fail;
1370 }
1371
1372 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1373 if (r < 0) {
1374 r = -errno;
1375 goto fail;
1376 }
1377
1378 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1379 if (r < 0) {
1380 r = -errno;
1381 goto fail;
1382 }
1383
1384 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1385 if (r < 0) {
1386 r = -errno;
1387 goto fail;
1388 }
1389
1390 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1391 if (r < 0) {
1392 r = -errno;
1393 goto fail;
1394 }
1395
1396 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
1397 if (r < 0) {
1398 r = -errno;
1399 goto fail;
1400 }
1401
1402 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
1403 if (r < 0) {
1404 r = -errno;
1405 goto fail;
1406 }
1407
1408 return m->llmnr_ipv6_udp_fd;
1409
1410fail:
1411 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
1412 return r;
1413}
623a4c97
LP
1414
1415static int on_llmnr_stream_packet(DnsStream *s) {
1416 assert(s);
1417
1418 if (dns_packet_validate_query(s->read_packet) > 0) {
1419 Link *l;
1420
1421 l = hashmap_get(s->manager->links, INT_TO_PTR(s->read_packet->ifindex));
1422 if (l) {
1423 DnsScope *scope = NULL;
1424
1425 if (s->read_packet->family == AF_INET)
1426 scope = l->llmnr_ipv4_scope;
1427 else if (s->read_packet->family == AF_INET6)
1428 scope = l->llmnr_ipv6_scope;
1429
1430 if (scope) {
1431 dns_scope_process_query(scope, s, s->read_packet);
1432
1433 /* If no reply packet was set, we free the stream */
1434 if (s->write_packet)
1435 return 0;
1436 }
1437 }
1438 }
1439
1440 dns_stream_free(s);
1441 return 0;
1442}
1443
1444static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1445 DnsStream *stream;
1446 Manager *m = userdata;
1447 int cfd, r;
1448
1449 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
1450 if (cfd < 0) {
1451 if (errno == EAGAIN || errno == EINTR)
1452 return 0;
1453
1454 return -errno;
1455 }
1456
1457 r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
1458 if (r < 0) {
1459 safe_close(cfd);
1460 return r;
1461 }
1462
1463 stream->on_packet = on_llmnr_stream_packet;
1464 return 0;
1465}
1466
1467int manager_llmnr_ipv4_tcp_fd(Manager *m) {
1468 union sockaddr_union sa = {
1469 .in.sin_family = AF_INET,
1470 .in.sin_port = htobe16(5355),
1471 };
1472 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
1473 int r;
1474
1475 assert(m);
1476
1477 if (m->llmnr_ipv4_tcp_fd >= 0)
1478 return m->llmnr_ipv4_tcp_fd;
1479
1480 m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1481 if (m->llmnr_ipv4_tcp_fd < 0)
1482 return -errno;
1483
bf3f1271 1484 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
623a4c97
LP
1485 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
1486 if (r < 0) {
1487 r = -errno;
1488 goto fail;
1489 }
1490
1491 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1492 if (r < 0) {
1493 r = -errno;
1494 goto fail;
1495 }
1496
1497 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1498 if (r < 0) {
1499 r = -errno;
1500 goto fail;
1501 }
1502
1503 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1504 if (r < 0) {
1505 r = -errno;
1506 goto fail;
1507 }
1508
1509 /* Disable Don't-Fragment bit in the IP header */
1510 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1511 if (r < 0) {
1512 r = -errno;
1513 goto fail;
1514 }
1515
1516 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
1517 if (r < 0) {
1518 r = -errno;
1519 goto fail;
1520 }
1521
1522 r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
1523 if (r < 0) {
1524 r = -errno;
1525 goto fail;
1526 }
1527
1528 r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
1529 if (r < 0)
1530 goto fail;
1531
1532 return m->llmnr_ipv4_tcp_fd;
1533
1534fail:
1535 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
1536 return r;
1537}
1538
1539int manager_llmnr_ipv6_tcp_fd(Manager *m) {
1540 union sockaddr_union sa = {
1541 .in6.sin6_family = AF_INET6,
1542 .in6.sin6_port = htobe16(5355),
1543 };
1544 static const int one = 1;
1545 int r;
1546
1547 assert(m);
1548
1549 if (m->llmnr_ipv6_tcp_fd >= 0)
1550 return m->llmnr_ipv6_tcp_fd;
1551
1552 m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1553 if (m->llmnr_ipv6_tcp_fd < 0)
1554 return -errno;
1555
bf3f1271 1556 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
623a4c97
LP
1557 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
1558 if (r < 0) {
1559 r = -errno;
1560 goto fail;
1561 }
1562
1563 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1564 if (r < 0) {
1565 r = -errno;
1566 goto fail;
1567 }
1568
1569 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1570 if (r < 0) {
1571 r = -errno;
1572 goto fail;
1573 }
1574
1575 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1576 if (r < 0) {
1577 r = -errno;
1578 goto fail;
1579 }
1580
1581 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1582 if (r < 0) {
1583 r = -errno;
1584 goto fail;
1585 }
1586
1587 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
1588 if (r < 0) {
1589 r = -errno;
1590 goto fail;
1591 }
1592
1593 r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
1594 if (r < 0) {
1595 r = -errno;
1596 goto fail;
1597 }
1598
1599 r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
1600 if (r < 0) {
1601 r = -errno;
1602 goto fail;
1603 }
1604
1605 return m->llmnr_ipv6_tcp_fd;
1606
1607fail:
1608 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
1609 return r;
1610}
1611
1612int manager_ifindex_is_loopback(Manager *m, int ifindex) {
1613 Link *l;
1614 assert(m);
1615
1616 if (ifindex <= 0)
1617 return -EINVAL;
1618
1619 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1620 if (l->flags & IFF_LOOPBACK)
1621 return 1;
1622
1623 return 0;
1624}
1625
1626int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1627 LinkAddress *a;
1628
1629 assert(m);
1630
4e945a6f 1631 a = manager_find_link_address(m, family, in_addr);
ec2c5e43
LP
1632 if (a)
1633 return a->link->ifindex;
1634
1635 return 0;
1636}
1637
eb60f9cd
LP
1638void manager_refresh_rrs(Manager *m) {
1639 Iterator i;
1640 Link *l;
1641
1642 assert(m);
1643
1644 m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
1645 m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
1646
1647 HASHMAP_FOREACH(l, m->links, i) {
1648 link_add_rrs(l, true);
1649 link_add_rrs(l, false);
1650 }
1651}
1652
ec2c5e43
LP
1653int manager_next_hostname(Manager *m) {
1654 const char *p;
ec2c5e43
LP
1655 uint64_t u;
1656 char *h;
623a4c97
LP
1657
1658 assert(m);
1659
ec2c5e43
LP
1660 p = strchr(m->hostname, 0);
1661 assert(p);
1662
1663 while (p > m->hostname) {
1664 if (!strchr("0123456789", p[-1]))
1665 break;
1666
1667 p--;
1668 }
1669
1670 if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
1671 u = 1;
1672
1673 u++;
1674
1675 if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
1676 return -ENOMEM;
1677
eb60f9cd 1678 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
ec2c5e43
LP
1679
1680 free(m->hostname);
1681 m->hostname = h;
1682
eb60f9cd 1683 manager_refresh_rrs(m);
623a4c97
LP
1684
1685 return 0;
1686}
ec2c5e43 1687
4e945a6f 1688LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e43
LP
1689 Iterator i;
1690 Link *l;
1691
1692 assert(m);
1693
1694 HASHMAP_FOREACH(l, m->links, i) {
1695 LinkAddress *a;
1696
1697 a = link_find_address(l, family, in_addr);
1698 if (a)
1699 return a;
1700 }
1701
1702 return NULL;
1703}
1704
1705int manager_our_packet(Manager *m, DnsPacket *p) {
1706 assert(m);
1707 assert(p);
1708
4e945a6f 1709 return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e43 1710}
4e945a6f
LP
1711
1712static const char* const support_table[_SUPPORT_MAX] = {
1713 [SUPPORT_NO] = "no",
1714 [SUPPORT_YES] = "yes",
1715 [SUPPORT_RESOLVE] = "resolve",
1716};
1717DEFINE_STRING_TABLE_LOOKUP(support, Support);