From 78d9bcacb63f70a2fe77bb91b3e246a4f7c872c6 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Fri, 22 Aug 2025 12:40:00 +0200 Subject: [PATCH] - Fix #1319: [FR] zone status for Unbound auth-zones. --- daemon/remote.c | 36 ++++++++++++++++++++++++++++++------ doc/Changelog | 1 + services/authzone.c | 23 ++++++++++++++++++++++- services/authzone.h | 12 ++++++++++++ 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 07f64ac06..edf379912 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3373,7 +3373,7 @@ static void do_list_auth_zones(RES* ssl, struct auth_zones* az) { struct auth_zone* z; - char buf[LDNS_MAX_DOMAINLEN], buf2[256]; + char buf[LDNS_MAX_DOMAINLEN], buf2[256], buf3[256]; lock_rw_rdlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_rdlock(&z->lock); @@ -3382,18 +3382,41 @@ do_list_auth_zones(RES* ssl, struct auth_zones* az) snprintf(buf2, sizeof(buf2), "expired"); else { uint32_t serial = 0; - if(auth_zone_get_serial(z, &serial)) + if(auth_zone_get_serial(z, &serial)) { snprintf(buf2, sizeof(buf2), "serial %u", (unsigned)serial); - else snprintf(buf2, sizeof(buf2), "no serial"); + if(z->soa_zone_acquired != 0) { +#if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R) + char tmbuf[32]; + struct tm tm; + struct tm *tm_p; + tm_p = localtime_r( + &z->soa_zone_acquired, &tm); + if(!strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%dT%H:%M:%S", tm_p)) + snprintf(tmbuf, sizeof(tmbuf), "strftime-err-%u", (unsigned)z->soa_zone_acquired); + snprintf(buf3, sizeof(buf3), + "\t since %u %s", + (unsigned)z->soa_zone_acquired, + tmbuf); +#else + snprintf(buf3, sizeof(buf3), + "\t since %u", + (unsigned)z->soa_zone_acquired); +#endif + } else { + buf3[0]=0; + } + } else { + snprintf(buf2, sizeof(buf2), "no serial"); + buf3[0]=0; + } } - if(!ssl_printf(ssl, "%s\t%s\n", buf, buf2)) { + lock_rw_unlock(&z->lock); + if(!ssl_printf(ssl, "%s\t%s%s\n", buf, buf2, buf3)) { /* failure to print */ - lock_rw_unlock(&z->lock); lock_rw_unlock(&az->lock); return; } - lock_rw_unlock(&z->lock); } lock_rw_unlock(&az->lock); } @@ -7461,6 +7484,7 @@ fr_worker_auth_add(struct worker* worker, struct fast_reload_auth_change* item, xfr->serial = 0; } } + auth_zone_pickup_initial_zone(item->new_z, &worker->env); lock_rw_unlock(&item->new_z->lock); lock_rw_unlock(&worker->env.auth_zones->lock); lock_rw_unlock(&worker->daemon->fast_reload_thread->old_auth_zones->lock); diff --git a/doc/Changelog b/doc/Changelog index 020c89eda..0391e057f 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,7 @@ 22 August 2025: Wouter - For #1318: Fix compile warnings for DoH compile on windows. - Fix sha1 enable environment variable in test code on windows. + - Fix #1319: [FR] zone status for Unbound auth-zones. 21 August 2025: Wouter - Fix to check for extraneous command arguments for unbound-control, diff --git a/services/authzone.c b/services/authzone.c index 591a76cd9..60ccc8698 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -5024,6 +5024,7 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z, xfr->have_zone = 0; xfr->serial = 0; + xfr->soa_zone_acquired = 0; /* insert all RRs in to the zone */ /* insert the SOA only once, skip the last one */ @@ -5125,6 +5126,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z, xfr->have_zone = 0; xfr->serial = 0; + xfr->soa_zone_acquired = 0; chunk = xfr->task_transfer->chunks_first; chunk_pos = 0; @@ -5335,6 +5337,8 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env, " (or malformed RR)", xfr->task_transfer->master->host); return 0; } + z->soa_zone_acquired = *env->now; + xfr->soa_zone_acquired = *env->now; /* release xfr lock while verifying zonemd because it may have * to spawn lookups in the state machines */ @@ -7004,13 +7008,23 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env, comm_timer_set(xfr->task_nextprobe->timer, &tv); } +void auth_zone_pickup_initial_zone(struct auth_zone* z, struct module_env* env) +{ + /* Set the time, because we now have timestamp in env, + * (not earlier during startup and apply_cfg), and this + * notes the start time when the data was acquired. */ + z->soa_zone_acquired = *env->now; +} + void auth_xfer_pickup_initial_zone(struct auth_xfer* x, struct module_env* env) { /* set lease_time, because we now have timestamp in env, * (not earlier during startup and apply_cfg), and this * notes the start time when the data was acquired */ - if(x->have_zone) + if(x->have_zone) { x->lease_time = *env->now; + x->soa_zone_acquired = *env->now; + } if(x->task_nextprobe && x->task_nextprobe->worker == NULL) { xfr_set_timeout(x, env, 0, 1); } @@ -7021,7 +7035,13 @@ void auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env) { struct auth_xfer* x; + struct auth_zone* z; lock_rw_wrlock(&az->lock); + RBTREE_FOR(z, struct auth_zone*, &az->ztree) { + lock_rw_wrlock(&z->lock); + auth_zone_pickup_initial_zone(z, env); + lock_rw_unlock(&z->lock); + } RBTREE_FOR(x, struct auth_xfer*, &az->xtree) { lock_basic_lock(&x->lock); auth_xfer_pickup_initial_zone(x, env); @@ -7106,6 +7126,7 @@ auth_xfer_new(struct auth_zone* z) lock_protect(&xfr->lock, &xfr->notify_serial, sizeof(xfr->notify_serial)); lock_protect(&xfr->lock, &xfr->zone_expired, sizeof(xfr->zone_expired)); lock_protect(&xfr->lock, &xfr->have_zone, sizeof(xfr->have_zone)); + lock_protect(&xfr->lock, &xfr->soa_zone_acquired, sizeof(xfr->soa_zone_acquired)); lock_protect(&xfr->lock, &xfr->serial, sizeof(xfr->serial)); lock_protect(&xfr->lock, &xfr->retry, sizeof(xfr->retry)); lock_protect(&xfr->lock, &xfr->refresh, sizeof(xfr->refresh)); diff --git a/services/authzone.h b/services/authzone.h index b11e7f144..ceb933bbb 100644 --- a/services/authzone.h +++ b/services/authzone.h @@ -118,6 +118,8 @@ struct auth_zone { char* zonefile; /** fallback to the internet on failure or ttl-expiry of auth zone */ int fallback_enabled; + /** the time when zone was transferred from upstream */ + time_t soa_zone_acquired; /** the zone has expired (enabled by the xfer worker), fallback * happens if that option is enabled. */ int zone_expired; @@ -261,6 +263,8 @@ struct auth_xfer { int zone_expired; /** do we have a zone (if 0, no zone data at all) */ int have_zone; + /** the time when zone was transferred from upstream */ + time_t soa_zone_acquired; /** current serial (from SOA), if we have no zone, 0 */ uint32_t serial; @@ -800,6 +804,14 @@ size_t auth_zones_get_mem(struct auth_zones* zones); void auth_xfer_pickup_initial_zone(struct auth_xfer* x, struct module_env* env); +/** + * Initial pick up of the auth zone, it sets the acquired time. + * @param z: the zone, locked by caller. + * @param env: environment of the worker, with current time. + */ +void auth_zone_pickup_initial_zone(struct auth_zone* z, + struct module_env* env); + /** * Delete auth xfer structure * @param xfr: delete this xfer and its tasks. -- 2.47.3