summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Haslett <aaronhaslett@catalyst.net.nz>2018-06-07 16:51:37 +1200
committerAndrew Bartlett <abartlet@samba.org>2018-07-12 04:31:56 +0200
commitf0210f5d17f27641bccb651313f30087d53c6ef0 (patch)
treec02b28e75f0c69bdfcec63fdd4f7eb2f5392eebb
parent8ef42d4dab4dfaf5ad225b33f7748914f14dcd8c (diff)
downloadsamba-f0210f5d17f27641bccb651313f30087d53c6ef0.tar.gz
dns: static records
Modifies bind9 and internal dns to match windows static records behaviour. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10812 Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--python/samba/tests/dns.py36
-rw-r--r--selftest/knownfail.d/dns4
-rw-r--r--source4/dns_server/dlz_bind9.c20
-rw-r--r--source4/dns_server/dns_update.c38
-rw-r--r--source4/dns_server/dnsserver_common.c17
-rw-r--r--source4/dns_server/dnsserver_common.h2
6 files changed, 94 insertions, 23 deletions
diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py
index faf4c524076..508d49f47d8 100644
--- a/python/samba/tests/dns.py
+++ b/python/samba/tests/dns.py
@@ -1093,6 +1093,42 @@ class TestZones(DNSTest):
self.assertEqual(len(recs), 1)
self.assertEqual(recs[0].dwTimeStamp, 0)
+ def test_static_record_dynamic_update(self):
+ name,txt = 'agingtest', ['test txt']
+ txt2 = ['test txt2']
+ self.set_aging(enable=True)
+ rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ rec_buf.rec = TXTRecord(txt)
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip,
+ self.zone, name, rec_buf, None)
+
+ rec2 = self.dns_update_record(name, txt2)
+ self.assertEqual(rec2.dwTimeStamp, 0)
+
+ def test_dynamic_record_static_update(self):
+ name,txt = 'agingtest', ['test txt']
+ txt2 = ['test txt2']
+ txt3 = ['test txt3']
+ self.set_aging(enable=True)
+
+ self.dns_update_record(name, txt)
+
+ rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ rec_buf.rec = TXTRecord(txt2)
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip,
+ self.zone, name, rec_buf, None)
+
+ self.dns_update_record(name, txt3)
+
+ recs = self.ldap_get_dns_records(name)
+ # Put in dict because ldap recs might be out of order
+ recs = {str(r.data.str):r for r in recs}
+ self.assertNotEqual(recs[str(txt)].dwTimeStamp, 0)
+ self.assertEqual(recs[str(txt2)].dwTimeStamp, 0)
+ self.assertEqual(recs[str(txt3)].dwTimeStamp, 0)
+
def test_dns_tombstone_custom_match_rule(self):
lp = self.get_loadparm()
self.samdb = SamDB(url = lp.samdb_url(), lp = lp,
diff --git a/selftest/knownfail.d/dns b/selftest/knownfail.d/dns
index 7ae19f65e33..99b0f1d63a0 100644
--- a/selftest/knownfail.d/dns
+++ b/selftest/knownfail.d/dns
@@ -46,6 +46,8 @@ samba.tests.dns.__main__.TestZones.test_rpc_add_no_timestamp\(rodc:local\)
samba.tests.dns.__main__.TestZones.test_basic_scavenging\(rodc:local\)
samba.tests.dns.__main__.TestZones.test_dns_tombstone_custom_match_rule\(rodc:local\)
samba.tests.dns.__main__.TestZones.test_dns_tombstone_custom_match_rule_fail\(rodc:local\)
+samba.tests.dns.__main__.TestZones.test_dynamic_record_static_update\(rodc:local\)
+samba.tests.dns.__main__.TestZones.test_static_record_dynamic_update\(rodc:local\)
samba.tests.dns.__main__.TestZones.test_set_aging\(vampire_dc:local\)
samba.tests.dns.__main__.TestZones.test_aging_update\(vampire_dc:local\)
@@ -53,6 +55,8 @@ samba.tests.dns.__main__.TestZones.test_aging_update_disabled\(vampire_dc:local\
samba.tests.dns.__main__.TestZones.test_aging_refresh\(vampire_dc:local\)
samba.tests.dns.__main__.TestZones.test_basic_scavenging\(vampire_dc:local\)
samba.tests.dns.__main__.TestZones.test_dns_tombstone_custom_match_rule\(vampire_dc:local\)
+samba.tests.dns.__main__.TestZones.test_dynamic_record_static_update\(vampire_dc:local\)
+samba.tests.dns.__main__.TestZones.test_static_record_dynamic_update\(vampire_dc:local\)
samba.tests.dns.__main__.TestComplexQueries.test_cname_two_chain\(vampire_dc:local\)
samba.tests.dns.__main__.TestComplexQueries.test_one_a_query\(vampire_dc:local\)
diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c
index e55d73ba50f..5f9a71dd741 100644
--- a/source4/dns_server/dlz_bind9.c
+++ b/source4/dns_server/dlz_bind9.c
@@ -1631,18 +1631,7 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo
return ISC_R_NOMEMORY;
}
- unix_to_nt_time(&t, time(NULL));
- /*
- * convert to seconds (NT time is in 100ns units)
- */
- t /= 10 * 1000 * 1000;
- /*
- * convert to hours
- */
- t /= 3600;
-
rec->rank = DNS_RANK_ZONE;
- rec->dwTimeStamp = (uint32_t)t;
if (!b9_parse(state, rdatastr, rec)) {
state->log(ISC_LOG_INFO, "samba_dlz: failed to parse rdataset '%s'", rdatastr);
@@ -1704,6 +1693,15 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo
return ISC_R_NOMEMORY;
}
num_recs++;
+
+ if (dns_name_is_static(recs, num_recs)) {
+ rec->dwTimeStamp = 0;
+ } else {
+ unix_to_nt_time(&t, time(NULL));
+ t /= 10 * 1000 * 1000; /* convert to seconds */
+ t /= 3600; /* convert to hours */
+ rec->dwTimeStamp = (uint32_t)t;
+ }
}
recs[i] = *rec;
diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c
index ebed4495dbd..f9866611119 100644
--- a/source4/dns_server/dns_update.c
+++ b/source4/dns_server/dns_update.c
@@ -38,7 +38,8 @@
static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
const struct dns_res_rec *rrec,
- struct dnsp_DnssrvRpcRecord *r);
+ struct dnsp_DnssrvRpcRecord *r,
+ bool name_is_static);
static WERROR check_one_prerequisite(struct dns_server *dns,
TALLOC_CTX *mem_ctx,
@@ -181,7 +182,7 @@ static WERROR check_one_prerequisite(struct dns_server *dns,
rec = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
W_ERROR_HAVE_NO_MEMORY(rec);
- werror = dns_rr_to_dnsp(rec, pr, rec);
+ werror = dns_rr_to_dnsp(rec, pr, rec, dns_name_is_static(ans, acount));
W_ERROR_NOT_OK_RETURN(werror);
for (i = 0; i < acount; i++) {
@@ -297,7 +298,8 @@ static WERROR update_prescan(const struct dns_name_question *zone,
static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
const struct dns_res_rec *rrec,
- struct dnsp_DnssrvRpcRecord *r)
+ struct dnsp_DnssrvRpcRecord *r,
+ bool name_is_static)
{
enum ndr_err_code ndr_err;
NTTIME t;
@@ -311,10 +313,14 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
r->wType = (enum dns_record_type) rrec->rr_type;
r->dwTtlSeconds = rrec->ttl;
r->rank = DNS_RANK_ZONE;
- unix_to_nt_time(&t, time(NULL));
- t /= 10 * 1000 * 1000;
- t /= 3600;
- r->dwTimeStamp = t;
+ if (name_is_static) {
+ r->dwTimeStamp = 0;
+ } else {
+ unix_to_nt_time(&t, time(NULL));
+ t /= 10 * 1000 * 1000;
+ t /= 3600;
+ r->dwTimeStamp = t;
+ }
/* If we get QCLASS_ANY, we're done here */
if (rrec->rr_class == DNS_QCLASS_ANY) {
@@ -390,6 +396,7 @@ static WERROR handle_one_update(struct dns_server *dns,
WERROR werror;
bool tombstoned = false;
bool needs_add = false;
+ bool name_is_static;
DEBUG(2, ("Looking at record: \n"));
if (DEBUGLVL(2)) {
@@ -432,6 +439,8 @@ static WERROR handle_one_update(struct dns_server *dns,
first = rcount;
}
+ name_is_static = dns_name_is_static(recs, rcount);
+
if (update->rr_class == zone->question_class) {
if (update->rr_type == DNS_QTYPE_CNAME) {
/*
@@ -456,7 +465,8 @@ static WERROR handle_one_update(struct dns_server *dns,
struct dnsp_DnssrvRpcRecord, rcount + 1);
W_ERROR_HAVE_NO_MEMORY(recs);
- werror = dns_rr_to_dnsp(recs, update, &recs[rcount]);
+ werror = dns_rr_to_dnsp(
+ recs, update, &recs[rcount], name_is_static);
W_ERROR_NOT_OK_RETURN(werror);
rcount += 1;
@@ -508,7 +518,8 @@ static WERROR handle_one_update(struct dns_server *dns,
return WERR_OK;
}
- werror = dns_rr_to_dnsp(mem_ctx, update, &recs[i]);
+ werror = dns_rr_to_dnsp(
+ mem_ctx, update, &recs[i], name_is_static);
W_ERROR_NOT_OK_RETURN(werror);
for (i++; i < rcount; i++) {
@@ -532,7 +543,8 @@ static WERROR handle_one_update(struct dns_server *dns,
struct dnsp_DnssrvRpcRecord, rcount+1);
W_ERROR_HAVE_NO_MEMORY(recs);
- werror = dns_rr_to_dnsp(recs, update, &recs[rcount]);
+ werror =
+ dns_rr_to_dnsp(recs, update, &recs[rcount], name_is_static);
W_ERROR_NOT_OK_RETURN(werror);
for (i = first; i < rcount; i++) {
@@ -618,7 +630,8 @@ static WERROR handle_one_update(struct dns_server *dns,
struct dnsp_DnssrvRpcRecord);
W_ERROR_HAVE_NO_MEMORY(ns_rec);
- werror = dns_rr_to_dnsp(ns_rec, update, ns_rec);
+ werror = dns_rr_to_dnsp(
+ ns_rec, update, ns_rec, name_is_static);
W_ERROR_NOT_OK_RETURN(werror);
for (i = first; i < rcount; i++) {
@@ -635,7 +648,8 @@ static WERROR handle_one_update(struct dns_server *dns,
del_rec = talloc(mem_ctx, struct dnsp_DnssrvRpcRecord);
W_ERROR_HAVE_NO_MEMORY(del_rec);
- werror = dns_rr_to_dnsp(del_rec, update, del_rec);
+ werror =
+ dns_rr_to_dnsp(del_rec, update, del_rec, name_is_static);
W_ERROR_NOT_OK_RETURN(werror);
for (i = first; i < rcount; i++) {
diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c
index 2551240fca4..2a493702ed2 100644
--- a/source4/dns_server/dnsserver_common.c
+++ b/source4/dns_server/dnsserver_common.c
@@ -724,6 +724,23 @@ static WERROR check_name_list(TALLOC_CTX *mem_ctx, uint16_t rec_count,
return WERR_OK;
}
+bool dns_name_is_static(struct dnsp_DnssrvRpcRecord *records,
+ uint16_t rec_count)
+{
+ int i = 0;
+ for (i = 0; i < rec_count; i++) {
+ if (records[i].wType == DNS_TYPE_TOMBSTONE) {
+ continue;
+ }
+
+ if (records[i].wType == DNS_TYPE_SOA ||
+ records[i].dwTimeStamp == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
WERROR dns_get_zone_properties(struct ldb_context *samdb,
TALLOC_CTX *mem_ctx,
struct ldb_dn *zone_dn,
diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h
index 9067e2234e7..380f61b8dbc 100644
--- a/source4/dns_server/dnsserver_common.h
+++ b/source4/dns_server/dnsserver_common.h
@@ -61,6 +61,8 @@ WERROR dns_get_zone_properties(struct ldb_context *samdb,
TALLOC_CTX *mem_ctx,
struct ldb_dn *zone_dn,
struct dnsserver_zoneinfo *zoneinfo);
+bool dns_name_is_static(struct dnsp_DnssrvRpcRecord *records,
+ uint16_t rec_count);
WERROR dns_common_replace(struct ldb_context *samdb,
TALLOC_CTX *mem_ctx,
struct ldb_dn *dn,