summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2017-02-28 11:20:49 +0100
committerTobias Klauser <tklauser@distanz.ch>2017-02-28 11:20:49 +0100
commitbba51a20374648eec948113cfe1f0cd298bbe771 (patch)
tree157dae2e808c7407118782bc0ffce5cecf4612d3
parenta90f8b45355f32376cc127a33b0d1dbed419d293 (diff)
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 <tklauser@distanz.ch>
-rw-r--r--llmnr.c6
-rw-r--r--llmnr.h1
-rw-r--r--llmnrd.c35
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 <stdbool.h>
+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 <string.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include <sys/ioctl.h>
#include <sys/param.h>
@@ -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);
}
}