resolved-manager.c revision a38d99451f2bf8026ec51aee91662292e823c6a8
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Tom Gundersen <teg@jklm.no>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to process RTNL link message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering a = link_find_address(l, family, &address);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_address_new(l, &a, family, &address);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø /* First, subscribe to interfaces coming and going */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Then, enumerate all links */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Finally, enumerate all addresses, too */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_process_address(m->rtnl, i, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_network_monitor_flush(m->network_monitor);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Could not update resolv.conf: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int determine_hostname(char **ret) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *h = NULL, *n = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("System hostname is not UTF-8 clean.");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("System hostname '%s' cannot be normalized.", h);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0; /* ignore invalid hostnames */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("System hostname changed to '%s'.", h);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int manager_watch_hostname(Manager *m) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = safe_close(m->hostname_fd);
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt return log_error_errno(r, "Failed to add hostname event source: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Defaulting to hostname 'linux'.");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Using system hostname '%s'.", m->hostname);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic void manager_llmnr_stop(Manager *m) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic int manager_llmnr_start(Manager *m) {
c4147df156835513c43260a14fc9f7af177f737fLennart Poettering log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering sd_event_source_unref(m->network_event_source);
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering sd_network_monitor_unref(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->dns_ipv4_event_source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->dns_ipv6_event_source);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->bus_retry_event_source);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_resource_key_unref(m->host_ipv4_key);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_resource_key_unref(m->host_ipv6_key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering sd_event_source_unref(m->hostname_event_source);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poetteringint manager_read_resolv_conf(Manager *m) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Reads the system /etc/resolv.conf, if it exists and is not
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * symlinked to our own resolv.conf instance */
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Have we already seen the file? */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Is it symlinked to our own file? */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_error_errno(errno, "Failed to stat open file: %m");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering FOREACH_LINE(line, f, r = -errno; goto clear) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering const char *a;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = in_addr_from_string_auto(a, &family, &address);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering log_warning("Failed to parse name server %s.", a);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering /* Whenever /etc/resolv.conf changes, start using the first
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * DNS server of it. This is useful to deal with broken
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * network managing implementations (like NetworkManager),
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * that when connecting to a VPN place both the VPN DNS
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * servers and the local ones in /etc/resolv.conf. Without
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * resetting the DNS server to use back to the first entry we
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * will continue to use the local one thus being unable to
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * resolve VPN domains. */
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering manager_set_dns_server(m, m->dns_servers);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersenstatic void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = in_addr_to_string(s->family, &s->address, &t);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersenstatic void write_resolv_conf_search(const char *domain, FILE *f,
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen fputs(" # Too many search domains configured, remaining ones ignored.", f);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmekstatic int write_resolv_conf_contents(FILE *f, Set *dns, Set *domains) {
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# Third party programs must not access this file directly, but\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# only through the symlink at /etc/resolv.conf. To manage\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# resolv.conf(5) in a different way, replace the symlink by a\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# static file or a different symlink.\n\n", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek fputs("# No DNS servers known.\n", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek write_resolv_conf_server(s, f, &count);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek unsigned length = 0, count = 0;
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek SET_FOREACH(domain, domains, i)
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek write_resolv_conf_search(domain, f, &count, &length);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_write_resolv_conf(Manager *m) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering static const char path[] = "/run/systemd/resolve/resolv.conf";
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen _cleanup_set_free_ Set *dns = NULL, *domains = NULL;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Read the system /etc/resolv.conf first */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* Add the full list to a set, to filter out duplicates */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* First add the system-wide servers */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers) {
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen /* Then, add the per-link servers and domains */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering LIST_FOREACH(servers, s, l->dns_servers) {
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen STRV_FOREACH(domain, l->unicast_scope->domains) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* If we found nothing, add the fallback servers */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers) {
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek r = fopen_temporary_label(path, path, &f, &temp_path);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek r = write_resolv_conf_contents(f, dns, domains);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->sender_port = be16toh(sa.in.sin_port);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->sender_port = be16toh(sa.in6.sin6_port);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } else if (cmsg->cmsg_level == IPPROTO_IP) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* The Linux kernel sets the interface index to the loopback
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * device if the packet came from the local host since it
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * avoids the routing table in such a case. Let's unset the
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * interface index in such a case. */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* If we don't know the interface index still, we look for the
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * first local interface with a matching address. Yuck! */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering 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));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
2c27fbca2d88214bd305272308a370a962818f1eLennart PoetteringDnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca2d88214bd305272308a370a962818f1eLennart PoetteringDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering in_addr_to_string(s->family, &s->address, &ip);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_info("Switching to system DNS server %s.", strna(ip));
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering dns_cache_flush(&m->unicast_scope->cache);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringDnsServer *manager_get_dns_server(Manager *m) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Try to read updates resolv.conf */
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->dns_servers);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* No DNS servers configured, let's see if there are
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * any on any links. If not, we use the fallback
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->fallback_dns_servers);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringvoid manager_next_dns_server(Manager *m) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* If there's currently no DNS server set, then the next
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * manager_get_dns_server() will find one */
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* Change to the next one */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->current_dns_server->servers_next) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->current_dns_server->servers_next);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* If there was no next one, then start from the beginning of
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->fallback_dns_servers);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->dns_servers);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering /* If we don't know on which link a DNS packet would be
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * delivered, let's find the largest MTU that works on all
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * interfaces we know of */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering } else if (dns_packet_validate_query(p) > 0) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Got query packet for id %u", DNS_PACKET_ID(p));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_llmnr_ipv4_udp_fd(Manager *m) {
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Disable Don't-Fragment bit in the IP header */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_llmnr_ipv6_udp_fd(Manager *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int on_llmnr_stream_packet(DnsStream *s) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering scope = manager_find_scope(s->manager, s->read_packet);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_warning("Got LLMNR TCP packet on unknown scope. Ignroing.");
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (dns_packet_validate_query(s->read_packet) > 0) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet));
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering dns_scope_process_query(scope, s, s->read_packet);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering /* If no reply packet was set, we free the stream */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering stream->on_packet = on_llmnr_stream_packet;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_llmnr_ipv4_tcp_fd(Manager *m) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering static const int one = 1, pmtu = IP_PMTUDISC_DONT;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* Disable Don't-Fragment bit in the IP header */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_llmnr_ipv6_tcp_fd(Manager *m) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering a = manager_find_link_address(m, family, in_addr);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering const char *p;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering while (p > m->hostname) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering /* Add a random number to the old value. This way we can avoid
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * that two hosts pick the same hostname, win on IPv4 and lose
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * on IPv6 (or vice versa), and pick the same hostname
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * replacement hostname, ad infinitum. We still want the
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * numbers to go up monotonically, hence we just add a random
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * value 1..10 */
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart PoetteringLinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering a = link_find_address(l, family, in_addr);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringbool manager_our_packet(Manager *m, DnsPacket *p) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return !!manager_find_link_address(m, p->family, &p->sender);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart PoetteringDnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poetteringvoid manager_flush_dns_servers(Manager *m, DnsServerType t) {
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering dns_server_free(m->fallback_dns_servers);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic const char* const support_table[_SUPPORT_MAX] = {