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) {
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
***/
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
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
}
}
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);
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));
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"));
}
/* 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,
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,
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,
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;
}
}
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;
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));
}
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));
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,
* 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,
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));