mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 06:52:22 +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 "socket-util.h"
|
||||||
#include "af-list.h"
|
#include "af-list.h"
|
||||||
#include "resolved.h"
|
#include "resolved.h"
|
||||||
|
#include "utf8.h"
|
||||||
|
#include "resolved-dns-domain.h"
|
||||||
|
|
||||||
#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
|
#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
|
||||||
|
|
||||||
@ -384,6 +386,92 @@ int manager_parse_config_file(Manager *m) {
|
|||||||
false, false, true, 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) {
|
int manager_new(Manager **ret) {
|
||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -397,6 +485,7 @@ int manager_new(Manager **ret) {
|
|||||||
m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
|
m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
|
||||||
m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_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->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
|
||||||
|
m->hostname_fd = -1;
|
||||||
|
|
||||||
m->use_llmnr = true;
|
m->use_llmnr = true;
|
||||||
|
|
||||||
@ -404,10 +493,6 @@ int manager_new(Manager **ret) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
m->hostname = gethostname_malloc();
|
|
||||||
if (!m->hostname)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = sd_event_default(&m->event);
|
r = sd_event_default(&m->event);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -417,6 +502,10 @@ int manager_new(Manager **ret) {
|
|||||||
|
|
||||||
sd_event_set_watchdog(m->event, true);
|
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);
|
r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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_ipv4_key);
|
||||||
dns_resource_key_unref(m->host_ipv6_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->hostname);
|
||||||
|
|
||||||
free(m);
|
free(m);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1408,12 +1501,25 @@ int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_a
|
|||||||
return 0;
|
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) {
|
int manager_next_hostname(Manager *m) {
|
||||||
const char *p;
|
const char *p;
|
||||||
Iterator i;
|
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
char *h;
|
char *h;
|
||||||
Link *l;
|
|
||||||
|
|
||||||
assert(m);
|
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)
|
if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
|
||||||
return -ENOMEM;
|
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);
|
free(m->hostname);
|
||||||
m->hostname = h;
|
m->hostname = h;
|
||||||
|
|
||||||
m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
|
manager_refresh_rrs(m);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,10 @@ struct Manager {
|
|||||||
char *hostname;
|
char *hostname;
|
||||||
DnsResourceKey *host_ipv4_key;
|
DnsResourceKey *host_ipv4_key;
|
||||||
DnsResourceKey *host_ipv6_key;
|
DnsResourceKey *host_ipv6_key;
|
||||||
|
|
||||||
|
/* Watch the system hostname */
|
||||||
|
int hostname_fd;
|
||||||
|
sd_event_source *hostname_event_source;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Manager */
|
/* 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);
|
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);
|
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_next_hostname(Manager *m);
|
||||||
|
|
||||||
int manager_our_packet(Manager *m, DnsPacket *p);
|
int manager_our_packet(Manager *m, DnsPacket *p);
|
||||||
|
Loading…
Reference in New Issue
Block a user