From: Ondřej Surý Date: Thu, 10 Dec 2020 09:31:31 +0000 (+0100) Subject: Print warning when falling back to increment soa serial method X-Git-Tag: v9.16.11~16^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04f9f45c541afc628072ecca92fc5ba2b5b4de1f;p=thirdparty%2Fbind9.git Print warning when falling back to increment soa serial method When using the `unixtime` or `date` method to update the SOA serial, `named` and `dnssec-signzone` would silently fallback to `increment` method to prevent the new serial number to be smaller than the old serial number (using the serial number arithmetics). Add a warning message when such fallback happens. (cherry picked from commit ef685bab5c0ce68e98328dd19dfb1fb8f9d0fdee) --- diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index c319693a2ed..e6c36ac6991 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -1351,7 +1351,8 @@ setsoaserial(uint32_t serial, dns_updatemethod_t method) { dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; - uint32_t old_serial, new_serial; + uint32_t old_serial, new_serial = 0; + dns_updatemethod_t used = dns_updatemethod_none; result = dns_db_getoriginnode(gdb, &node); if (result != ISC_R_SUCCESS) { @@ -1375,16 +1376,20 @@ setsoaserial(uint32_t serial, dns_updatemethod_t method) { if (method == dns_updatemethod_date || method == dns_updatemethod_unixtime) { - new_serial = dns_update_soaserial(old_serial, method); + new_serial = dns_update_soaserial(old_serial, method, &used); } else if (serial != 0 || method == dns_updatemethod_none) { /* Set SOA serial to the value provided. */ new_serial = serial; + used = method; } else { - /* Increment SOA serial using RFC 1982 arithmetic */ - new_serial = (old_serial + 1) & 0xFFFFFFFF; - if (new_serial == 0) { - new_serial = 1; - } + new_serial = dns_update_soaserial(old_serial, method, &used); + } + + if (method != used) { + fprintf(stderr, + "%s: warning: Serial number would not advance, " + "using increment method instead\n", + program); } /* If the new serial is not likely to cause a zone transfer diff --git a/lib/dns/include/dns/update.h b/lib/dns/include/dns/update.h index 7a816e22929..f566488e3ec 100644 --- a/lib/dns/include/dns/update.h +++ b/lib/dns/include/dns/update.h @@ -38,15 +38,23 @@ ISC_LANG_BEGINDECLS ***/ uint32_t -dns_update_soaserial(uint32_t serial, dns_updatemethod_t method); +dns_update_soaserial(uint32_t serial, dns_updatemethod_t method, + dns_updatemethod_t *used); /*%< * Return the next serial number after 'serial', depending on the * update method 'method': * *\li * dns_updatemethod_increment increments the serial number by one + *\li * dns_updatemethod_date sets the serial number to YYYYMMDD00 *\li * dns_updatemethod_unixtime sets the serial number to the current - * time (seconds since UNIX epoch) if possible, or increments by one - * if not. + * time (seconds since UNIX epoch) + *\li * dns_updatemethod_none just returns the given serial + * + * NOTE: The dns_updatemethod_increment will be used if dns_updatemethod_date or + * dns_updatemethod_unixtime is used and the new serial number would be lower + * than current serial number. + * + * Sets *used to the method that was used. */ isc_result_t diff --git a/lib/dns/tests/update_test.c b/lib/dns/tests/update_test.c index e97c750f266..bc789b2be29 100644 --- a/lib/dns/tests/update_test.c +++ b/lib/dns/tests/update_test.c @@ -111,7 +111,7 @@ increment_test(void **state) { UNUSED(state); - serial = dns_update_soaserial(old, dns_updatemethod_increment); + serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, 51); @@ -125,7 +125,7 @@ increment_past_zero_test(void **state) { UNUSED(state); - serial = dns_update_soaserial(old, dns_updatemethod_increment); + serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, 1u); @@ -142,7 +142,7 @@ past_to_unix_test(void **state) { set_mystdtime(2011, 6, 22); old = mystdtime - 1; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, mystdtime); @@ -159,7 +159,7 @@ now_to_unix_test(void **state) { set_mystdtime(2011, 6, 22); old = mystdtime; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, old + 1); @@ -176,7 +176,7 @@ future_to_unix_test(void **state) { set_mystdtime(2011, 6, 22); old = mystdtime + 1; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, old + 1); @@ -194,7 +194,7 @@ undefined_plus1_to_unix_test(void **state) { old = mystdtime ^ 0x80000000u; old += 1; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, mystdtime); @@ -212,7 +212,7 @@ undefined_minus1_to_unix_test(void **state) { old = mystdtime ^ 0x80000000u; old -= 1; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, old + 1); @@ -229,7 +229,7 @@ undefined_to_unix_test(void **state) { set_mystdtime(2011, 6, 22); old = mystdtime ^ 0x80000000u; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, old + 1); @@ -246,7 +246,7 @@ unixtime_zero_test(void **state) { mystdtime = 0; old = 0xfffffff0; - serial = dns_update_soaserial(old, dns_updatemethod_unixtime); + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, old + 1); @@ -260,10 +260,10 @@ past_to_date_test(void **state) { UNUSED(state); set_mystdtime(2014, 3, 31); - old = dns_update_soaserial(0, dns_updatemethod_date); + old = dns_update_soaserial(0, dns_updatemethod_date, NULL); set_mystdtime(2014, 4, 1); - serial = dns_update_soaserial(old, dns_updatemethod_date); + serial = dns_update_soaserial(old, dns_updatemethod_date, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); @@ -279,9 +279,9 @@ now_to_date_test(void **state) { UNUSED(state); set_mystdtime(2014, 4, 1); - old = dns_update_soaserial(0, dns_updatemethod_date); + old = dns_update_soaserial(0, dns_updatemethod_date, NULL); - serial = dns_update_soaserial(old, dns_updatemethod_date); + serial = dns_update_soaserial(old, dns_updatemethod_date, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, 2014040101); @@ -296,10 +296,10 @@ future_to_date_test(void **state) { UNUSED(state); set_mystdtime(2014, 4, 1); - old = dns_update_soaserial(0, dns_updatemethod_date); + old = dns_update_soaserial(0, dns_updatemethod_date, NULL); set_mystdtime(2014, 3, 31); - serial = dns_update_soaserial(old, dns_updatemethod_date); + serial = dns_update_soaserial(old, dns_updatemethod_date, NULL); assert_true(isc_serial_lt(old, serial)); assert_int_not_equal(serial, 0); assert_int_equal(serial, 2014040101); diff --git a/lib/dns/update.c b/lib/dns/update.c index 4a8a03c0c17..43dad7035a3 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -2204,35 +2204,55 @@ epoch_to_yyyymmdd(time_t when) { tm->tm_mday); } -uint32_t -dns_update_soaserial(uint32_t serial, dns_updatemethod_t method) { +static uint32_t +dns__update_soaserial(uint32_t serial, dns_updatemethod_t method) { isc_stdtime_t now; - uint32_t new_serial; switch (method) { case dns_updatemethod_none: return (serial); case dns_updatemethod_unixtime: isc_stdtime_get(&now); - if (now != 0 && isc_serial_gt(now, serial)) { - return (now); - } - break; + return (now); case dns_updatemethod_date: isc_stdtime_get(&now); - new_serial = epoch_to_yyyymmdd((time_t)now) * 100; - if (new_serial != 0 && isc_serial_gt(new_serial, serial)) { - return (new_serial); + return (epoch_to_yyyymmdd((time_t)now) * 100); + case dns_updatemethod_increment: + /* RFC1982 */ + serial = (serial + 1) & 0xFFFFFFFF; + if (serial == 0) { + return (1); } + return (serial); + default: + INSIST(0); + ISC_UNREACHABLE(); + } +} + +uint32_t +dns_update_soaserial(uint32_t serial, dns_updatemethod_t method, + dns_updatemethod_t *used) { + uint32_t new_serial = dns__update_soaserial(serial, method); + switch (method) { + case dns_updatemethod_none: case dns_updatemethod_increment: break; + case dns_updatemethod_unixtime: + case dns_updatemethod_date: + if (!(new_serial != 0 && isc_serial_gt(new_serial, serial))) { + method = dns_updatemethod_increment; + new_serial = dns__update_soaserial(serial, method); + } + break; + default: + INSIST(0); + ISC_UNREACHABLE(); } - /* RFC1982 */ - serial = (serial + 1) & 0xFFFFFFFF; - if (serial == 0) { - serial = 1; + if (used != NULL) { + *used = method; } - return (serial); + return (new_serial); } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index b536ae3b7a3..7b7d1f36c32 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -4305,12 +4305,14 @@ update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, } static isc_result_t -update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, - isc_mem_t *mctx, dns_updatemethod_t method) { +update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff, isc_mem_t *mctx, + dns_updatemethod_t method) { dns_difftuple_t *deltuple = NULL; dns_difftuple_t *addtuple = NULL; uint32_t serial; isc_result_t result; + dns_updatemethod_t used = dns_updatemethod_none; INSIST(method != dns_updatemethod_none); @@ -4319,7 +4321,12 @@ update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, addtuple->op = DNS_DIFFOP_ADD; serial = dns_soa_getserial(&addtuple->rdata); - serial = dns_update_soaserial(serial, method); + serial = dns_update_soaserial(serial, method, &used); + if (method != used) { + dns_zone_log(zone, ISC_LOG_WARNING, + "update_soa_serial:new serial would be lower than " + "old serial, using increment method instead"); + } dns_soa_setserial(serial, &addtuple->rdata); CHECK(do_one_tuple(&deltuple, db, ver, diff)); CHECK(do_one_tuple(&addtuple, db, ver, diff)); @@ -4576,7 +4583,7 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { result = arg.result; if (changed) { /* Write changes to journal file. */ - CHECK(update_soa_serial(db, ver, &diff, zone->mctx, + CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx, zone->updatemethod)); CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone")); @@ -7123,7 +7130,7 @@ zone_resigninc(dns_zone_t *zone) { } /* Increment SOA serial if we have made changes */ - result = update_soa_serial(db, version, zonediff.diff, zone->mctx, + result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx, zone->updatemethod); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -8831,7 +8838,7 @@ skip_removals: goto failure; } - result = update_soa_serial(db, version, zonediff.diff, zone->mctx, + result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx, zone->updatemethod); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, @@ -9574,7 +9581,7 @@ zone_sign(dns_zone_t *zone) { goto cleanup; } - result = update_soa_serial(db, version, zonediff.diff, zone->mctx, + result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx, zone->updatemethod); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, @@ -10581,7 +10588,7 @@ anchors_done: done: if (!ISC_LIST_EMPTY(diff.tuples)) { /* Write changes to journal file. */ - CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx, + CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx, zone->updatemethod)); CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done")); commit = true; @@ -10812,7 +10819,7 @@ zone_refreshkeys(dns_zone_t *zone) { } } if (!ISC_LIST_EMPTY(diff.tuples)) { - CHECK(update_soa_serial(db, ver, &diff, zone->mctx, + CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx, zone->updatemethod)); CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys")); commit = true; @@ -15961,7 +15968,8 @@ nextevent: CHECK(do_one_tuple(&soatuple, zone->rss_db, zone->rss_newver, &zone->rss_diff)); } else { - CHECK(update_soa_serial(zone->rss_db, zone->rss_newver, + CHECK(update_soa_serial(zone, zone->rss_db, + zone->rss_newver, &zone->rss_diff, zone->mctx, zone->updatemethod)); } @@ -19856,7 +19864,7 @@ zone_rekey(dns_zone_t *zone) { CHECK(clean_nsec3param(zone, db, ver, &diff)); CHECK(add_signing_records(db, zone->privatetype, ver, &diff, (newalg || fullsign))); - CHECK(update_soa_serial(db, ver, &diff, mctx, + CHECK(update_soa_serial(zone, db, ver, &diff, mctx, zone->updatemethod)); CHECK(add_chains(zone, db, ver, &diff)); CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff)); @@ -20653,7 +20661,7 @@ keydone(isc_task_t *task, isc_event_t *event) { if (!ISC_LIST_EMPTY(diff.tuples)) { /* Write changes to journal file. */ - CHECK(update_soa_serial(db, newver, &diff, zone->mctx, + CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx, zone->updatemethod)); result = dns_update_signatures(&log, zone, db, oldver, newver, @@ -20938,7 +20946,7 @@ rss_post(dns_zone_t *zone, isc_event_t *event) { * records. */ if (!ISC_LIST_EMPTY(diff.tuples)) { - CHECK(update_soa_serial(db, newver, &diff, zone->mctx, + CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx, zone->updatemethod)); result = dns_update_signatures(&log, zone, db, oldver, newver, &diff, diff --git a/lib/ns/update.c b/lib/ns/update.c index cb0ff5cd84b..277bc1b6ebb 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -1473,7 +1473,7 @@ update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, addtuple->op = DNS_DIFFOP_ADD; serial = dns_soa_getserial(&addtuple->rdata); - serial = dns_update_soaserial(serial, method); + serial = dns_update_soaserial(serial, method, NULL); dns_soa_setserial(serial, &addtuple->rdata); CHECK(do_one_tuple(&deltuple, db, ver, diff)); CHECK(do_one_tuple(&addtuple, db, ver, diff));