From: Libor Peltan Date: Wed, 31 Dec 2025 22:09:02 +0000 (+0100) Subject: zone/events: dont send NOTIFY before server starts answering X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=657eda94644e9c603aa09173c3017230f6cb14ec;p=thirdparty%2Fknot-dns.git zone/events: dont send NOTIFY before server starts answering --- diff --git a/src/knot/events/events.c b/src/knot/events/events.c index d93af62ce5..70c0cb08ec 100644 --- a/src/knot/events/events.c +++ b/src/knot/events/events.c @@ -132,7 +132,8 @@ static zone_event_type_t get_next_event(zone_events_t *events) time_t current = events->time[i]; if ((next == 0 || current < next) && (current != 0) && - (events->forced[i] || !events->ufrozen || !ufreeze_applies(i))) { + (events->forced[i] || !events->ufrozen || !ufreeze_applies(i)) && + (events->answering || !only_started(i))) { next = current; next_type = i; } @@ -489,6 +490,13 @@ void zone_events_freeze_blocking(zone_t *zone) pthread_cond_destroy(&cond); } +void zone_events_start_answering(zone_t *zone) +{ + pthread_mutex_lock(&zone->events.mx); + zone->events.answering = true; + reschedule(&zone->events, true); // unlocks events->mx +} + void zone_events_start(zone_t *zone) { if (!zone) { @@ -502,7 +510,7 @@ void zone_events_start(zone_t *zone) pthread_mutex_lock(&events->mx); events->frozen = false; - reschedule(events, true); //unlocks events->mx + reschedule(events, true); // unlocks events->mx } time_t zone_events_get_time(const struct zone *zone, zone_event_type_t type) diff --git a/src/knot/events/events.h b/src/knot/events/events.h index 49bba840f7..7e75d691be 100644 --- a/src/knot/events/events.h +++ b/src/knot/events/events.h @@ -48,6 +48,7 @@ typedef struct zone_events { bool frozen; //!< Terminated, don't schedule new events. bool ufrozen; //!< Updates to the zone temporarily frozen by user. + bool answering; //!< Server is answering. event_t *event; //!< Scheduler event. worker_pool_t *pool; //!< Server worker pool. @@ -159,6 +160,11 @@ void zone_events_freeze(struct zone *zone); */ void zone_events_freeze_blocking(struct zone *zone); +/*! + * \brief Set "answering" bit to true. + */ +void zone_events_start_answering(struct zone *zone); + /*! * \brief ufreeze_applies * \param type Type of event to be checked @@ -166,6 +172,14 @@ void zone_events_freeze_blocking(struct zone *zone); */ bool ufreeze_applies(zone_event_type_t type); +/*! + * \brief Events that require answering server. + */ +inline static bool only_started(zone_event_type_t type) +{ + return type == ZONE_EVENT_NOTIFY; +} + /*! * \brief Start the events processing. * diff --git a/src/knot/server/server.c b/src/knot/server/server.c index 6ff377b20a..07d3011dca 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -1213,6 +1213,8 @@ int server_start_answering(server_t *server) } } + knot_zonedb_foreach(server->zone_db, zone_events_start_answering); + return KNOT_EOK; } diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c index 46140faba7..b2cf094294 100644 --- a/src/knot/zone/zonedb-load.c +++ b/src/knot/zone/zonedb-load.c @@ -67,6 +67,7 @@ static zone_t *create_zone_from(const knot_dname_t *name, server_t *server) zone_free(&zone); return NULL; } + zone->events.answering = (server->state & ServerAnswering); return zone; } diff --git a/tests-extra/tests/notify/too_early/test.py b/tests-extra/tests/notify/too_early/test.py new file mode 100644 index 0000000000..18e4eebb7f --- /dev/null +++ b/tests-extra/tests/notify/too_early/test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +'''Test that NOTIFY is not sent before server is answering (on XFR).''' + +from dnstest.test import Test + +t = Test() + +master = t.server("knot") +slave = t.server("knot") + +zones = t.zone_rnd(1, records=1200, names=["zzzzzzzzz."]) + t.zone("example.") + +t.link(zones, master, slave) + +master.dnssec(zones[0]).enable = True +slave.conf_zone(zones).retry_min_interval = 300 + +t.generate_conf() +slave.start() +master.start() + +serials = master.zones_wait(zones) +slave.zones_wait(zones) + +t.end() diff --git a/tests-extra/tools/dnstest/test.py b/tests-extra/tools/dnstest/test.py index a0262c890f..0facf6063c 100644 --- a/tests-extra/tools/dnstest/test.py +++ b/tests-extra/tools/dnstest/test.py @@ -384,11 +384,12 @@ class Test(object): return [zone] def zone_rnd(self, number, dnssec=None, nsec3=None, records=None, serial=None, - ttl=None, exists=True): + ttl=None, exists=True, names=None): zones = list() # Generate unique zone names. - names = zone_generate.main(["-n", number]).split() + if names is None: + names = zone_generate.main(["-n", number]).split() for name in names: zone = dnstest.zonefile.ZoneFile(self.zones_dir) zone.set_name(name)