From bba51a20374648eec948113cfe1f0cd298bbe771 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 28 Feb 2017 11:20:49 +0100 Subject: llmnrd: Poll hostname Poll "/proc/sys/kernel/hostname" and update the hostname when it was changed. systemd has a similar mechanism. Note that the hostname is not polled if it has been provided on the command line, or if "/proc/sys/kernel/hostname" cannot be opened. Patch contributed by @tbetker Fixes #23 Signed-off-by: Tobias Klauser --- llmnr.c | 6 +++++- llmnr.h | 1 + llmnrd.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/llmnr.c b/llmnr.c index f5a3f2a..dc4b72a 100644 --- a/llmnr.c +++ b/llmnr.c @@ -42,12 +42,16 @@ static bool llmnr_ipv6 = false; /* Host name in DNS name format (length octet + name + 0 byte) */ static char llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 2]; -void llmnr_init(const char *hostname, bool ipv6) +void llmnr_set_hostname(const char *hostname) { llmnr_hostname[0] = strlen(hostname); strncpy(&llmnr_hostname[1], hostname, LLMNR_LABEL_MAX_SIZE); llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 1] = '\0'; +} +void llmnr_init(const char *hostname, bool ipv6) +{ + llmnr_set_hostname(hostname); llmnr_ipv6 = ipv6; } diff --git a/llmnr.h b/llmnr.h index 892ba24..6380ebf 100644 --- a/llmnr.h +++ b/llmnr.h @@ -21,6 +21,7 @@ #include +void llmnr_set_hostname(const char *hostname); void llmnr_init(const char *hostname, bool ipv6); void llmnr_recv(int sock); diff --git a/llmnrd.c b/llmnrd.c index 66a9f04..3853101 100644 --- a/llmnrd.c +++ b/llmnrd.c @@ -28,6 +28,10 @@ #include #include +#include +#include +#include + #include #include @@ -43,6 +47,7 @@ static bool llmnrd_running = true; static int llmnrd_sock_ipv4 = -1; static int llmnrd_sock_ipv6 = -1; +static int llmnrd_fd_hostname = -1; static const char *short_opts = "H:i:p:6dhV"; static const struct option long_opts[] = { @@ -129,6 +134,22 @@ static void iface_event_handle(enum iface_event_type type, unsigned char af, } } +static void hostname_change_handle(char *hostname, size_t maxlen) +{ + char *newname; + + newname = xzalloc(maxlen); + if (gethostname(newname, maxlen) == 0) { + newname[maxlen - 1] = '\0'; + if (strncmp(hostname, newname, maxlen) != 0) { + log_info("Hostname changed to %s\n", newname); + strncpy(hostname, newname, maxlen); + llmnr_set_hostname(hostname); + } + } + free(newname); +} + int main(int argc, char **argv) { int c, ret = -1; @@ -183,6 +204,8 @@ int main(int argc, char **argv) return EXIT_FAILURE; } hostname[MAXHOSTNAMELEN - 1] = '\0'; + + llmnrd_fd_hostname = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY); } if (daemonize) { @@ -216,10 +239,12 @@ int main(int argc, char **argv) nfds = max(llmnrd_sock_ipv4, llmnrd_sock_rtnl); if (llmnrd_sock_ipv6 >= 0) nfds = max(nfds, llmnrd_sock_ipv6); + if (llmnrd_fd_hostname >= 0) + nfds = max(nfds, llmnrd_fd_hostname); nfds += 1; while (llmnrd_running) { - fd_set rfds; + fd_set rfds, efds; FD_ZERO(&rfds); FD_SET(llmnrd_sock_ipv4, &rfds); @@ -227,7 +252,11 @@ int main(int argc, char **argv) if (llmnrd_sock_ipv6 >= 0) FD_SET(llmnrd_sock_ipv6, &rfds); - ret = select(nfds, &rfds, NULL, NULL, NULL); + FD_ZERO(&efds); + if (llmnrd_fd_hostname >= 0) + FD_SET(llmnrd_fd_hostname, &efds); + + ret = select(nfds, &rfds, NULL, &efds, NULL); if (ret < 0) { if (errno != EINTR) log_err("Failed to select() on socket: %s\n", strerror(errno)); @@ -242,6 +271,8 @@ int main(int argc, char **argv) llmnr_recv(llmnrd_sock_ipv4); if (llmnrd_sock_ipv6 >= 0 && FD_ISSET(llmnrd_sock_ipv6, &rfds)) llmnr_recv(llmnrd_sock_ipv6); + if (llmnrd_fd_hostname >= 0 && FD_ISSET(llmnrd_fd_hostname, &efds)) + hostname_change_handle(hostname, MAXHOSTNAMELEN); } } -- cgit v1.2.3-54-g00ecf