X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=blobdiff_plain;f=src%2Fresolve%2Fresolved-manager.c;h=58fe572d3b9969c7bbfb2fa68c6d05a6498b69da;hp=30036049da6e58b1775954b73d40322797c728ef;hb=608f70e6b454020bfc8f807bd0f9d1c412d4157a;hpb=a2c28c645160b4e9377db4cb40cb9f22141f2dd3 diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 30036049da6..58fe572d3b9 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -21,6 +21,10 @@ #include #include +#if HAVE_LIBIDN2 +#include +#endif + #include "af-list.h" #include "alloc-util.h" #include "dirent-util.h" @@ -322,32 +326,46 @@ static int manager_network_monitor_listen(Manager *m) { return 0; } -static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) { +static int determine_hostname(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) { _cleanup_free_ char *h = NULL, *n = NULL; +#if HAVE_LIBIDN2 + _cleanup_free_ char *utf8 = NULL; +#elif HAVE_LIBIDN + int k; +#endif char label[DNS_LABEL_MAX]; - const char *p; - int r, k; + const char *p, *decoded; + int r; + assert(full_hostname); assert(llmnr_hostname); assert(mdns_hostname); - /* Extract and normalize the first label of the locally - * configured hostname, and check it's not "localhost". */ + /* Extract and normalize the first label of the locally configured hostname, and check it's not "localhost". */ - h = gethostname_malloc(); - if (!h) - return log_oom(); + r = gethostname_strict(&h); + if (r < 0) + return log_debug_errno(r, "Can't determine system hostname: %m"); p = h; - r = dns_label_unescape(&p, label, sizeof(label)); + r = dns_label_unescape(&p, label, sizeof label); if (r < 0) return log_error_errno(r, "Failed to unescape host name: %m"); if (r == 0) { - log_error("Couldn't find a single label in hosntame."); + log_error("Couldn't find a single label in hostname."); return -EINVAL; } - k = dns_label_undo_idna(label, r, label, sizeof(label)); +#if HAVE_LIBIDN2 + r = idn2_to_unicode_8z8z(label, &utf8, 0); + if (r != IDN2_OK) + return log_error("Failed to undo IDNA: %s", idn2_strerror(r)); + assert(utf8_is_valid(utf8)); + + r = strlen(utf8); + decoded = utf8; +#elif HAVE_LIBIDN + k = dns_label_undo_idna(label, r, label, sizeof label); if (k < 0) return log_error_errno(k, "Failed to undo IDNA: %m"); if (k > 0) @@ -357,8 +375,12 @@ static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) { log_error("System hostname is not UTF-8 clean."); return -EINVAL; } + decoded = label; +#else + decoded = label; /* no decoding */ +#endif - r = dns_label_escape_new(label, r, &n); + r = dns_label_escape_new(decoded, r, &n); if (r < 0) return log_error_errno(r, "Failed to escape host name: %m"); @@ -374,32 +396,84 @@ static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) { *llmnr_hostname = n; n = NULL; + *full_hostname = h; + h = NULL; + + return 0; +} + +static const char *fallback_hostname(void) { + + /* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it to be + * "localhost" even if that's the compiled in hostname. In this case, let's revert to "linux" instead. */ + + if (is_localhost(FALLBACK_HOSTNAME)) + return "linux"; + + return FALLBACK_HOSTNAME; +} + +static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) { + _cleanup_free_ char *n = NULL, *m = NULL; + char label[DNS_LABEL_MAX], *h; + const char *p; + int r; + + assert(full_hostname); + assert(llmnr_hostname); + assert(mdns_hostname); + + p = fallback_hostname(); + r = dns_label_unescape(&p, label, sizeof(label)); + if (r < 0) + return log_error_errno(r, "Failed to unescape fallback host name: %m"); + + assert(r > 0); /* The fallback hostname must have at least one label */ + + r = dns_label_escape_new(label, r, &n); + if (r < 0) + return log_error_errno(r, "Failed to escape fallback hostname: %m"); + + r = dns_name_concat(n, "local", &m); + if (r < 0) + return log_error_errno(r, "Failed to concatenate mDNS hostname: %m"); + + h = strdup(fallback_hostname()); + if (!h) + return log_oom(); + + *llmnr_hostname = n; + n = NULL; + + *mdns_hostname = m; + m = NULL; + + *full_hostname = h; + return 0; } static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) { - _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL; + _cleanup_free_ char *full_hostname = NULL, *llmnr_hostname = NULL, *mdns_hostname = NULL; Manager *m = userdata; int r; assert(m); - r = determine_hostname(&llmnr_hostname, &mdns_hostname); + r = determine_hostname(&full_hostname, &llmnr_hostname, &mdns_hostname); if (r < 0) return 0; /* ignore invalid hostnames */ - if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname)) + if (streq(full_hostname, m->full_hostname) && + streq(llmnr_hostname, m->llmnr_hostname) && + streq(mdns_hostname, m->mdns_hostname)) return 0; - log_info("System hostname changed to '%s'.", llmnr_hostname); - - free(m->llmnr_hostname); - free(m->mdns_hostname); - - m->llmnr_hostname = llmnr_hostname; - m->mdns_hostname = mdns_hostname; + log_info("System hostname changed to '%s'.", full_hostname); - llmnr_hostname = mdns_hostname = NULL; + free_and_replace(m->full_hostname, full_hostname); + free_and_replace(m->llmnr_hostname, llmnr_hostname); + free_and_replace(m->mdns_hostname, mdns_hostname); manager_refresh_rrs(m); @@ -428,18 +502,15 @@ static int manager_watch_hostname(Manager *m) { (void) sd_event_source_set_description(m->hostname_event_source, "hostname"); - r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname); + r = determine_hostname(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname); if (r < 0) { - log_info("Defaulting to hostname 'linux'."); - m->llmnr_hostname = strdup("linux"); - if (!m->llmnr_hostname) - return log_oom(); - - m->mdns_hostname = strdup("linux.local"); - if (!m->mdns_hostname) - return log_oom(); + log_info("Defaulting to hostname '%s'.", fallback_hostname()); + + r = make_fallback_hostnames(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname); + if (r < 0) + return r; } else - log_info("Using system hostname '%s'.", m->llmnr_hostname); + log_info("Using system hostname '%s'.", m->full_hostname); return 0; } @@ -498,8 +569,10 @@ int manager_new(Manager **ret) { m->hostname_fd = -1; m->llmnr_support = RESOLVE_SUPPORT_YES; - m->mdns_support = RESOLVE_SUPPORT_NO; + m->mdns_support = RESOLVE_SUPPORT_YES; m->dnssec_mode = DEFAULT_DNSSEC_MODE; + m->enable_cache = true; + m->dns_stub_listener_mode = DNS_STUB_LISTENER_UDP; m->read_resolv_conf = true; m->need_builtin_fallbacks = true; m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY; @@ -510,7 +583,7 @@ int manager_new(Manager **ret) { r = manager_parse_config_file(m); if (r < 0) - return r; + log_warning_errno(r, "Failed to parse configuration file: %m"); r = sd_event_default(&m->event); if (r < 0) @@ -561,14 +634,6 @@ int manager_start(Manager *m) { if (r < 0) return r; - r = manager_llmnr_start(m); - if (r < 0) - return r; - - r = manager_mdns_start(m); - if (r < 0) - return r; - return 0; } @@ -619,18 +684,20 @@ Manager *manager_free(Manager *m) { dns_resource_key_unref(m->llmnr_host_ipv4_key); dns_resource_key_unref(m->llmnr_host_ipv6_key); + dns_resource_key_unref(m->mdns_host_ipv4_key); + dns_resource_key_unref(m->mdns_host_ipv6_key); sd_event_source_unref(m->hostname_event_source); safe_close(m->hostname_fd); + + free(m->full_hostname); free(m->llmnr_hostname); free(m->mdns_hostname); dns_trust_anchor_flush(&m->trust_anchor); manager_etc_hosts_flush(m); - free(m); - - return NULL; + return mfree(m); } int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { @@ -656,7 +723,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { if (ms < 0) return ms; - r = dns_packet_new(&p, protocol, ms); + r = dns_packet_new(&p, protocol, ms, DNS_PACKET_SIZE_MAX); if (r < 0) return r; @@ -674,7 +741,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { if (l == 0) return 0; if (l < 0) { - if (errno == EAGAIN || errno == EINTR) + if (IN_SET(errno, EAGAIN, EINTR)) return 0; return -errno; @@ -1007,6 +1074,8 @@ void manager_refresh_rrs(Manager *m) { m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key); m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key); + m->mdns_host_ipv4_key = dns_resource_key_unref(m->mdns_host_ipv4_key); + m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key); HASHMAP_FOREACH(l, m->links, i) { link_add_rrs(l, true); @@ -1146,8 +1215,14 @@ int manager_is_own_hostname(Manager *m, const char *name) { return r; } - if (m->mdns_hostname) - return dns_name_equal(name, m->mdns_hostname); + if (m->mdns_hostname) { + r = dns_name_equal(name, m->mdns_hostname); + if (r != 0) + return r; + } + + if (m->full_hostname) + return dns_name_equal(name, m->full_hostname); return 0; } @@ -1199,6 +1274,11 @@ int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { return 0; } +/* filter_route is a tri-state: + * < 0: no filtering + * = 0 or false: return only domains which should be used for searching + * > 0 or true: return only domains which are for routing only + */ int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) { DnsSearchDomain *d; Iterator i; @@ -1344,7 +1424,7 @@ void manager_cleanup_saved_user(Manager *m) { if (!IN_SET(de->d_type, DT_UNKNOWN, DT_REG)) continue; - if (STR_IN_SET(de->d_name, ".", "..")) + if (dot_or_dot_dot(de->d_name)) continue; r = parse_ifindex(de->d_name, &ifindex);