Skip to content

Commit

Permalink
dhcpv6-ia: make tmp lease file hidden
Browse files Browse the repository at this point in the history
Use a hidden . prefixed temporary lease file instead of appending
'.tmp'.  Dnsmasq is capable of scanning files/directories using inotify
to receive file change notifications and updating its view of hostname
ip address mapping without being SIGHUPped.  Until dnsmasq v2.88 this
mechanism allows additions to hostnames, no deletions.  dnsmasq v2.88
when released will understand how to remove mappings.

Unfortunately without this change dnsmasq sees odhcpd's temporary lease
file via inotify and it also sees the change when odhcpd atomically
renames the file from '.tmp' to the correct name.

dnsmasq excludes hidden '.' files from it's inotify scans, thus changing
odhcpd to use a hidden temporary lease file reduces load and makes
sense.

Also, while here, only rename the temporary file if it actually contains
different content.

Signed-off-by: Kevin Darbyshire-Bryant <[email protected]>
  • Loading branch information
ldir-EDB0 authored and dedeckeh committed Oct 24, 2022
1 parent 4a673e1 commit a92c0a7
Showing 1 changed file with 33 additions and 12 deletions.
45 changes: 33 additions & 12 deletions src/dhcpv6-ia.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/timerfd.h>
Expand Down Expand Up @@ -320,13 +321,29 @@ void dhcpv6_ia_write_statefile(void)
md5_begin(&ctxt.md5);

if (config.dhcp_statefile) {
unsigned tmp_statefile_strlen = strlen(config.dhcp_statefile) + strlen(".tmp") + 1;
unsigned statefile_strlen = strlen(config.dhcp_statefile) + 1;
unsigned tmp_statefile_strlen = statefile_strlen + 1; /* space for . */
char *tmp_statefile = alloca(tmp_statefile_strlen);

char *dir_statefile;
char *base_statefile;
char *pdir_statefile;
char *pbase_statefile;

time_t now = odhcpd_time(), wall_time = time(NULL);
int fd, ret;
char leasebuf[512];

snprintf(tmp_statefile, tmp_statefile_strlen, "%s.tmp", config.dhcp_statefile);
dir_statefile = strndup(config.dhcp_statefile, statefile_strlen);
base_statefile = strndup(config.dhcp_statefile, statefile_strlen);

pdir_statefile = dirname(dir_statefile);
pbase_statefile = basename(base_statefile);

snprintf(tmp_statefile, tmp_statefile_strlen, "%s/.%s", pdir_statefile, pbase_statefile);

free(dir_statefile);
free(base_statefile);

fd = open(tmp_statefile, O_CREAT | O_WRONLY | O_CLOEXEC, 0644);
if (fd < 0)
Expand Down Expand Up @@ -437,18 +454,22 @@ void dhcpv6_ia_write_statefile(void)

fclose(ctxt.fp);

rename(tmp_statefile, config.dhcp_statefile);
}
uint8_t newmd5[16];
md5_end(newmd5, &ctxt.md5);

uint8_t newmd5[16];
md5_end(newmd5, &ctxt.md5);
if (memcmp(newmd5, statemd5, sizeof(newmd5))) {
memcpy(statemd5, newmd5, sizeof(statemd5));
rename(tmp_statefile, config.dhcp_statefile);

if (config.dhcp_cb && memcmp(newmd5, statemd5, sizeof(newmd5))) {
memcpy(statemd5, newmd5, sizeof(statemd5));
char *argv[2] = {config.dhcp_cb, NULL};
if (!vfork()) {
execv(argv[0], argv);
_exit(128);
if (config.dhcp_cb) {
char *argv[2] = {config.dhcp_cb, NULL};
if (!vfork()) {
execv(argv[0], argv);
_exit(128);
}
}
} else {
unlink(tmp_statefile);
}
}
}
Expand Down

0 comments on commit a92c0a7

Please sign in to comment.