From 79ea5d7573347f270a050661dd7ce48c558e5392 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Mon, 14 Jan 2013 00:56:48 +0100 Subject: [PATCH 1/3] dns: more debug debug options in the tests Signed-off-by: Kai Blin Reviewed-By: Amitay Isaacs (cherry picked from commit 223cf7fb3026daa1d383a2e5796cbfe8beecaac2) --- python/samba/tests/dns.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py index a29025d..b29302b 100644 --- a/python/samba/tests/dns.py +++ b/python/samba/tests/dns.py @@ -23,6 +23,9 @@ import samba.ndr as ndr import samba.dcerpc.dns as dns from samba.tests import TestCase +FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) + + class DNSTest(TestCase): def errstr(self, errcode): @@ -82,36 +85,53 @@ class DNSTest(TestCase): "Helper to get dns domain" return os.getenv('REALM', 'example.com').lower() - def dns_transaction_udp(self, packet, host=os.getenv('SERVER_IP')): + def dns_transaction_udp(self, packet, host=os.getenv('SERVER_IP'), dump=False): "send a DNS query and read the reply" s = None try: send_packet = ndr.ndr_pack(packet) + if dump: + print self.hexdump(send_packet) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) s.connect((host, 53)) s.send(send_packet, 0) recv_packet = s.recv(2048, 0) + if dump: + print self.hexdump(recv_packet) return ndr.ndr_unpack(dns.name_packet, recv_packet) finally: if s is not None: s.close() - def dns_transaction_tcp(self, packet, host=os.getenv('SERVER_IP')): + def dns_transaction_tcp(self, packet, host=os.getenv('SERVER_IP'), dump=False): "send a DNS query and read the reply" s = None try: send_packet = ndr.ndr_pack(packet) + if dump: + print self.hexdump(send_packet) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) s.connect((host, 53)) tcp_packet = struct.pack('!H', len(send_packet)) tcp_packet += send_packet s.send(tcp_packet, 0) recv_packet = s.recv(0xffff + 2, 0) + if dump: + print self.hexdump(recv_packet) return ndr.ndr_unpack(dns.name_packet, recv_packet[2:]) finally: if s is not None: s.close() + def hexdump(self, src, length=8): + N=0; result='' + while src: + s,src = src[:length],src[length:] + hexa = ' '.join(["%02X"%ord(x) for x in s]) + s = s.translate(FILTER) + result += "%04X %-*s %s\n" % (N, length*3, hexa, s) + N+=length + return result class TestSimpleQueries(DNSTest): @@ -550,8 +570,10 @@ class TestDNSUpdates(DNSTest): response = self.dns_transaction_udp(p) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assertEqual(response.ancount, 1) - self.assertEqual(response.answers[0].rdata.preference, 10) - self.assertEqual(response.answers[0].rdata.exchange, 'mail.%s' % self.get_dns_domain()) + ans = response.answers[0] + self.assertEqual(ans.rr_type, dns.DNS_QTYPE_MX) + self.assertEqual(ans.rdata.preference, 10) + self.assertEqual(ans.rdata.exchange, 'mail.%s' % self.get_dns_domain()) class TestComplexQueries(DNSTest): -- 1.7.11.7 From 988d067f59758d7ef92eeefaf1a6757eb749f462 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Thu, 16 May 2013 12:13:22 +0200 Subject: [PATCH 2/3] dns: Fix allocation of txt_record in txt record tests Signed-off-by: Kai Blin Reviewed-By: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Thu May 16 15:39:15 CEST 2013 on sn-devel-104 (cherry picked from commit 46e98cf20b04f3668e96fb597a414d0b39d5b1ed) --- python/samba/tests/dns.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py index b29302b..15672a0 100644 --- a/python/samba/tests/dns.py +++ b/python/samba/tests/dns.py @@ -390,8 +390,9 @@ class TestDNSUpdates(DNSTest): r.rr_class = dns.DNS_QCLASS_IN r.ttl = 900 r.length = 0xffff - r.rdata = dns.txt_record() - r.rdata.txt = '"This is a test"' + rdata = dns.txt_record() + rdata.txt = '"This is a test"' + r.rdata = rdata updates.append(r) p.nscount = len(updates) p.nsrecs = updates @@ -430,8 +431,9 @@ class TestDNSUpdates(DNSTest): r.rr_class = dns.DNS_QCLASS_IN r.ttl = 900 r.length = 0xffff - r.rdata = dns.txt_record() - r.rdata.txt = '"This is a test" "and this is a test, too"' + rdata = dns.txt_record() + rdata.txt = '"This is a test" "and this is a test, too"' + r.rdata = rdata updates.append(r) p.nscount = len(updates) p.nsrecs = updates @@ -474,8 +476,9 @@ class TestDNSUpdates(DNSTest): r.rr_class = dns.DNS_QCLASS_IN r.ttl = 900 r.length = 0xffff - r.rdata = dns.txt_record() - r.rdata.txt = '"This is a test"' + rdata = dns.txt_record() + rdata.txt = '"This is a test"' + r.rdata = rdata updates.append(r) p.nscount = len(updates) p.nsrecs = updates @@ -510,8 +513,9 @@ class TestDNSUpdates(DNSTest): r.rr_class = dns.DNS_QCLASS_NONE r.ttl = 0 r.length = 0xffff - r.rdata = dns.txt_record() - r.rdata.txt = '"This is a test"' + rdata = dns.txt_record() + rdata.txt = '"This is a test"' + r.rdata = rdata updates.append(r) p.nscount = len(updates) p.nsrecs = updates -- 1.7.11.7 From df71441d40e872481ee5610a44dda1baba184bcd Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Sat, 1 Jun 2013 10:24:11 +0200 Subject: [PATCH 3/3] dns: Delete dnsNode objects when they are empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an update leaves the dnsNode without any entries, the dnsNode object should be deleted. Thanks to Günter Kukkukk for his excellent debugging work on this one. This should fix bug #9559 Signed-off-by: Kai Blin Reviewed-by: Andrew Bartlett (cherry picked from commit 8b24c43b382740106474e26dec59e1419ba77306) --- python/samba/tests/dns.py | 117 +++++++++++++++++++++++++++++++++++++++++ source4/dns_server/dns_utils.c | 8 ++- 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py index 15672a0..0ac9cf4 100644 --- a/python/samba/tests/dns.py +++ b/python/samba/tests/dns.py @@ -534,6 +534,123 @@ class TestDNSUpdates(DNSTest): response = self.dns_transaction_udp(p) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) + def test_readd_record(self): + "Test if adding, deleting and then readding a records works" + + NAME = "readdrec.%s" % self.get_dns_domain() + + # Create the record + p = self.make_name_packet(dns.DNS_OPCODE_UPDATE) + updates = [] + + name = self.get_dns_domain() + + u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN) + updates.append(u) + self.finish_name_packet(p, updates) + + updates = [] + r = dns.res_rec() + r.name = NAME + r.rr_type = dns.DNS_QTYPE_TXT + r.rr_class = dns.DNS_QCLASS_IN + r.ttl = 900 + r.length = 0xffff + rdata = dns.txt_record() + rdata.txt = '"This is a test"' + r.rdata = rdata + updates.append(r) + p.nscount = len(updates) + p.nsrecs = updates + + response = self.dns_transaction_udp(p) + self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) + + # Now check the record is around + p = self.make_name_packet(dns.DNS_OPCODE_QUERY) + questions = [] + q = self.make_name_question(NAME, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN) + questions.append(q) + + self.finish_name_packet(p, questions) + response = self.dns_transaction_udp(p) + self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) + + # Now delete the record + p = self.make_name_packet(dns.DNS_OPCODE_UPDATE) + updates = [] + + name = self.get_dns_domain() + + u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN) + updates.append(u) + self.finish_name_packet(p, updates) + + updates = [] + r = dns.res_rec() + r.name = NAME + r.rr_type = dns.DNS_QTYPE_TXT + r.rr_class = dns.DNS_QCLASS_NONE + r.ttl = 0 + r.length = 0xffff + rdata = dns.txt_record() + rdata.txt = '"This is a test"' + r.rdata = rdata + updates.append(r) + p.nscount = len(updates) + p.nsrecs = updates + + response = self.dns_transaction_udp(p) + self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) + + # check it's gone + p = self.make_name_packet(dns.DNS_OPCODE_QUERY) + questions = [] + + q = self.make_name_question(NAME, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN) + questions.append(q) + + self.finish_name_packet(p, questions) + response = self.dns_transaction_udp(p) + self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) + + # recreate the record + p = self.make_name_packet(dns.DNS_OPCODE_UPDATE) + updates = [] + + name = self.get_dns_domain() + + u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN) + updates.append(u) + self.finish_name_packet(p, updates) + + updates = [] + r = dns.res_rec() + r.name = NAME + r.rr_type = dns.DNS_QTYPE_TXT + r.rr_class = dns.DNS_QCLASS_IN + r.ttl = 900 + r.length = 0xffff + rdata = dns.txt_record() + rdata.txt = '"This is a test"' + r.rdata = rdata + updates.append(r) + p.nscount = len(updates) + p.nsrecs = updates + + response = self.dns_transaction_udp(p) + self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) + + # Now check the record is around + p = self.make_name_packet(dns.DNS_OPCODE_QUERY) + questions = [] + q = self.make_name_question(NAME, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN) + questions.append(q) + + self.finish_name_packet(p, questions) + response = self.dns_transaction_udp(p) + self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) + def test_update_add_mx_record(self): "test adding MX records works" p = self.make_name_packet(dns.DNS_OPCODE_UPDATE) diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index cb2c6f4..b192730 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -271,7 +271,13 @@ WERROR dns_replace_records(struct dns_server *dns, if (needs_add) { return WERR_OK; } - /* TODO: Delete object? */ + /* No entries left, delete the dnsNode object */ + ret = ldb_delete(dns->samdb, msg->dn); + if (ret != LDB_SUCCESS) { + DEBUG(0, ("Deleting record failed; %d\n", ret)); + return DNS_ERR(SERVER_FAILURE); + } + return WERR_OK; } if (needs_add) { -- 1.7.11.7