mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
hostnamed: watch system hostname changes and update LLMNR RRs accordingly
This commit is contained in:
parent
8581858257
commit
eb60f9cd4e
@ -34,6 +34,8 @@
|
||||
#include "socket-util.h"
|
||||
#include "af-list.h"
|
||||
#include "resolved.h"
|
||||
#include "utf8.h"
|
||||
#include "resolved-dns-domain.h"
|
||||
|
||||
#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
|
||||
|
||||
@ -384,6 +386,92 @@ int manager_parse_config_file(Manager *m) {
|
||||
false, false, true, m);
|
||||
}
|
||||
|
||||
static int determine_hostname(char **ret) {
|
||||
_cleanup_free_ char *h = NULL, *n = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
h = gethostname_malloc();
|
||||
if (!h)
|
||||
return log_oom();
|
||||
|
||||
if (!utf8_is_valid(h)) {
|
||||
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;
|
||||
}
|
||||
|
||||
*ret = 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;
|
||||
Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = determine_hostname(&h);
|
||||
if (r < 0)
|
||||
return 0; /* ignore invalid hostnames */
|
||||
|
||||
if (streq(h, m->hostname))
|
||||
return 0;
|
||||
|
||||
log_info("System hostname changed to '%s'.", h);
|
||||
free(m->hostname);
|
||||
m->hostname = h;
|
||||
h = NULL;
|
||||
|
||||
manager_refresh_rrs(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_watch_hostname(Manager *m) {
|
||||
_cleanup_free_ char *h = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
|
||||
if (m->hostname_fd < 0) {
|
||||
log_warning("Failed to watch hostname: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
|
||||
if (r < 0) {
|
||||
if (r == -EPERM)
|
||||
/* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
|
||||
m->hostname_fd = safe_close(m->hostname_fd);
|
||||
else {
|
||||
log_error("Failed to add hostname event source: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = determine_hostname(&m->hostname);
|
||||
if (r < 0) {
|
||||
log_info("Defaulting to hostname 'linux'.");
|
||||
m->hostname = strdup("linux");
|
||||
if (!m->hostname)
|
||||
return log_oom();
|
||||
} else
|
||||
log_info("Using system hostname '%s'.", m->hostname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int r;
|
||||
@ -397,6 +485,7 @@ int manager_new(Manager **ret) {
|
||||
m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
|
||||
m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
|
||||
m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
|
||||
m->hostname_fd = -1;
|
||||
|
||||
m->use_llmnr = true;
|
||||
|
||||
@ -404,10 +493,6 @@ int manager_new(Manager **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->hostname = gethostname_malloc();
|
||||
if (!m->hostname)
|
||||
return -ENOMEM;
|
||||
|
||||
r = sd_event_default(&m->event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -417,6 +502,10 @@ int manager_new(Manager **ret) {
|
||||
|
||||
sd_event_set_watchdog(m->event, true);
|
||||
|
||||
r = manager_watch_hostname(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -497,7 +586,11 @@ Manager *manager_free(Manager *m) {
|
||||
|
||||
dns_resource_key_unref(m->host_ipv4_key);
|
||||
dns_resource_key_unref(m->host_ipv6_key);
|
||||
|
||||
safe_close(m->hostname_fd);
|
||||
sd_event_source_unref(m->hostname_event_source);
|
||||
free(m->hostname);
|
||||
|
||||
free(m);
|
||||
|
||||
return NULL;
|
||||
@ -1408,12 +1501,25 @@ int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_a
|
||||
return 0;
|
||||
}
|
||||
|
||||
void manager_refresh_rrs(Manager *m) {
|
||||
Iterator i;
|
||||
Link *l;
|
||||
|
||||
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);
|
||||
|
||||
HASHMAP_FOREACH(l, m->links, i) {
|
||||
link_add_rrs(l, true);
|
||||
link_add_rrs(l, false);
|
||||
}
|
||||
}
|
||||
|
||||
int manager_next_hostname(Manager *m) {
|
||||
const char *p;
|
||||
Iterator i;
|
||||
uint64_t u;
|
||||
char *h;
|
||||
Link *l;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -1435,18 +1541,12 @@ int manager_next_hostname(Manager *m) {
|
||||
if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
log_info("Hostname conflict, changing local hostname from '%s' to '%s'.", m->hostname, h);
|
||||
log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
|
||||
|
||||
free(m->hostname);
|
||||
m->hostname = h;
|
||||
|
||||
m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
|
||||
m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
|
||||
|
||||
HASHMAP_FOREACH(l, m->links, i) {
|
||||
link_add_rrs(l, true);
|
||||
link_add_rrs(l, false);
|
||||
}
|
||||
manager_refresh_rrs(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -90,6 +90,10 @@ struct Manager {
|
||||
char *hostname;
|
||||
DnsResourceKey *host_ipv4_key;
|
||||
DnsResourceKey *host_ipv6_key;
|
||||
|
||||
/* Watch the system hostname */
|
||||
int hostname_fd;
|
||||
sd_event_source *hostname_event_source;
|
||||
};
|
||||
|
||||
/* Manager */
|
||||
@ -120,6 +124,7 @@ int manager_ifindex_is_loopback(Manager *m, int ifindex);
|
||||
int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr);
|
||||
LinkAddress* manager_find_address(Manager *m, int family, const union in_addr_union *in_addr);
|
||||
|
||||
void manager_refresh_rrs(Manager *m);
|
||||
int manager_next_hostname(Manager *m);
|
||||
|
||||
int manager_our_packet(Manager *m, DnsPacket *p);
|
||||
|
Loading…
Reference in New Issue
Block a user