From 7318bbc26262a66a0d740ceefed769961ef7e476 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Thu, 17 Apr 2014 16:05:50 -0700 Subject: [PATCH] [master] serial-update-method date; 3811. [func] "serial-update-method date;" sets serial number on dynamic update to today's date in YYYYMMDDNN format. (Thanks to Bradley Forschinger.) [RT #24903] --- CHANGES | 4 ++ bin/named/zoneconf.c | 3 + bin/tests/system/nsupdate/clean.sh | 2 +- bin/tests/system/nsupdate/ns1/named.conf | 9 +++ bin/tests/system/nsupdate/setup.sh | 1 + bin/tests/system/nsupdate/tests.sh | 16 +++++ doc/arm/Bv9ARM-book.xml | 11 ++- lib/dns/include/dns/types.h | 6 +- lib/dns/tests/update_test.c | 85 ++++++++++++++++++++++-- lib/dns/update.c | 20 +++++- lib/isccfg/namedconf.c | 3 +- 11 files changed, 146 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 1ce6916910..f99a130b56 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3811. [func] "serial-update-method date;" sets serial number + on dynamic update to today's date in YYYYMMDDNN + format. (Thanks to Bradley Forschinger.) [RT #24903] + --- 9.10.0 released --- 3810. [bug] Work around broken nameservers that fail to ignore diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 38493997ca..a386f62301 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -1576,6 +1576,9 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) dns_zone_setserialupdatemethod(zone, dns_updatemethod_unixtime); + else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) + dns_zone_setserialupdatemethod(zone, + dns_updatemethod_date); else dns_zone_setserialupdatemethod(zone, dns_updatemethod_increment); diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh index aaefc02885..424cdf40c6 100644 --- a/bin/tests/system/nsupdate/clean.sh +++ b/bin/tests/system/nsupdate/clean.sh @@ -20,7 +20,7 @@ # rm -f ns1/*.jnl ns2/*.jnl -rm -f ns1/example.db ns1/unixtime.db ns1/update.db ns1/other.db ns1/keytests.db +rm -f ns1/example.db ns1/unixtime.db ns1/yyyymmddvv.db ns1/update.db ns1/other.db ns1/keytests.db rm -f ns1/md5.key ns1/sha1.key ns1/sha224.key ns1/sha256.key ns1/sha384.key rm -f ns1/sha512.key ns1/ddns.key rm -f nsupdate.out diff --git a/bin/tests/system/nsupdate/ns1/named.conf b/bin/tests/system/nsupdate/ns1/named.conf index df99040e5e..f9e3b20d30 100644 --- a/bin/tests/system/nsupdate/ns1/named.conf +++ b/bin/tests/system/nsupdate/ns1/named.conf @@ -99,6 +99,15 @@ zone "unixtime.nil" { serial-update-method unixtime; }; +zone "yyyymmddvv.nil" { + type master; + file "yyyymmddvv.db"; + check-integrity no; + allow-update { any; }; + allow-transfer { any; }; + serial-update-method date; +}; + include "md5.key"; include "sha1.key"; include "sha224.key"; diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh index 31d1562345..97c24f39a1 100644 --- a/bin/tests/system/nsupdate/setup.sh +++ b/bin/tests/system/nsupdate/setup.sh @@ -31,6 +31,7 @@ rm -f ns3/example.db.jnl cp -f ns1/example1.db ns1/example.db sed 's/example.nil/other.nil/g' ns1/example1.db > ns1/other.db sed 's/example.nil/unixtime.nil/g' ns1/example1.db > ns1/unixtime.db +sed 's/example.nil/yyyymmddvv.nil/g' ns1/example1.db > ns1/yyyymmddvv.db sed 's/example.nil/keytests.nil/g' ns1/example1.db > ns1/keytests.db cp -f ns3/example.db.in ns3/example.db diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 6a7b7b0f63..25d8659b7d 100755 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -581,5 +581,21 @@ if [ $ret -ne 0 ]; then status=1 fi +n=`expr $n + 1` +echo "I:check that yyyymmddvv serial number is correctly generated ($n)" +oldserial=`$DIG +short yyyymmddvv.nil. soa @10.53.0.1 -p 5300 | awk '{print $3}'` || ret=1 +$NSUPDATE < /dev/null 2>&1 || ret=1 + server 10.53.0.1 5300 + ttl 600 + update add new.yyyymmddvv.nil in a 1.2.3.4 + send +END +now=`$PERL -e '@lt=localtime(); printf "%.4d%.2d%2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];'` +sleep 1 +serial=`$DIG +short yyyymmddvv.nil. soa @10.53.0.1 -p 5300 | awk '{print $3}'` || ret=1 +[ "$oldserial" -ne "$serial" ] || ret=1 +[ "$serial" -eq "$now" ] || ret=1 +[ $ret = 0 ] || { echo I:failed; status=1; } + echo "I:exit status: $status" exit $status diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 81a3d7d61f..0b9cff857c 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -11050,7 +11050,7 @@ view "external" { auto-dnssec allow|maintain|off; inline-signing yes_or_no; zero-no-soa-ttl yes_or_no ; - serial-update-method increment|unixtime; + serial-update-method increment|unixtime|date; max-zone-ttl number ; }; @@ -12274,6 +12274,15 @@ example.com. NS ns2.example.net. already greater than or equal to that value, in which case it is simply incremented by one. + + When set to + serial-update-method date;, the + new SOA serial number will be the current date + in the form "YYYYMMDD", followed by two zeroes, + unless the existing serial number is already greater + than or equal to that value, in which case it is + incremented by one. + diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 7324a973a2..95c8f165e8 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -347,12 +347,12 @@ typedef enum { * \li _increment: Add one to the current serial, skipping 0. * \li _unixtime: Set to the seconds since 00:00 Jan 1, 1970, * if possible. - * \li _yyyymmvv: Set to Year, Month, Version, if possible. - * (Not yet implemented) + * \li _date: Set to YYYYMMDDVV: Year, Month, Day, Version */ typedef enum { dns_updatemethod_increment = 0, - dns_updatemethod_unixtime + dns_updatemethod_unixtime, + dns_updatemethod_date } dns_updatemethod_t; /* diff --git a/lib/dns/tests/update_test.c b/lib/dns/tests/update_test.c index f5fa7bf04d..16de79fdb1 100644 --- a/lib/dns/tests/update_test.c +++ b/lib/dns/tests/update_test.c @@ -39,7 +39,7 @@ static void set_mystdtime(int year, int month, int day) { memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; - tm.tm_mon = month; + tm.tm_mon = month - 1; tm.tm_mday = day; mystdtime = timegm(&tm) ; } @@ -135,7 +135,7 @@ ATF_TC_BODY(now_to_unix, tc) { new = dns_update_soaserial(old, dns_updatemethod_unixtime); ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); ATF_CHECK(new != 0); - ATF_REQUIRE_EQ(new, old+1); + ATF_REQUIRE_EQ(new, old + 1); dns_test_end(); } @@ -158,7 +158,7 @@ ATF_TC_BODY(future_to_unix, tc) { new = dns_update_soaserial(old, dns_updatemethod_unixtime); ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); ATF_CHECK(new != 0); - ATF_REQUIRE_EQ(new, old+1); + ATF_REQUIRE_EQ(new, old + 1); dns_test_end(); } @@ -206,7 +206,7 @@ ATF_TC_BODY(undefined_minus1_to_unix, tc) { new = dns_update_soaserial(old, dns_updatemethod_unixtime); ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); ATF_CHECK(new != 0); - ATF_REQUIRE_EQ(new, old+1); + ATF_REQUIRE_EQ(new, old + 1); dns_test_end(); } @@ -229,7 +229,7 @@ ATF_TC_BODY(undefined_to_unix, tc) { new = dns_update_soaserial(old, dns_updatemethod_unixtime); ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); ATF_CHECK(new != 0); - ATF_REQUIRE_EQ(new, old+1); + ATF_REQUIRE_EQ(new, old + 1); dns_test_end(); } @@ -252,7 +252,77 @@ ATF_TC_BODY(unixtime_zero, tc) { new = dns_update_soaserial(old, dns_updatemethod_unixtime); ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); ATF_CHECK(new != 0); - ATF_REQUIRE_EQ(new, old+1); + ATF_REQUIRE_EQ(new, old + 1); + dns_test_end(); +} + +ATF_TC(past_to_date); +ATF_TC_HEAD(past_to_date, tc) { + atf_tc_set_md_var(tc, "descr", "past to date"); +} +ATF_TC_BODY(past_to_date, tc) { + isc_uint32_t old, new; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2014, 3, 31); + old = dns_update_soaserial(0, dns_updatemethod_date); + set_mystdtime(2014, 4, 1); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + new = dns_update_soaserial(old, dns_updatemethod_date); + ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); + ATF_CHECK(new != 0); + ATF_REQUIRE_EQ(new, 2014040100); + dns_test_end(); +} + +ATF_TC(now_to_date); +ATF_TC_HEAD(now_to_date, tc) { + atf_tc_set_md_var(tc, "descr", "now to date"); +} +ATF_TC_BODY(now_to_date, tc) { + isc_uint32_t old; + isc_uint32_t new; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2014, 4, 1); + old = dns_update_soaserial(0, dns_updatemethod_date); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + new = dns_update_soaserial(old, dns_updatemethod_date); + ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); + ATF_CHECK(new != 0); + ATF_REQUIRE_EQ(new, 2014040101); + dns_test_end(); +} + +ATF_TC(future_to_date); +ATF_TC_HEAD(future_to_date, tc) { + atf_tc_set_md_var(tc, "descr", "future to date"); +} +ATF_TC_BODY(future_to_date, tc) { + isc_uint32_t old; + isc_uint32_t new; + isc_result_t result; + + UNUSED(tc); + + set_mystdtime(2014, 4, 1); + old = dns_update_soaserial(0, dns_updatemethod_date); + set_mystdtime(2014, 3, 31); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + new = dns_update_soaserial(old, dns_updatemethod_date); + ATF_REQUIRE_EQ(isc_serial_lt(old, new), ISC_TRUE); + ATF_CHECK(new != 0); + ATF_REQUIRE_EQ(new, 2014040101); dns_test_end(); } @@ -269,6 +339,9 @@ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, undefined_plus1_to_unix); ATF_TP_ADD_TC(tp, undefined_minus1_to_unix); ATF_TP_ADD_TC(tp, unixtime_zero); + ATF_TP_ADD_TC(tp, past_to_date); + ATF_TP_ADD_TC(tp, now_to_date); + ATF_TP_ADD_TC(tp, future_to_date); return (atf_no_error()); } diff --git a/lib/dns/update.c b/lib/dns/update.c index e727c347ce..7fccc87918 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -14,10 +14,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - #include +#include + #include #include #include @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -1846,6 +1847,14 @@ dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, return (result); } +static isc_stdtime_t +epoch_to_yyyymmdd(time_t when) { + struct tm *tm; + tm = localtime(&when); + return (((tm->tm_year + 1900) * 10000) + + ((tm->tm_mon + 1) * 100) + tm->tm_mday); +} + isc_uint32_t dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) { isc_stdtime_t now; @@ -1854,6 +1863,13 @@ dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) { isc_stdtime_get(&now); if (now != 0 && isc_serial_gt(now, serial)) return (now); + } else if (method == dns_updatemethod_date) { + isc_uint32_t new_serial; + + 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); } /* RFC1982 */ diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 911612f13b..4fa58e7224 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -594,7 +594,8 @@ static cfg_type_t cfg_type_dnssecupdatemode = { &cfg_rep_string, &dnssecupdatemode_enums }; -static const char *updatemethods_enums[] = { "increment", "unixtime", NULL }; +static const char *updatemethods_enums[] = { + "increment", "unixtime", "date", NULL }; static cfg_type_t cfg_type_updatemethod = { "updatemethod", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, &updatemethods_enums