Skip to content

Commit

Permalink
Add support for reloading configuration on SIGHUP
Browse files Browse the repository at this point in the history
Fixes #323.
  • Loading branch information
k0ekk0ek committed Aug 9, 2024
1 parent b4a5ccd commit 253f17c
Show file tree
Hide file tree
Showing 17 changed files with 186 additions and 1 deletion.
1 change: 1 addition & 0 deletions configlexer.lex
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ rrl-ipv4-prefix-length{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV4_
rrl-ipv6-prefix-length{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV6_PREFIX_LENGTH;}
rrl-whitelist-ratelimit{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST_RATELIMIT;}
rrl-whitelist{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST;}
reload-config{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RELOAD_CONFIG; }
zonefiles-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_CHECK;}
zonefiles-write{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_WRITE;}
dnstap{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP;}
Expand Down
3 changes: 3 additions & 0 deletions configparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ struct component {
%token VAR_MINIMAL_RESPONSES
%token VAR_CONFINE_TO_ZONE
%token VAR_REFUSE_ANY
%token VAR_RELOAD_CONFIG
%token VAR_ZONEFILES_CHECK
%token VAR_ZONEFILES_WRITE
%token VAR_RRL_SIZE
Expand Down Expand Up @@ -445,6 +446,8 @@ server_option:
cfg_parser->opt->rrl_whitelist_ratelimit = (size_t)$2;
#endif
}
| VAR_RELOAD_CONFIG boolean
{ cfg_parser->opt->reload_config = $2; }
| VAR_ZONEFILES_CHECK boolean
{ cfg_parser->opt->zonefiles_check = $2; }
| VAR_ZONEFILES_WRITE number
Expand Down
4 changes: 4 additions & 0 deletions nsd.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ the response with one RRset. Popular and not large types, like A, AAAA and
MX are preferred, and large types, like DNSKEY and RRSIG are picked with a
lower preference than other types. This makes the response smaller.
.TP
.B reload\-config:\fR <yes or no>
Reload configuration file and update TSIG keys and zones on SIGHUP.
Default is no.
.B zonefiles\-check:\fR <yes or no>
Make NSD check the mtime of zone files on start and sighup. If you
disable it it starts faster (less disk activity in case of a lot of zones).
Expand All @@ -468,6 +471,7 @@ regardless of this option.
Write updated secondary zones to their zonefile every N seconds. If the
zone or pattern's "zonefile" option is set to "" (empty string), no zonefile
is written. The default is 3600 (1 hour).
.TP
.\" rrlstart
.TP
.B rrl\-size:\fR <numbuckets>
Expand Down
3 changes: 3 additions & 0 deletions nsd.conf.sample.in
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ server:
# default is 3600.
# zonefiles-write: 3600

# Reload nsd.conf and update TSIG keys and zones on SIGHUP.
# reload-config: no

# RRLconfig
# Response Rate Limiting, size of the hashtable. Default 1000000.
# rrl-size: 1000000
Expand Down
1 change: 1 addition & 0 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ nsd_options_create(region_type* region)
opt->dnstap_log_auth_query_messages = 0;
opt->dnstap_log_auth_response_messages = 0;
#endif
opt->reload_config = 0;
opt->zonefiles_check = 1;
opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL;
opt->xfrd_reload_timeout = 1;
Expand Down
1 change: 1 addition & 0 deletions options.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ struct nsd_options {
const char* zonelistfile;
const char* nsid;
int xfrd_reload_timeout;
int reload_config;
int zonefiles_check;
int zonefiles_write;
int log_time_ascii;
Expand Down
42 changes: 41 additions & 1 deletion remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
#else
# include "mini_event.h"
#endif
#include "remote.h"
#include "util.h"
#include "xfrd.h"
#include "xfrd-catalog-zones.h"
Expand All @@ -81,6 +80,7 @@
#include "options.h"
#include "difffile.h"
#include "ipc.h"
#include "remote.h"

#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
Expand Down Expand Up @@ -2038,6 +2038,46 @@ do_repattern(RES* ssl, xfrd_state_type* xfrd)
region_destroy(region);
}

static void print_cfg_err(void *unused, const char *message)
{
(void)unused;
log_msg(LOG_ERR, "%s", message);
}

/* mostly identical to do_repattern */
void xfrd_reload_config(xfrd_state_type *xfrd)
{
const char *chrootdir = xfrd->nsd->chrootdir;
const char *file = xfrd->nsd->options->configfile;

if (chrootdir && !file_inside_chroot(file, chrootdir))
{
log_msg(LOG_ERR, "%s is not relative to %s: %s",
xfrd->nsd->options->configfile, xfrd->nsd->chrootdir,
"chroot prevents reread of config");
goto error_chroot;
}

region_type *region = region_create(xalloc, free);
struct nsd_options *options = nsd_options_create(region);

if (!parse_options_file(
options, file, print_cfg_err, NULL, xfrd->nsd->options))
{
goto error_parse;
}

repat_keys(xfrd, options);
repat_patterns(xfrd, options); /* adds/deletes zones too */
repat_options(xfrd, options);
zonestat_inc_ifneeded(xfrd);

error_parse:
region_destroy(region);
error_chroot:
return;
}

/** do the serverpid command: printout pid of server process */
static void
do_serverpid(RES* ssl, xfrd_state_type* xfrd)
Expand Down
2 changes: 2 additions & 0 deletions remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@ void daemon_remote_attach(struct daemon_remote* rc, struct xfrd_state* xfrd);
*/
int create_local_accept_sock(const char* path, int* noproto);

void xfrd_reload_config(struct xfrd_state *xfrd);

#endif /* DAEMON_REMOTE_H */
4 changes: 4 additions & 0 deletions tpkg/reload-config.tdir/example.com.zone
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@ IN SOA ns1.example.com. hostmaster 2024080900 1800 900 604800 86400
IN NS ns1.example.com.
IN NS ns2.example.com.
IN A 192.0.2.1
4 changes: 4 additions & 0 deletions tpkg/reload-config.tdir/example.net.zone
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@ IN SOA ns1.example.net. hostmaster 2024090900 1800 900 604800 86400
IN NS ns1.example.net.
IN NS ns2.example.net.
IN A 192.0.2.2
13 changes: 13 additions & 0 deletions tpkg/reload-config.tdir/reload-config.1.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
server:
xfrdfile: "xfrd.state"
logfile: "/dev/stderr"
zonesdir: ""
username: ""
chroot: ""
verbosity: 1
ip-address: 127.0.0.1
reload-config: yes

zone:
name: example.com
zonefile: example.com.zone
17 changes: 17 additions & 0 deletions tpkg/reload-config.tdir/reload-config.2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
server:
xfrdfile: "xfrd.state"
logfile: "/dev/stderr"
zonesdir: ""
username: ""
chroot: ""
verbosity: 1
ip-address: 127.0.0.1
reload-config: yes

zone:
name: example.com
zonefile: example.com.zone

zone:
name: example.net
zonefile: example.net.zone
16 changes: 16 additions & 0 deletions tpkg/reload-config.tdir/reload-config.dsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
BaseName: reload-config
Version: 1.0
Description: Test reread of nsd.conf on SIGHUP
CreationDate: Fri Aug 9 13:47:00 CEST 2024
Maintainer: Jeroen Koekkoek
Category:
Component:
CmdDepends:
Depends: 0000_nsd-compile.tpkg
Help:
Pre: reload-config.pre
Post: reload-config.post
Test: reload-config.test
AuxFiles:
Passed:
Failure:
19 changes: 19 additions & 0 deletions tpkg/reload-config.tdir/reload-config.post
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# #-- reload-config.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
. ../common.sh

cat nsd.log

rm -f nsd.log
rm -f xfrd.state
rm -f nsd.zonelist

if test -f $NSD_PID; then
# the test must have failed
kill_pid `cat $NSD_PID`
fi
16 changes: 16 additions & 0 deletions tpkg/reload-config.tdir/reload-config.pre
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# #-- reload-config.pre --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh

# start NSD
get_random_port 1
NSD_PORT=$RND_PORT

NSD_PID="nsd.pid.$$"

# share the vars
echo "export NSD_PORT=$NSD_PORT" >> .tpkg.var.test
echo "export NSD_PID=$NSD_PID" >> .tpkg.var.test
37 changes: 37 additions & 0 deletions tpkg/reload-config.tdir/reload-config.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# #-- reload-config.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh

NSD="../../nsd"

cp reload-config.1.conf nsd.conf
$NSD -p $NSD_PORT -P $NSD_PID -V 5 -c nsd.conf > nsd.log 2>&1
wait_nsd_up nsd.log

dig @127.0.0.1 -p $NSD_PORT example.com. SOA | tee result
if ! grep hostmaster.example.com result; then
echo "zone example.com should be available" >&2
exit 1
fi

dig @127.0.0.1 -p $NSD_PORT example.net. SOA | tee result
if grep hostmaster.example.net result; then
echo "zone example.net should not be available" >&2
exit 1
fi

cp reload-config.2.conf nsd.conf
kill -SIGHUP $(head -n1 ${NSD_PID})

wait_logfile nsd.log "zone example.net read"

dig @127.0.0.1 -p $NSD_PORT example.net. SOA | tee result
if ! grep hostmaster.example.net result; then
echo "zone example.net should be available" >&2
exit 1
fi

exit 0
4 changes: 4 additions & 0 deletions xfrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ xfrd_sig_process(void)
} else if(xfrd->nsd->signal_hint_reload_hup) {
log_msg(LOG_WARNING, "SIGHUP received, reloading...");
xfrd->nsd->signal_hint_reload_hup = 0;
if(xfrd->nsd->options->reload_config) {
xfrd_reload_config(xfrd);
}
if(xfrd->nsd->options->zonefiles_check) {
task_new_check_zonefiles(xfrd->nsd->task[
xfrd->nsd->mytask], xfrd->last_task, NULL);
Expand Down Expand Up @@ -316,6 +319,7 @@ xfrd_main(void)
xfrd->shutdown = 0;
while(!xfrd->shutdown)
{
/* xfrd_sig_process takes care of reading zones on SIGHUP */
xfrd_process_catalog_producer_zones();
xfrd_process_catalog_consumer_zones();
/* process activated zones before blocking in select again */
Expand Down

0 comments on commit 253f17c

Please sign in to comment.