summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve/resolved-manager.c')
-rw-r--r--src/resolve/resolved-manager.c131
1 files changed, 99 insertions, 32 deletions
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 645f2a824c..9f451dd3e8 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -310,51 +310,84 @@ static int manager_network_monitor_listen(Manager *m) {
return 0;
}
-static int determine_hostname(char **ret) {
+static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
_cleanup_free_ char *h = NULL, *n = NULL;
- int r;
+ char label[DNS_LABEL_MAX];
+ const char *p;
+ int r, k;
- assert(ret);
+ assert(llmnr_hostname);
+ assert(mdns_hostname);
+
+ /* 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();
- if (!utf8_is_valid(h)) {
+ p = h;
+ 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.");
+ return -EINVAL;
+ }
+
+ 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)
+ r = k;
+
+ if (!utf8_is_valid(label)) {
log_error("System hostname is not UTF-8 clean.");
return -EINVAL;
}
- r = dns_name_normalize(h, &n);
- if (r < 0) {
- log_error("System hostname '%s' cannot be normalized.", h);
- return r;
+ r = dns_label_escape(label, r, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to escape host name: %m");
+
+ if (is_localhost(n)) {
+ log_debug("System hostname is 'localhost', ignoring.");
+ return -EINVAL;
}
- *ret = n;
+ r = dns_name_concat(n, "local", mdns_hostname);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine mDNS hostname: %m");
+
+ *llmnr_hostname = n;
n = NULL;
return 0;
}
static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
- _cleanup_free_ char *h = NULL;
+ _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
Manager *m = userdata;
int r;
assert(m);
- r = determine_hostname(&h);
+ r = determine_hostname(&llmnr_hostname, &mdns_hostname);
if (r < 0)
return 0; /* ignore invalid hostnames */
- if (streq(h, m->hostname))
+ if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
return 0;
- log_info("System hostname changed to '%s'.", h);
- free(m->hostname);
- m->hostname = h;
- h = NULL;
+ 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;
+
+ llmnr_hostname = mdns_hostname = NULL;
manager_refresh_rrs(m);
@@ -381,14 +414,18 @@ static int manager_watch_hostname(Manager *m) {
return log_error_errno(r, "Failed to add hostname event source: %m");
}
- r = determine_hostname(&m->hostname);
+ r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
if (r < 0) {
log_info("Defaulting to hostname 'linux'.");
- m->hostname = strdup("linux");
- if (!m->hostname)
+ 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();
} else
- log_info("Using system hostname '%s'.", m->hostname);
+ log_info("Using system hostname '%s'.", m->llmnr_hostname);
return 0;
}
@@ -492,12 +529,13 @@ Manager *manager_free(Manager *m) {
sd_event_unref(m->event);
- dns_resource_key_unref(m->host_ipv4_key);
- dns_resource_key_unref(m->host_ipv6_key);
+ dns_resource_key_unref(m->llmnr_host_ipv4_key);
+ dns_resource_key_unref(m->llmnr_host_ipv6_key);
safe_close(m->hostname_fd);
sd_event_source_unref(m->hostname_event_source);
- free(m->hostname);
+ free(m->llmnr_hostname);
+ free(m->mdns_hostname);
free(m);
@@ -1229,8 +1267,8 @@ void manager_refresh_rrs(Manager *m) {
assert(m);
- m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
- m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
+ 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);
HASHMAP_FOREACH(l, m->links, i) {
link_add_rrs(l, true);
@@ -1241,14 +1279,15 @@ void manager_refresh_rrs(Manager *m) {
int manager_next_hostname(Manager *m) {
const char *p;
uint64_t u, a;
- char *h;
+ char *h, *k;
+ int r;
assert(m);
- p = strchr(m->hostname, 0);
+ p = strchr(m->llmnr_hostname, 0);
assert(p);
- while (p > m->hostname) {
+ while (p > m->llmnr_hostname) {
if (!strchr("0123456789", p[-1]))
break;
@@ -1268,13 +1307,22 @@ int manager_next_hostname(Manager *m) {
random_bytes(&a, sizeof(a));
u += 1 + a % 10;
- if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
+ if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
return -ENOMEM;
- log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
+ r = dns_name_concat(h, "local", &k);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
+
+ free(m->llmnr_hostname);
+ m->llmnr_hostname = h;
- free(m->hostname);
- m->hostname = h;
+ free(m->mdns_hostname);
+ m->mdns_hostname = k;
manager_refresh_rrs(m);
@@ -1356,6 +1404,25 @@ void manager_flush_dns_servers(Manager *m, DnsServerType t) {
}
}
+int manager_is_own_hostname(Manager *m, const char *name) {
+ _cleanup_free_ char *l = NULL;
+ int r;
+
+ assert(m);
+ assert(name);
+
+ if (m->llmnr_hostname) {
+ r = dns_name_equal(name, m->llmnr_hostname);
+ if (r != 0)
+ return r;
+ }
+
+ if (m->mdns_hostname)
+ return dns_name_equal(name, m->mdns_hostname);
+
+ return 0;
+}
+
static const char* const support_table[_SUPPORT_MAX] = {
[SUPPORT_NO] = "no",
[SUPPORT_YES] = "yes",