isc_boolean_t first = ISC_TRUE;
isc_boolean_t list = ISC_FALSE, clear = ISC_FALSE;
isc_boolean_t chain = ISC_FALSE;
+ isc_boolean_t setserial = ISC_FALSE;
+ isc_uint32_t serial = 0;
char keystr[DNS_SECALG_FORMATSIZE + 7];
unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0;
unsigned char salt[255];
saltlen = isc_buffer_usedlength(&buf);
}
}
+ } else if (strcasecmp(ptr, "-serial") == 0) {
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+ CHECK(isc_parse_uint32(&serial, ptr, 10));
+ setserial = ISC_TRUE;
} else
CHECK(DNS_R_SYNTAX);
(isc_uint8_t)flags, iter,
(isc_uint8_t)saltlen, salt,
ISC_TRUE));
- putstr(text, "request queued");
+ putstr(text, "nsec3param request queued");
+ putnull(text);
+ } else if (setserial) {
+ CHECK(dns_zone_setserial(zone, serial));
+ putstr(text, "serial request queued");
putnull(text);
} else if (list) {
privatetype = dns_zone_getprivatetype(zone);
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+n=`expr $n + 1`
+echo "I:testing updating inline secure serial via 'rndc signing -serial' ($n)"
+ret=0
+$DIG nsec3. SOA -p 5300 @10.53.0.3 > dig.out.n3.pre.test$n
+newserial=`awk '$4 == "SOA" { print $7 + 10}' dig.out.n3.pre.test$n`
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1
+sleep 1
+$DIG nsec3. SOA -p 5300 @10.53.0.3 > dig.out.ns3.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n`
+[ ${newserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:testing updating inline secure serial via 'rndc signing -serial' with negative change ($n)"
+ret=0
+$DIG nsec3. SOA -p 5300 @10.53.0.3 > dig.out.n3.pre.test$n
+oldserial=`awk '$4 == "SOA" { print $7 }' dig.out.n3.pre.test$n`
+newserial=`awk '$4 == "SOA" { print $7 - 10}' dig.out.n3.pre.test$n`
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1
+sleep 1
+$DIG nsec3. SOA -p 5300 @10.53.0.3 > dig.out.ns3.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n`
+[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+#
+# Freezing only operates on the raw zone.
+#
+n=`expr $n + 1`
+echo "I:testing updating inline secure serial via 'rndc signing -serial' when frozen ($n)"
+ret=0
+$DIG nsec3. SOA -p 5300 @10.53.0.3 > dig.out.n3.pre.test$n
+oldserial=`awk '$4 == "SOA" { print $7 }' dig.out.n3.pre.test$n`
+newserial=`awk '$4 == "SOA" { print $7 + 10}' dig.out.n3.pre.test$n`
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 freeze nsec3 > /dev/null 2>&1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -serial ${newserial:-0} nsec3 > /dev/null 2>&1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 thaw nsec3 > /dev/null 2>&1
+sleep 1
+$DIG nsec3. SOA -p 5300 @10.53.0.3 > dig.out.ns3.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n`
+[ ${newserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo "I:testing updating dynamic serial via 'rndc signing -serial' ($n)"
+ret=0
+$DIG bits. SOA -p 5300 @10.53.0.2 > dig.out.ns2.pre.test$n
+newserial=`awk '$4 == "SOA" { print $7 + 10}' dig.out.ns2.pre.test$n`
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 signing -serial ${newserial:-0} bits > /dev/null 2>&1
+sleep 1
+$DIG bits. SOA -p 5300 @10.53.0.2 > dig.out.ns2.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.post.test$n`
+[ ${newserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:testing updating dynamic serial via 'rndc signing -serial' with negative change ($n)"
+ret=0
+$DIG bits. SOA -p 5300 @10.53.0.2 > dig.out.ns2.pre.test$n
+oldserial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.pre.test$n`
+newserial=`awk '$4 == "SOA" { print $7 - 10}' dig.out.ns2.pre.test$n`
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 signing -serial ${newserial:-0} bits > /dev/null 2>&1
+sleep 1
+$DIG bits. SOA -p 5300 @10.53.0.2 > dig.out.ns2.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.post.test$n`
+[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:testing updating dynamic serial via 'rndc signing -serial' when frozen ($n)"
+ret=0
+$DIG bits. SOA -p 5300 @10.53.0.2 > dig.out.ns2.pre.test$n
+oldserial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.pre.test$n`
+newserial=`awk '$4 == "SOA" { print $7 + 10}' dig.out.ns2.pre.test$n`
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 freeze bits > /dev/null 2>&1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 signing -serial ${newserial:-0} bits > /dev/null 2>&1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 thaw bits > /dev/null 2>&1
+sleep 1
+$DIG bits. SOA -p 5300 @10.53.0.2 > dig.out.ns2.post.test$n
+serial=`awk '$4 == "SOA" { print $7 }' dig.out.ns2.post.test$n`
+[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
exit $status
nsec3param_t params;
};
+struct ssevent {
+ isc_event_t event;
+ isc_uint32_t serial;
+};
+
/*%
* Increment resolver-related statistics counters. Zone must be locked.
*/
dns_diff_init(zone->mctx, &diff);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
- if (zone->db != NULL) {
+ if (zone->db != NULL)
dns_db_attach(zone->db, &db);
- dns_db_currentversion(db, &oldver);
- result = dns_db_newversion(db, &newver);
- if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_ERROR,
- "keydone:dns_db_newversion -> %s",
- dns_result_totext(result));
- goto failure;
- }
- }
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
if (db == NULL)
goto failure;
+ dns_db_currentversion(db, &oldver);
+ result = dns_db_newversion(db, &newver);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "keydone:dns_db_newversion -> %s",
+ dns_result_totext(result));
+ goto failure;
+ }
+
result = dns_db_getoriginnode(db, &node);
if (result != ISC_R_SUCCESS)
goto failure;
dns_diff_init(zone->mctx, &diff);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
- if (zone->db != NULL) {
+ if (zone->db != NULL)
dns_db_attach(zone->db, &db);
- dns_db_currentversion(db, &oldver);
- result = dns_db_newversion(db, &newver);
- if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_ERROR,
- "setnsec3param:dns_db_newversion -> %s",
- dns_result_totext(result));
- goto failure;
- }
- }
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
if (db == NULL)
goto failure;
+ dns_db_currentversion(db, &oldver);
+ result = dns_db_newversion(db, &newver);
+ if (result != ISC_R_SUCCESS) {
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "setnsec3param:dns_db_newversion -> %s",
+ dns_result_totext(result));
+ goto failure;
+ }
+
CHECK(dns_db_getoriginnode(db, &node));
/*
return (zone->statlevel);
}
+
+static void
+setserial(isc_task_t *task, isc_event_t *event) {
+ isc_uint32_t oldserial, desired;
+ const char *me = "setserial";
+ isc_boolean_t commit = ISC_FALSE;
+ isc_result_t result;
+ dns_dbversion_t *oldver = NULL, *newver = NULL;
+ dns_zone_t *zone;
+ dns_db_t *db = NULL;
+ dns_diff_t diff;
+ struct ssevent *sse = (struct ssevent *)event;
+ dns_update_log_t log = { update_log_cb, NULL };
+ dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
+
+ UNUSED(task);
+
+ zone = event->ev_arg;
+ INSIST(DNS_ZONE_VALID(zone));
+
+ ENTER;
+
+ if (zone->update_disabled)
+ goto failure;
+
+ desired = sse->serial;
+
+ dns_diff_init(zone->mctx, &diff);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL)
+ goto failure;
+
+ dns_db_currentversion(db, &oldver);
+ result = dns_db_newversion(db, &newver);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "setserial:dns_db_newversion -> %s",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
+ DNS_DIFFOP_DEL, &oldtuple));
+ CHECK(dns_difftuple_copy(oldtuple, &newtuple));
+ newtuple->op = DNS_DIFFOP_ADD;
+
+ oldserial = dns_soa_getserial(&oldtuple->rdata);
+ if (desired == 0U)
+ desired = 1;
+ if (!isc_serial_gt(desired, oldserial)) {
+ if (desired != oldserial)
+ dns_zone_log(zone, ISC_LOG_INFO,
+ "setserial: desired serial (%u) "
+ "out of range (%u-%u)", desired,
+ oldserial + 1, (oldserial + 0x7fffffff));
+ goto failure;
+ }
+
+ dns_soa_setserial(desired, &newtuple->rdata);
+ CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
+ CHECK(do_one_tuple(&newtuple, db, newver, &diff));
+ result = dns_update_signatures(&log, zone, db,
+ oldver, newver, &diff,
+ zone->sigvalidityinterval);
+ if (result != ISC_R_NOTFOUND)
+ CHECK(result);
+
+ /* Write changes to journal file. */
+ CHECK(zone_journal(zone, &diff, NULL, "setserial"));
+ commit = ISC_TRUE;
+
+ LOCK_ZONE(zone);
+ zone_needdump(zone, 30);
+ UNLOCK_ZONE(zone);
+
+ failure:
+ if (oldtuple != NULL)
+ dns_difftuple_free(&oldtuple);
+ if (newtuple != NULL)
+ dns_difftuple_free(&newtuple);
+ if (oldver != NULL)
+ dns_db_closeversion(db, &oldver, ISC_FALSE);
+ if (newver != NULL)
+ dns_db_closeversion(db, &newver, commit);
+ if (db != NULL)
+ dns_db_detach(&db);
+ dns_diff_clear(&diff);
+ isc_event_free(&event);
+ dns_zone_idetach(&zone);
+
+ INSIST(oldver == NULL);
+ INSIST(newver == NULL);
+}
+
+isc_result_t
+dns_zone_setserial(dns_zone_t *zone, isc_uint32_t serial) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_zone_t *dummy = NULL;
+ isc_event_t *e = NULL;
+ struct ssevent *sse;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+
+ if (!inline_secure(zone)) {
+ if (!dns_zone_isdynamic(zone, ISC_TRUE)) {
+ result = DNS_R_NOTDYNAMIC;
+ goto failure;
+ }
+ }
+
+ if (zone->update_disabled) {
+ result = DNS_R_FROZEN;
+ goto failure;
+ }
+
+ e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
+ setserial, zone, sizeof(struct ssevent));
+ if (e == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+
+ sse = (struct ssevent *)e;
+ sse->serial = serial;
+
+ zone_iattach(zone, &dummy);
+ isc_task_send(zone->task, &e);
+
+ failure:
+ if (e != NULL)
+ isc_event_free(&e);
+ UNLOCK_ZONE(zone);
+ return (result);
+}