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. diff -Naur llmnrd-0.4-orig/llmnr.c llmnrd-0.4/llmnr.c --- llmnrd-0.4-orig/llmnr.c 2017-02-10 08:33:42.000000000 +0000 +++ llmnrd-0.4/llmnr.c 2017-02-27 14:08:15.330531281 +0000 @@ -51,6 +51,13 @@ llmnr_ipv6 = 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'; +} + static bool llmnr_name_matches(const uint8_t *query) { uint8_t n = llmnr_hostname[0]; diff -Naur llmnrd-0.4-orig/llmnr.h llmnrd-0.4/llmnr.h --- llmnrd-0.4-orig/llmnr.h 2017-02-10 08:33:42.000000000 +0000 +++ llmnrd-0.4/llmnr.h 2017-02-27 14:06:22.125065973 +0000 @@ -22,6 +22,7 @@ #include void llmnr_init(const char *hostname, bool ipv6); +void llmnr_set_hostname(const char *hostname); void llmnr_recv(int sock); #endif /* LLMNR_H */ diff -Naur llmnrd-0.4-orig/llmnrd.c llmnrd-0.4/llmnrd.c --- llmnrd-0.4-orig/llmnrd.c 2017-02-10 08:33:42.000000000 +0000 +++ llmnrd-0.4/llmnrd.c 2017-02-27 14:57:25.968718661 +0000 @@ -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 hostname_change_handle(char *hostname, int maxlen) +{ + char *newname; + + newname = xzalloc(maxlen); + if (gethostname(newname, maxlen) == 0) { + newname[maxlen - 1] = '\0'; + if (strcmp(hostname, newname) != 0) { + log_info("Hostname changed to %s\n", newname); + strcpy(hostname, newname); + llmnr_set_hostname(hostname); + } + } + free(newname); +} + int main(int argc, char **argv) { int c, ret = -1; @@ -183,6 +204,8 @@ 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 @@ 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 @@ 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)); @@ -240,6 +269,8 @@ iface_recv(llmnrd_sock_rtnl); if (FD_ISSET(llmnrd_sock_ipv4, &rfds)) llmnr_recv(llmnrd_sock_ipv4); + if (llmnrd_fd_hostname >= 0 && FD_ISSET(llmnrd_fd_hostname, &efds)) + hostname_change_handle(hostname, MAXHOSTNAMELEN); if (llmnrd_sock_ipv6 >= 0 && FD_ISSET(llmnrd_sock_ipv6, &rfds)) llmnr_recv(llmnrd_sock_ipv6); }