dns: Delete dnsNode objects when they are empty
authorKai Blin <kai@samba.org>
Sat, 1 Jun 2013 08:24:11 +0000 (10:24 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 1 Jun 2013 08:48:11 +0000 (18:48 +1000)
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 <kai@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/dns.py
source4/dns_server/dns_utils.c

index 15672a0b008b91862218fd67cfd0366bac6a0a6e..0ac9cf4b8b49480edf421ff498efc11a65d73105 100644 (file)
@@ -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)
index 21c7f5a6808bd214208fa1e278e36384bfdc58ec..72782cf450011bd211ad6e24955ff9eb9390dbb4 100644 (file)
@@ -276,7 +276,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) {