1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
22 #include <netinet/in.h>
24 #include <sys/ioctl.h>
27 #include "alloc-util.h"
28 #include "dns-domain.h"
30 #include "fileio-label.h"
31 #include "hostname-util.h"
33 #include "netlink-util.h"
34 #include "network-internal.h"
35 #include "ordered-set.h"
36 #include "parse-util.h"
37 #include "random-util.h"
38 #include "resolved-bus.h"
39 #include "resolved-conf.h"
40 #include "resolved-llmnr.h"
41 #include "resolved-manager.h"
42 #include "resolved-resolv-conf.h"
43 #include "resolved-mdns.h"
44 #include "socket-util.h"
45 #include "string-table.h"
46 #include "string-util.h"
49 #define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
51 static int manager_process_link(sd_netlink
*rtnl
, sd_netlink_message
*mm
, void *userdata
) {
52 Manager
*m
= userdata
;
61 r
= sd_netlink_message_get_type(mm
, &type
);
65 r
= sd_rtnl_message_link_get_ifindex(mm
, &ifindex
);
69 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
77 r
= link_new(m
, &l
, ifindex
);
82 r
= link_update_rtnl(l
, mm
);
86 r
= link_update_monitor(l
);
91 log_debug("Found new link %i/%s", ifindex
, l
->name
);
98 log_debug("Removing link %i/%s", l
->ifindex
, l
->name
);
108 log_warning_errno(r
, "Failed to process RTNL link message: %m");
112 static int manager_process_address(sd_netlink
*rtnl
, sd_netlink_message
*mm
, void *userdata
) {
113 Manager
*m
= userdata
;
114 union in_addr_union address
;
116 int r
, ifindex
, family
;
124 r
= sd_netlink_message_get_type(mm
, &type
);
128 r
= sd_rtnl_message_addr_get_ifindex(mm
, &ifindex
);
132 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
136 r
= sd_rtnl_message_addr_get_family(mm
, &family
);
143 r
= sd_netlink_message_read_in_addr(mm
, IFA_LOCAL
, &address
.in
);
145 r
= sd_netlink_message_read_in_addr(mm
, IFA_ADDRESS
, &address
.in
);
153 r
= sd_netlink_message_read_in6_addr(mm
, IFA_LOCAL
, &address
.in6
);
155 r
= sd_netlink_message_read_in6_addr(mm
, IFA_ADDRESS
, &address
.in6
);
166 a
= link_find_address(l
, family
, &address
);
173 r
= link_address_new(l
, &a
, family
, &address
);
178 r
= link_address_update_rtnl(a
, mm
);
185 link_address_free(a
);
192 log_warning_errno(r
, "Failed to process RTNL address message: %m");
196 static int manager_rtnl_listen(Manager
*m
) {
197 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
198 sd_netlink_message
*i
;
203 /* First, subscribe to interfaces coming and going */
204 r
= sd_netlink_open(&m
->rtnl
);
208 r
= sd_netlink_attach_event(m
->rtnl
, m
->event
, 0);
212 r
= sd_netlink_add_match(m
->rtnl
, RTM_NEWLINK
, manager_process_link
, m
);
216 r
= sd_netlink_add_match(m
->rtnl
, RTM_DELLINK
, manager_process_link
, m
);
220 r
= sd_netlink_add_match(m
->rtnl
, RTM_NEWADDR
, manager_process_address
, m
);
224 r
= sd_netlink_add_match(m
->rtnl
, RTM_DELADDR
, manager_process_address
, m
);
228 /* Then, enumerate all links */
229 r
= sd_rtnl_message_new_link(m
->rtnl
, &req
, RTM_GETLINK
, 0);
233 r
= sd_netlink_message_request_dump(req
, true);
237 r
= sd_netlink_call(m
->rtnl
, req
, 0, &reply
);
241 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
242 r
= manager_process_link(m
->rtnl
, i
, m
);
247 req
= sd_netlink_message_unref(req
);
248 reply
= sd_netlink_message_unref(reply
);
250 /* Finally, enumerate all addresses, too */
251 r
= sd_rtnl_message_new_addr(m
->rtnl
, &req
, RTM_GETADDR
, 0, AF_UNSPEC
);
255 r
= sd_netlink_message_request_dump(req
, true);
259 r
= sd_netlink_call(m
->rtnl
, req
, 0, &reply
);
263 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
264 r
= manager_process_address(m
->rtnl
, i
, m
);
272 static int on_network_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
273 Manager
*m
= userdata
;
280 sd_network_monitor_flush(m
->network_monitor
);
282 HASHMAP_FOREACH(l
, m
->links
, i
) {
283 r
= link_update_monitor(l
);
285 log_warning_errno(r
, "Failed to update monitor information for %i: %m", l
->ifindex
);
288 r
= manager_write_resolv_conf(m
);
290 log_warning_errno(r
, "Could not update resolv.conf: %m");
295 static int manager_network_monitor_listen(Manager
*m
) {
300 r
= sd_network_monitor_new(&m
->network_monitor
, NULL
);
304 fd
= sd_network_monitor_get_fd(m
->network_monitor
);
308 events
= sd_network_monitor_get_events(m
->network_monitor
);
312 r
= sd_event_add_io(m
->event
, &m
->network_event_source
, fd
, events
, &on_network_event
, m
);
316 (void) sd_event_source_set_description(m
->network_event_source
, "network-monitor");
321 static int determine_hostname(char **llmnr_hostname
, char **mdns_hostname
) {
322 _cleanup_free_
char *h
= NULL
, *n
= NULL
;
323 char label
[DNS_LABEL_MAX
];
327 assert(llmnr_hostname
);
328 assert(mdns_hostname
);
330 /* Extract and normalize the first label of the locally
331 * configured hostname, and check it's not "localhost". */
333 h
= gethostname_malloc();
338 r
= dns_label_unescape(&p
, label
, sizeof(label
));
340 return log_error_errno(r
, "Failed to unescape host name: %m");
342 log_error("Couldn't find a single label in hosntame.");
346 k
= dns_label_undo_idna(label
, r
, label
, sizeof(label
));
348 return log_error_errno(k
, "Failed to undo IDNA: %m");
352 if (!utf8_is_valid(label
)) {
353 log_error("System hostname is not UTF-8 clean.");
357 r
= dns_label_escape_new(label
, r
, &n
);
359 return log_error_errno(r
, "Failed to escape host name: %m");
361 if (is_localhost(n
)) {
362 log_debug("System hostname is 'localhost', ignoring.");
366 r
= dns_name_concat(n
, "local", mdns_hostname
);
368 return log_error_errno(r
, "Failed to determine mDNS hostname: %m");
376 static int on_hostname_change(sd_event_source
*es
, int fd
, uint32_t revents
, void *userdata
) {
377 _cleanup_free_
char *llmnr_hostname
= NULL
, *mdns_hostname
= NULL
;
378 Manager
*m
= userdata
;
383 r
= determine_hostname(&llmnr_hostname
, &mdns_hostname
);
385 return 0; /* ignore invalid hostnames */
387 if (streq(llmnr_hostname
, m
->llmnr_hostname
) && streq(mdns_hostname
, m
->mdns_hostname
))
390 log_info("System hostname changed to '%s'.", llmnr_hostname
);
392 free(m
->llmnr_hostname
);
393 free(m
->mdns_hostname
);
395 m
->llmnr_hostname
= llmnr_hostname
;
396 m
->mdns_hostname
= mdns_hostname
;
398 llmnr_hostname
= mdns_hostname
= NULL
;
400 manager_refresh_rrs(m
);
405 static int manager_watch_hostname(Manager
*m
) {
410 m
->hostname_fd
= open("/proc/sys/kernel/hostname", O_RDONLY
|O_CLOEXEC
|O_NDELAY
|O_NOCTTY
);
411 if (m
->hostname_fd
< 0) {
412 log_warning_errno(errno
, "Failed to watch hostname: %m");
416 r
= sd_event_add_io(m
->event
, &m
->hostname_event_source
, m
->hostname_fd
, 0, on_hostname_change
, m
);
419 /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
420 m
->hostname_fd
= safe_close(m
->hostname_fd
);
422 return log_error_errno(r
, "Failed to add hostname event source: %m");
425 (void) sd_event_source_set_description(m
->hostname_event_source
, "hostname");
427 r
= determine_hostname(&m
->llmnr_hostname
, &m
->mdns_hostname
);
429 log_info("Defaulting to hostname 'linux'.");
430 m
->llmnr_hostname
= strdup("linux");
431 if (!m
->llmnr_hostname
)
434 m
->mdns_hostname
= strdup("linux.local");
435 if (!m
->mdns_hostname
)
438 log_info("Using system hostname '%s'.", m
->llmnr_hostname
);
443 static int manager_sigusr1(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
444 _cleanup_free_
char *buffer
= NULL
;
445 _cleanup_fclose_
FILE *f
= NULL
;
446 Manager
*m
= userdata
;
454 f
= open_memstream(&buffer
, &size
);
458 LIST_FOREACH(scopes
, scope
, m
->dns_scopes
)
459 dns_scope_dump(scope
, f
);
461 if (fflush_and_check(f
) < 0)
464 log_dump(LOG_INFO
, buffer
);
468 int manager_new(Manager
**ret
) {
469 _cleanup_(manager_freep
) Manager
*m
= NULL
;
474 m
= new0(Manager
, 1);
478 m
->llmnr_ipv4_udp_fd
= m
->llmnr_ipv6_udp_fd
= -1;
479 m
->llmnr_ipv4_tcp_fd
= m
->llmnr_ipv6_tcp_fd
= -1;
480 m
->mdns_ipv4_fd
= m
->mdns_ipv6_fd
= -1;
483 m
->llmnr_support
= RESOLVE_SUPPORT_YES
;
484 m
->mdns_support
= RESOLVE_SUPPORT_NO
;
485 m
->dnssec_mode
= DNSSEC_NO
;
486 m
->read_resolv_conf
= true;
487 m
->need_builtin_fallbacks
= true;
489 r
= dns_trust_anchor_load(&m
->trust_anchor
);
493 r
= manager_parse_config_file(m
);
497 r
= sd_event_default(&m
->event
);
501 sd_event_add_signal(m
->event
, NULL
, SIGTERM
, NULL
, NULL
);
502 sd_event_add_signal(m
->event
, NULL
, SIGINT
, NULL
, NULL
);
504 sd_event_set_watchdog(m
->event
, true);
506 r
= manager_watch_hostname(m
);
510 r
= dns_scope_new(m
, &m
->unicast_scope
, NULL
, DNS_PROTOCOL_DNS
, AF_UNSPEC
);
514 r
= manager_network_monitor_listen(m
);
518 r
= manager_rtnl_listen(m
);
522 r
= manager_connect_bus(m
);
526 (void) sd_event_add_signal(m
->event
, &m
->sigusr1_event_source
, SIGUSR1
, manager_sigusr1
, m
);
534 int manager_start(Manager
*m
) {
539 r
= manager_llmnr_start(m
);
543 r
= manager_mdns_start(m
);
550 Manager
*manager_free(Manager
*m
) {
556 dns_server_unlink_all(m
->dns_servers
);
557 dns_server_unlink_all(m
->fallback_dns_servers
);
558 dns_search_domain_unlink_all(m
->search_domains
);
560 while ((l
= hashmap_first(m
->links
)))
563 while (m
->dns_queries
)
564 dns_query_free(m
->dns_queries
);
566 dns_scope_free(m
->unicast_scope
);
568 hashmap_free(m
->links
);
569 hashmap_free(m
->dns_transactions
);
571 sd_event_source_unref(m
->network_event_source
);
572 sd_network_monitor_unref(m
->network_monitor
);
574 sd_netlink_unref(m
->rtnl
);
575 sd_event_source_unref(m
->rtnl_event_source
);
577 manager_llmnr_stop(m
);
578 manager_mdns_stop(m
);
580 sd_bus_slot_unref(m
->prepare_for_sleep_slot
);
581 sd_event_source_unref(m
->bus_retry_event_source
);
582 sd_bus_unref(m
->bus
);
584 sd_event_source_unref(m
->sigusr1_event_source
);
586 sd_event_unref(m
->event
);
588 dns_resource_key_unref(m
->llmnr_host_ipv4_key
);
589 dns_resource_key_unref(m
->llmnr_host_ipv6_key
);
591 sd_event_source_unref(m
->hostname_event_source
);
592 safe_close(m
->hostname_fd
);
593 free(m
->llmnr_hostname
);
594 free(m
->mdns_hostname
);
596 dns_trust_anchor_flush(&m
->trust_anchor
);
603 int manager_recv(Manager
*m
, int fd
, DnsProtocol protocol
, DnsPacket
**ret
) {
604 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
606 struct cmsghdr header
; /* For alignment */
607 uint8_t buffer
[CMSG_SPACE(MAXSIZE(struct in_pktinfo
, struct in6_pktinfo
))
608 + CMSG_SPACE(int) /* ttl/hoplimit */
609 + EXTRA_CMSG_SPACE
/* kernel appears to require extra buffer space */];
611 union sockaddr_union sa
;
612 struct msghdr mh
= {};
613 struct cmsghdr
*cmsg
;
622 r
= ioctl(fd
, FIONREAD
, &ms
);
628 r
= dns_packet_new(&p
, protocol
, ms
);
632 iov
.iov_base
= DNS_PACKET_DATA(p
);
633 iov
.iov_len
= p
->allocated
;
635 mh
.msg_name
= &sa
.sa
;
636 mh
.msg_namelen
= sizeof(sa
);
639 mh
.msg_control
= &control
;
640 mh
.msg_controllen
= sizeof(control
);
642 l
= recvmsg(fd
, &mh
, 0);
644 if (errno
== EAGAIN
|| errno
== EINTR
)
653 assert(!(mh
.msg_flags
& MSG_CTRUNC
));
654 assert(!(mh
.msg_flags
& MSG_TRUNC
));
656 p
->size
= (size_t) l
;
658 p
->family
= sa
.sa
.sa_family
;
659 p
->ipproto
= IPPROTO_UDP
;
660 if (p
->family
== AF_INET
) {
661 p
->sender
.in
= sa
.in
.sin_addr
;
662 p
->sender_port
= be16toh(sa
.in
.sin_port
);
663 } else if (p
->family
== AF_INET6
) {
664 p
->sender
.in6
= sa
.in6
.sin6_addr
;
665 p
->sender_port
= be16toh(sa
.in6
.sin6_port
);
666 p
->ifindex
= sa
.in6
.sin6_scope_id
;
668 return -EAFNOSUPPORT
;
670 CMSG_FOREACH(cmsg
, &mh
) {
672 if (cmsg
->cmsg_level
== IPPROTO_IPV6
) {
673 assert(p
->family
== AF_INET6
);
675 switch (cmsg
->cmsg_type
) {
678 struct in6_pktinfo
*i
= (struct in6_pktinfo
*) CMSG_DATA(cmsg
);
681 p
->ifindex
= i
->ipi6_ifindex
;
683 p
->destination
.in6
= i
->ipi6_addr
;
688 p
->ttl
= *(int *) CMSG_DATA(cmsg
);
692 } else if (cmsg
->cmsg_level
== IPPROTO_IP
) {
693 assert(p
->family
== AF_INET
);
695 switch (cmsg
->cmsg_type
) {
698 struct in_pktinfo
*i
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
701 p
->ifindex
= i
->ipi_ifindex
;
703 p
->destination
.in
= i
->ipi_addr
;
708 p
->ttl
= *(int *) CMSG_DATA(cmsg
);
714 /* The Linux kernel sets the interface index to the loopback
715 * device if the packet came from the local host since it
716 * avoids the routing table in such a case. Let's unset the
717 * interface index in such a case. */
718 if (p
->ifindex
== LOOPBACK_IFINDEX
)
721 if (protocol
!= DNS_PROTOCOL_DNS
) {
722 /* If we don't know the interface index still, we look for the
723 * first local interface with a matching address. Yuck! */
725 p
->ifindex
= manager_find_ifindex(m
, p
->family
, &p
->destination
);
734 static int sendmsg_loop(int fd
, struct msghdr
*mh
, int flags
) {
741 if (sendmsg(fd
, mh
, flags
) >= 0)
750 r
= fd_wait_for_event(fd
, POLLOUT
, SEND_TIMEOUT_USEC
);
758 static int write_loop(int fd
, void *message
, size_t length
) {
765 if (write(fd
, message
, length
) >= 0)
774 r
= fd_wait_for_event(fd
, POLLOUT
, SEND_TIMEOUT_USEC
);
782 int manager_write(Manager
*m
, int fd
, DnsPacket
*p
) {
785 log_debug("Sending %s packet with id %" PRIu16
".", DNS_PACKET_QR(p
) ? "response" : "query", DNS_PACKET_ID(p
));
787 r
= write_loop(fd
, DNS_PACKET_DATA(p
), p
->size
);
794 static int manager_ipv4_send(Manager
*m
, int fd
, int ifindex
, const struct in_addr
*addr
, uint16_t port
, DnsPacket
*p
) {
795 union sockaddr_union sa
= {
796 .in
.sin_family
= AF_INET
,
799 struct cmsghdr header
; /* For alignment */
800 uint8_t buffer
[CMSG_SPACE(sizeof(struct in_pktinfo
))];
802 struct msghdr mh
= {};
811 iov
.iov_base
= DNS_PACKET_DATA(p
);
812 iov
.iov_len
= p
->size
;
814 sa
.in
.sin_addr
= *addr
;
815 sa
.in
.sin_port
= htobe16(port
),
819 mh
.msg_name
= &sa
.sa
;
820 mh
.msg_namelen
= sizeof(sa
.in
);
823 struct cmsghdr
*cmsg
;
824 struct in_pktinfo
*pi
;
828 mh
.msg_control
= &control
;
829 mh
.msg_controllen
= CMSG_LEN(sizeof(struct in_pktinfo
));
831 cmsg
= CMSG_FIRSTHDR(&mh
);
832 cmsg
->cmsg_len
= mh
.msg_controllen
;
833 cmsg
->cmsg_level
= IPPROTO_IP
;
834 cmsg
->cmsg_type
= IP_PKTINFO
;
836 pi
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
837 pi
->ipi_ifindex
= ifindex
;
840 return sendmsg_loop(fd
, &mh
, 0);
843 static int manager_ipv6_send(Manager
*m
, int fd
, int ifindex
, const struct in6_addr
*addr
, uint16_t port
, DnsPacket
*p
) {
844 union sockaddr_union sa
= {
845 .in6
.sin6_family
= AF_INET6
,
848 struct cmsghdr header
; /* For alignment */
849 uint8_t buffer
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
851 struct msghdr mh
= {};
860 iov
.iov_base
= DNS_PACKET_DATA(p
);
861 iov
.iov_len
= p
->size
;
863 sa
.in6
.sin6_addr
= *addr
;
864 sa
.in6
.sin6_port
= htobe16(port
),
865 sa
.in6
.sin6_scope_id
= ifindex
;
869 mh
.msg_name
= &sa
.sa
;
870 mh
.msg_namelen
= sizeof(sa
.in6
);
873 struct cmsghdr
*cmsg
;
874 struct in6_pktinfo
*pi
;
878 mh
.msg_control
= &control
;
879 mh
.msg_controllen
= CMSG_LEN(sizeof(struct in6_pktinfo
));
881 cmsg
= CMSG_FIRSTHDR(&mh
);
882 cmsg
->cmsg_len
= mh
.msg_controllen
;
883 cmsg
->cmsg_level
= IPPROTO_IPV6
;
884 cmsg
->cmsg_type
= IPV6_PKTINFO
;
886 pi
= (struct in6_pktinfo
*) CMSG_DATA(cmsg
);
887 pi
->ipi6_ifindex
= ifindex
;
890 return sendmsg_loop(fd
, &mh
, 0);
893 int manager_send(Manager
*m
, int fd
, int ifindex
, int family
, const union in_addr_union
*addr
, uint16_t port
, DnsPacket
*p
) {
900 log_debug("Sending %s packet with id %" PRIu16
" on interface %i/%s.", DNS_PACKET_QR(p
) ? "response" : "query", DNS_PACKET_ID(p
), ifindex
, af_to_name(family
));
902 if (family
== AF_INET
)
903 return manager_ipv4_send(m
, fd
, ifindex
, &addr
->in
, port
, p
);
904 else if (family
== AF_INET6
)
905 return manager_ipv6_send(m
, fd
, ifindex
, &addr
->in6
, port
, p
);
907 return -EAFNOSUPPORT
;
910 uint32_t manager_find_mtu(Manager
*m
) {
915 /* If we don't know on which link a DNS packet would be
916 * delivered, let's find the largest MTU that works on all
917 * interfaces we know of */
919 HASHMAP_FOREACH(l
, m
->links
, i
) {
923 if (mtu
<= 0 || l
->mtu
< mtu
)
930 int manager_find_ifindex(Manager
*m
, int family
, const union in_addr_union
*in_addr
) {
935 a
= manager_find_link_address(m
, family
, in_addr
);
937 return a
->link
->ifindex
;
942 void manager_refresh_rrs(Manager
*m
) {
948 m
->llmnr_host_ipv4_key
= dns_resource_key_unref(m
->llmnr_host_ipv4_key
);
949 m
->llmnr_host_ipv6_key
= dns_resource_key_unref(m
->llmnr_host_ipv6_key
);
951 HASHMAP_FOREACH(l
, m
->links
, i
) {
952 link_add_rrs(l
, true);
953 link_add_rrs(l
, false);
957 int manager_next_hostname(Manager
*m
) {
965 p
= strchr(m
->llmnr_hostname
, 0);
968 while (p
> m
->llmnr_hostname
) {
969 if (!strchr("0123456789", p
[-1]))
975 if (*p
== 0 || safe_atou64(p
, &u
) < 0 || u
<= 0)
978 /* Add a random number to the old value. This way we can avoid
979 * that two hosts pick the same hostname, win on IPv4 and lose
980 * on IPv6 (or vice versa), and pick the same hostname
981 * replacement hostname, ad infinitum. We still want the
982 * numbers to go up monotonically, hence we just add a random
985 random_bytes(&a
, sizeof(a
));
988 if (asprintf(&h
, "%.*s%" PRIu64
, (int) (p
- m
->llmnr_hostname
), m
->llmnr_hostname
, u
) < 0)
991 r
= dns_name_concat(h
, "local", &k
);
997 log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m
->llmnr_hostname
, h
);
999 free(m
->llmnr_hostname
);
1000 m
->llmnr_hostname
= h
;
1002 free(m
->mdns_hostname
);
1003 m
->mdns_hostname
= k
;
1005 manager_refresh_rrs(m
);
1010 LinkAddress
* manager_find_link_address(Manager
*m
, int family
, const union in_addr_union
*in_addr
) {
1016 HASHMAP_FOREACH(l
, m
->links
, i
) {
1019 a
= link_find_address(l
, family
, in_addr
);
1027 bool manager_our_packet(Manager
*m
, DnsPacket
*p
) {
1031 return !!manager_find_link_address(m
, p
->family
, &p
->sender
);
1034 DnsScope
* manager_find_scope(Manager
*m
, DnsPacket
*p
) {
1040 l
= hashmap_get(m
->links
, INT_TO_PTR(p
->ifindex
));
1044 switch (p
->protocol
) {
1045 case DNS_PROTOCOL_LLMNR
:
1046 if (p
->family
== AF_INET
)
1047 return l
->llmnr_ipv4_scope
;
1048 else if (p
->family
== AF_INET6
)
1049 return l
->llmnr_ipv6_scope
;
1053 case DNS_PROTOCOL_MDNS
:
1054 if (p
->family
== AF_INET
)
1055 return l
->mdns_ipv4_scope
;
1056 else if (p
->family
== AF_INET6
)
1057 return l
->mdns_ipv6_scope
;
1068 void manager_verify_all(Manager
*m
) {
1073 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1074 dns_zone_verify_all(&s
->zone
);
1077 int manager_is_own_hostname(Manager
*m
, const char *name
) {
1083 if (m
->llmnr_hostname
) {
1084 r
= dns_name_equal(name
, m
->llmnr_hostname
);
1089 if (m
->mdns_hostname
)
1090 return dns_name_equal(name
, m
->mdns_hostname
);
1095 int manager_compile_dns_servers(Manager
*m
, OrderedSet
**dns
) {
1104 r
= ordered_set_ensure_allocated(dns
, &dns_server_hash_ops
);
1108 /* First add the system-wide servers and domains */
1109 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1110 r
= ordered_set_put(*dns
, s
);
1117 /* Then, add the per-link servers */
1118 HASHMAP_FOREACH(l
, m
->links
, i
) {
1119 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1120 r
= ordered_set_put(*dns
, s
);
1128 /* If we found nothing, add the fallback servers */
1129 if (ordered_set_isempty(*dns
)) {
1130 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1131 r
= ordered_set_put(*dns
, s
);
1142 int manager_compile_search_domains(Manager
*m
, OrderedSet
**domains
) {
1151 r
= ordered_set_ensure_allocated(domains
, &dns_name_hash_ops
);
1155 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1156 r
= ordered_set_put(*domains
, d
->name
);
1163 HASHMAP_FOREACH(l
, m
->links
, i
) {
1165 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1166 r
= ordered_set_put(*domains
, d
->name
);
1177 DnssecMode
manager_get_dnssec_mode(Manager
*m
) {
1180 if (m
->dnssec_mode
!= _DNSSEC_MODE_INVALID
)
1181 return m
->dnssec_mode
;
1186 bool manager_dnssec_supported(Manager
*m
) {
1193 if (manager_get_dnssec_mode(m
) == DNSSEC_NO
)
1196 server
= manager_get_dns_server(m
);
1197 if (server
&& !dns_server_dnssec_supported(server
))
1200 HASHMAP_FOREACH(l
, m
->links
, i
)
1201 if (!link_dnssec_supported(l
))