s4:dns_server: handle tombstones in handle_one_update()
authorStefan Metzmacher <metze@samba.org>
Thu, 31 Jul 2014 07:35:26 +0000 (09:35 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 10 Mar 2015 09:55:42 +0000 (10:55 +0100)
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 491715399ff7e1ab788fec5e254581dc312e2cef)

source4/dns_server/dns_update.c

index 0906c2aaff72433a13e54ac7af33dd47a53ad991..f96be0cedf57b6fcee3c1c129057e7f49e55288b 100644 (file)
@@ -397,7 +397,9 @@ static WERROR handle_one_update(struct dns_server *dns,
        uint16_t rcount = 0;
        struct ldb_dn *dn;
        uint16_t i;
+       uint16_t first = 0;
        WERROR werror;
+       bool tombstoned = false;
        bool needs_add = false;
 
        DEBUG(2, ("Looking at record: \n"));
@@ -425,23 +427,29 @@ static WERROR handle_one_update(struct dns_server *dns,
        werror = dns_name2dn(dns, mem_ctx, update->name, &dn);
        W_ERROR_NOT_OK_RETURN(werror);
 
-       werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rcount);
+       werror = dns_common_lookup(dns->samdb, mem_ctx, dn,
+                                  &recs, &rcount, &tombstoned);
        if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
                needs_add = true;
                werror = WERR_OK;
        }
-       if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
-               werror = WERR_OK;
-       }
        W_ERROR_NOT_OK_RETURN(werror);
 
+       if (tombstoned) {
+               /*
+                * we need to keep the existing tombstone record
+                * and ignore it
+                */
+               first = rcount;
+       }
+
        if (update->rr_class == zone->question_class) {
                if (update->rr_type == DNS_QTYPE_CNAME) {
                        /*
                         * If there is a record in the directory
                         * that's not a CNAME, ignore update
                         */
-                       for (i = 0; i < rcount; i++) {
+                       for (i = first; i < rcount; i++) {
                                if (recs[i].wType != DNS_TYPE_CNAME) {
                                        DEBUG(5, ("Skipping update\n"));
                                        return WERR_OK;
@@ -454,13 +462,14 @@ static WERROR handle_one_update(struct dns_server *dns,
                         * per name, so replace everything with the new CNAME
                         */
 
-                       rcount = 1;
+                       rcount = first;
                        recs = talloc_realloc(mem_ctx, recs,
-                                       struct dnsp_DnssrvRpcRecord, rcount);
+                                       struct dnsp_DnssrvRpcRecord, rcount + 1);
                        W_ERROR_HAVE_NO_MEMORY(recs);
 
-                       werror = dns_rr_to_dnsp(recs, update, &recs[0]);
+                       werror = dns_rr_to_dnsp(recs, update, &recs[rcount]);
                        W_ERROR_NOT_OK_RETURN(werror);
+                       rcount += 1;
 
                        werror = dns_replace_records(dns, mem_ctx, dn,
                                                     needs_add, recs, rcount);
@@ -472,7 +481,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                         * If there is a CNAME record for this name,
                         * ignore update
                         */
-                       for (i = 0; i < rcount; i++) {
+                       for (i = first; i < rcount; i++) {
                                if (recs[i].wType == DNS_TYPE_CNAME) {
                                        DEBUG(5, ("Skipping update\n"));
                                        return WERR_OK;
@@ -487,7 +496,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                         * serial number is smaller than existing SOA's,
                         * ignore update
                         */
-                       for (i = 0; i < rcount; i++) {
+                       for (i = first; i < rcount; i++) {
                                if (recs[i].wType == DNS_TYPE_SOA) {
                                        uint16_t n, o;
 
@@ -537,7 +546,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                werror = dns_rr_to_dnsp(recs, update, &recs[rcount]);
                W_ERROR_NOT_OK_RETURN(werror);
 
-               for (i = 0; i < rcount; i++) {
+               for (i = first; i < rcount; i++) {
                        if (!dns_records_match(&recs[i], &recs[rcount])) {
                                continue;
                        }
@@ -559,7 +568,7 @@ static WERROR handle_one_update(struct dns_server *dns,
        } else if (update->rr_class == DNS_QCLASS_ANY) {
                if (update->rr_type == DNS_QTYPE_ALL) {
                        if (dns_name_equal(update->name, zone->name)) {
-                               for (i = 0; i < rcount; i++) {
+                               for (i = first; i < rcount; i++) {
 
                                        if (recs[i].wType == DNS_TYPE_SOA) {
                                                continue;
@@ -575,7 +584,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                                }
 
                        } else {
-                               for (i = 0; i < rcount; i++) {
+                               for (i = first; i < rcount; i++) {
                                        recs[i] = (struct dnsp_DnssrvRpcRecord) {
                                                .wType = DNS_TYPE_TOMBSTONE,
                                        };
@@ -592,7 +601,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                                return WERR_OK;
                        }
                }
-               for (i = 0; i < rcount; i++) {
+               for (i = first; i < rcount; i++) {
                        if (recs[i].wType == update->rr_type) {
                                recs[i] = (struct dnsp_DnssrvRpcRecord) {
                                        .wType = DNS_TYPE_TOMBSTONE,
@@ -621,7 +630,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                        werror = dns_rr_to_dnsp(ns_rec, update, ns_rec);
                        W_ERROR_NOT_OK_RETURN(werror);
 
-                       for (i = 0; i < rcount; i++) {
+                       for (i = first; i < rcount; i++) {
                                if (dns_records_match(ns_rec, &recs[i])) {
                                        found = true;
                                        break;
@@ -638,7 +647,7 @@ static WERROR handle_one_update(struct dns_server *dns,
                werror = dns_rr_to_dnsp(del_rec, update, del_rec);
                W_ERROR_NOT_OK_RETURN(werror);
 
-               for (i = 0; i < rcount; i++) {
+               for (i = first; i < rcount; i++) {
                        if (dns_records_match(del_rec, &recs[i])) {
                                recs[i] = (struct dnsp_DnssrvRpcRecord) {
                                        .wType = DNS_TYPE_TOMBSTONE,