Skip to content

Commit

Permalink
Track $INCLUDE dependencies
Browse files Browse the repository at this point in the history
Fixes #57.
  • Loading branch information
k0ekk0ek committed Oct 23, 2024
1 parent c75cab0 commit fb13c69
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 21 deletions.
69 changes: 54 additions & 15 deletions dbaccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ namedb_zone_create(namedb_type* db, const dname_type* dname,
zone->opts = zo;
zone->ixfr = NULL;
zone->filename = NULL;
zone->includes.count = 0;
zone->includes.paths = NULL;
zone->logstr = NULL;
zone->mtime.tv_sec = 0;
zone->mtime.tv_nsec = 0;
Expand All @@ -89,6 +91,34 @@ namedb_zone_create(namedb_type* db, const dname_type* dname,
return zone;
}

void
namedb_zone_free_filenames(namedb_type *db, zone_type* zone)
{
assert(!zone->includes.paths == !zone->includes.count);

if (zone->filename) {
region_recycle(
db->region, zone->filename, strlen(zone->filename) + 1);
zone->filename = NULL;
}

if (zone->includes.count) {
for (size_t i=0; i < zone->includes.count; i++) {
region_recycle(
db->region,
zone->includes.paths[i],
strlen(zone->includes.paths[i]) + 1);
}

region_recycle(
db->region,
zone->includes.paths,
zone->includes.count * sizeof(*zone->includes.paths));
zone->includes.count = 0;
zone->includes.paths = NULL;
}
}

void
namedb_zone_delete(namedb_type* db, zone_type* zone)
{
Expand Down Expand Up @@ -119,9 +149,7 @@ namedb_zone_delete(namedb_type* db, zone_type* zone)
hash_tree_delete(db->region, zone->dshashtree);
#endif
zone_ixfr_free(zone->ixfr);
if(zone->filename)
region_recycle(db->region, zone->filename,
strlen(zone->filename)+1);
namedb_zone_free_filenames(db, zone);
if(zone->logstr)
region_recycle(db->region, zone->logstr,
strlen(zone->logstr)+1);
Expand Down Expand Up @@ -236,12 +264,27 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
/* if zone_fname, then the file was acquired from reading it,
* and see if filename changed or mtime newer to read it */
} else if(zone_fname && strcmp(zone_fname, fname) == 0 &&
timespec_compare(&zone_mtime, &mtime) == 0) {
VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
fname));
return;
timespec_compare(&zone_mtime, &mtime) == 0) {
int changed = 0;
struct timespec include_mtime;
/* one of the includes may have been deleted, changed, etc */
for (size_t i=0; i < zone->includes.count; i++) {
if (!file_get_mtime(zone->includes.paths[i], &include_mtime, &nonexist)) {
changed = 1;
} else if (timespec_compare(&zone_mtime, &include_mtime) < 0) {
mtime = include_mtime;
changed = 1;
}
}

if (!changed) {
VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
fname));
return;
}
}
}

if(ixfr_create_from_difference(zone, fname,
&ixfr_create_already_done)) {
ixfrcr = ixfr_create_start(zone, fname,
Expand All @@ -252,6 +295,9 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
}
}

namedb_zone_free_filenames(nsd->db, zone);
zone->filename = region_strdup(nsd->db->region, fname);

/* wipe zone from memory */
#ifdef NSEC3
nsec3_clear_precompile(nsd->db, zone);
Expand All @@ -271,10 +317,7 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
zone->nsec3_param = NULL;
#endif
delete_zone_rrs(nsd->db, zone);
if(zone->filename)
region_recycle(nsd->db->region, zone->filename,
strlen(zone->filename)+1);
zone->filename = NULL;
namedb_zone_free_filenames(nsd->db, zone);
if(zone->logstr)
region_recycle(nsd->db->region, zone->logstr,
strlen(zone->logstr)+1);
Expand All @@ -286,10 +329,6 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
zone->is_changed = 0;
/* store zone into udb */
zone->mtime = mtime;
if(zone->filename)
region_recycle(nsd->db->region, zone->filename,
strlen(zone->filename)+1);
zone->filename = region_strdup(nsd->db->region, fname);
if(zone->logstr)
region_recycle(nsd->db->region, zone->logstr,
strlen(zone->logstr)+1);
Expand Down
5 changes: 1 addition & 4 deletions difffile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1396,10 +1396,7 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_type* zone, FILE* in,
region_recycle(nsd->db->region, zone->logstr,
strlen(zone->logstr)+1);
zone->logstr = region_strdup(nsd->db->region, log_buf);
if(zone->filename)
region_recycle(nsd->db->region, zone->filename,
strlen(zone->filename)+1);
zone->filename = NULL;
namedb_zone_free_filenames(nsd->db, zone);
if(softfail && taskudb && !is_axfr) {
log_msg(LOG_ERR, "Failed to apply IXFR cleanly "
"(deletes nonexistent RRs, adds existing RRs). "
Expand Down
3 changes: 3 additions & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
format.
- Fix to initialize log_time_iso value in options.

23 August 2024: Jeroen
- Fix #57: Track $INCLUDEs in zone files

23 August 2024: Wouter
- Merge #376: Point the user towards tcpdump for logging individual
queries.
Expand Down
2 changes: 2 additions & 0 deletions doc/RELNOTES
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ FEATURES:
- Fix #383: log timestamps in ISO8601 format with timezone.
This adds the option `log-time-iso: yes` that logs in ISO8601
format.

BUG FIXES:
- Fix title underline and declaration after statement warnings.
- Add cross platform freebsd, openbsd and netbsd to github ci.
Expand All @@ -15,6 +16,7 @@ BUG FIXES:
prepended to fix detection.
- Merge #376: Point the user towards tcpdump for logging individual
queries.
- Track $INCLUDEs in zone files.
- Fix ci to update macos-12 to the macos-15 runner image.
- Merge #391: Update copyright lines (in version output).

Expand Down
8 changes: 7 additions & 1 deletion namedb.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ struct zone
#endif
struct zone_options* opts;
struct zone_ixfr* ixfr;
char* filename; /* set if read from file, which file */
char *filename; /* set if read from file, which files */
/* list of include files to monitor for changes */
struct {
size_t count;
char **paths;
} includes;
char* logstr; /* set for zone xfer, the log string */
struct timespec mtime; /* time of last modification */
unsigned zonestatid; /* array index for zone stats */
Expand Down Expand Up @@ -400,6 +405,7 @@ namedb_find_or_create_zone(namedb_type *db, const dname_type *dname,
struct zone_options* zopt)
{ zone_type* zone = namedb_find_zone(db, dname);
return zone ? zone : namedb_zone_create(db, dname, zopt); }
void namedb_zone_free_filenames(namedb_type* db, zone_type* zone);
void namedb_zone_delete(namedb_type* db, zone_type* zone);
void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
Expand Down
2 changes: 1 addition & 1 deletion simdzone
14 changes: 14 additions & 0 deletions tpkg/includes.tdir/includes.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
server:
zonesdir: ""
username: ""
chroot: ""
pidfile: nsd.pid
logfile: nsd.log
xfrdfile: nsd.xfrd
zonelistfile: "zone.list"
interface: 127.0.0.1
zonefiles-check: yes

zone:
name: example.com
zonefile: example.com
15 changes: 15 additions & 0 deletions tpkg/includes.tdir/includes.dsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
BaseName: includes
Version: 1.0
Description: Test for tracking include dependencies
CreationDate: Fri Aug 23 9:47:00 CET 2024
Maintainer: Jeroen Koekkoek
Category:
Component:
Depends:
Help:
Pre:
Post:
Test: includes.test
AuxFiles: includes.conf
Passed:
Failure:
60 changes: 60 additions & 0 deletions tpkg/includes.tdir/includes.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/bash
# #-- includes.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
get_random_port 1

# start NSD
PRE="../.."
NSD="$PRE/nsd"

example_com="
\$ORIGIN example.com.
\$INCLUDE example.com.soa
\$INCLUDE example.com.data
"

soa="@ IN SOA ns hostmaster 2024082300 6h 2h 7h 1h"

data="\$INCLUDE example.com.hosts"

hosts="www A 192.0.2.2"

echo "$example_com" > example.com
echo "$soa" > example.com.soa
echo "$data" > example.com.data
echo "$hosts" > example.com.hosts

$NSD -c includes.conf -p $RND_PORT
wait_nsd_up nsd.log
dig @127.0.0.1 -p $RND_PORT www.example.com
if dig @127.0.0.1 -p $RND_PORT www.example.com A | grep 192.0.2.2; then
echo "started successfully"
else
cat nsd.log
echo "failed to start"
kill_from_pidfile nsd.pid
exit 1
fi

hosts="www A 192.0.2.3"
echo "$hosts" > example.com.hosts
kill -1 `cat nsd.pid`

wait_logfile nsd.log "SIGHUP received, reloading..."
sleep 1
dig @127.0.0.1 -p $RND_PORT www.example.com
if dig @127.0.0.1 -p $RND_PORT www.example.com A | grep 192.0.2.3; then
echo "reloaded successfully"
else
cat nsd.log
echo "failed to reload"
kill_from_pidfile nsd.pid
exit 1
fi

kill_from_pidfile nsd.pid
rm -f example.com example.com.soa example.com.data example.com.hosts
38 changes: 38 additions & 0 deletions zonec.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,43 @@ int32_t zonec_accept(
return 0;
}

static int32_t zonec_include(
zone_parser_t *parser,
const char *file,
const char *path,
void *user_data)
{
char **paths;
struct zonec_state *state;
struct namedb *database;
struct zone *zone;

(void)parser;
(void)file;

state = (struct zonec_state *)user_data;
database = state->database;
zone = state->zone;

assert((zone->includes.count == 0) == (zone->includes.paths == NULL));

for (size_t i=0; i < zone->includes.count; i++)
if (strcmp(path, zone->includes.paths[i]) == 0)
return 0;

paths = region_alloc_array(
database->region, zone->includes.count + 1, sizeof(*paths));
if (zone->includes.count) {
const size_t size = zone->includes.count * sizeof(*paths);
memcpy(paths, zone->includes.paths, size);
region_recycle(database->region, zone->includes.paths, size);
}
paths[zone->includes.count] = region_strdup(database->region, path);
zone->includes.count++;
zone->includes.paths = paths;
return 0;
}

static void zonec_log(
zone_parser_t *parser,
uint32_t category,
Expand Down Expand Up @@ -395,6 +432,7 @@ zonec_read(
options.pretty_ttls = true; /* non-standard, for backwards compatibility */
options.log.callback = &zonec_log;
options.accept.callback = &zonec_accept;
options.include.callback = &zonec_include;

/* Parse and process all RRs. */
if (zone_parse(&parser, &options, &buffers, zonefile, &state) != 0) {
Expand Down

0 comments on commit fb13c69

Please sign in to comment.