The Samba-Bugzilla – Attachment 10184 Details for
Bug 10749
Support for DNS_TYPE_TOMBSTONE records
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Current work in progress on top of master
tmp.diff (text/plain), 82.34 KB, created by
Stefan Metzmacher
on 2014-08-07 13:52:17 UTC
(
hide
)
Description:
Current work in progress on top of master
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2014-08-07 13:52:17 UTC
Size:
82.34 KB
patch
obsolete
>From 6c81b497dfe929498432b1c116d0b6849344dffc Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 17:55:57 +0200 >Subject: [PATCH 01/19] s4:dns_server: handle > WERR_DNS_ERROR_NAME_DOES_NOT_EXIST in werr_to_dns_err() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_utils.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index 72782cf..86f7e7c 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -43,6 +43,8 @@ uint8_t werr_to_dns_err(WERROR werr) > return DNS_RCODE_SERVFAIL; > } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { > return DNS_RCODE_NXDOMAIN; >+ } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) { >+ return DNS_RCODE_NXDOMAIN; > } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { > return DNS_RCODE_NOTIMP; > } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { >-- >1.9.1 > > >From 72c6e258d30f4c7b560ba54b2223f07e36bbd44b Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 08:19:50 +0200 >Subject: [PATCH 02/19] s4:dns_server: map LDB_ERR_NO_SUCH_OBJECT to > WERR_DNS_ERROR_NAME_DOES_NOT_EXIST > >This is the correct fix for commit 8b24c43b382740106474e26dec59e1419ba77306 >and Bug: https://bugzilla.samba.org/show_bug.cgi?id=9559 > >With this change we have a consistent behavior between internal server >and the bind dlz module. We keep a dangling LDAP object without >dnsRecord attribute arround forever. This will be fixed in the following >commits. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_update.c | 21 ++++++++++++++++----- > source4/dns_server/dns_utils.c | 17 ++++++++--------- > 2 files changed, 24 insertions(+), 14 deletions(-) > >diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c >index 9edc40b..c439d8d 100644 >--- a/source4/dns_server/dns_update.c >+++ b/source4/dns_server/dns_update.c >@@ -82,6 +82,9 @@ static WERROR check_one_prerequisite(struct dns_server *dns, > /* > */ > werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); >+ if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { >+ return DNS_ERR(NAME_ERROR); >+ } > W_ERROR_NOT_OK_RETURN(werror); > > if (acount == 0) { >@@ -91,6 +94,9 @@ static WERROR check_one_prerequisite(struct dns_server *dns, > /* > */ > werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); >+ if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { >+ return DNS_ERR(NXRRSET); >+ } > if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { > return DNS_ERR(NXRRSET); > } >@@ -131,10 +137,11 @@ static WERROR check_one_prerequisite(struct dns_server *dns, > /* > */ > werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); >+ if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { >+ werror = WERR_OK; >+ } > if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { > werror = WERR_OK; >- ans = NULL; >- acount = 0; > } > > for (i = 0; i < acount; i++) { >@@ -163,6 +170,9 @@ static WERROR check_one_prerequisite(struct dns_server *dns, > *final_result = false; > > werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount); >+ if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { >+ return DNS_ERR(NXRRSET); >+ } > if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { > return DNS_ERR(NXRRSET); > } >@@ -421,12 +431,13 @@ static WERROR handle_one_update(struct dns_server *dns, > W_ERROR_NOT_OK_RETURN(werror); > > werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rcount); >- if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) { >- recs = NULL; >- rcount = 0; >+ 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 (update->rr_class == zone->question_class) { >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index 86f7e7c..14ca2f4 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -194,8 +194,14 @@ WERROR dns_lookup_records(struct dns_server *dns, > struct ldb_message *msg = NULL; > struct dnsp_DnssrvRpcRecord *recs; > >+ *records = NULL; >+ *rec_count = 0; >+ > ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn, > LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)"); >+ if (ret == LDB_ERR_NO_SUCH_OBJECT) { >+ return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; >+ } > if (ret != LDB_SUCCESS) { > /* TODO: we need to check if there's a glue record we need to > * create a referral to */ >@@ -204,8 +210,6 @@ WERROR dns_lookup_records(struct dns_server *dns, > > el = ldb_msg_find_element(msg, attrs[0]); > if (el == NULL) { >- *records = NULL; >- *rec_count = 0; > return DNS_ERR(NAME_ERROR); > } > >@@ -278,13 +282,8 @@ WERROR dns_replace_records(struct dns_server *dns, > if (needs_add) { > return WERR_OK; > } >- /* 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; >+ /* TODO: Delete object? */ >+ el->flags = LDB_FLAG_MOD_DELETE; > } > > if (needs_add) { >-- >1.9.1 > > >From add49b1b23c76cf35c3103389cd1886b42134a4a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 08:01:11 +0200 >Subject: [PATCH 03/19] s4:dns_server: split out a private 'dnsserver_common' > library > >This will contain common code for the internal dns server, the dlz_bind9 module >and the rpc dns management server. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_server.h | 4 +-- > source4/dns_server/dns_utils.c | 33 ----------------- > source4/dns_server/dnsserver_common.c | 68 +++++++++++++++++++++++++++++++++++ > source4/dns_server/dnsserver_common.h | 28 +++++++++++++++ > source4/dns_server/wscript_build | 8 ++++- > 5 files changed, 105 insertions(+), 36 deletions(-) > create mode 100644 source4/dns_server/dnsserver_common.c > create mode 100644 source4/dns_server/dnsserver_common.h > >diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h >index efe4db8..2459616 100644 >--- a/source4/dns_server/dns_server.h >+++ b/source4/dns_server/dns_server.h >@@ -86,7 +86,6 @@ WERROR dns_server_process_update(struct dns_server *dns, > struct dns_res_rec **updates, uint16_t *update_count, > struct dns_res_rec **additional, uint16_t *arcount); > >-uint8_t werr_to_dns_err(WERROR werror); > bool dns_name_match(const char *zone, const char *name, size_t *host_part_len); > bool dns_name_equal(const char *name1, const char *name2); > bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1, >@@ -124,5 +123,6 @@ WERROR dns_sign_tsig(struct dns_server *dns, > struct dns_name_packet *packet, > uint16_t error); > >-#define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str >+#include "source4/dns_server/dnsserver_common.h" >+ > #endif /* __DNS_SERVER_H__ */ >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index 14ca2f4..461e58d 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -33,39 +33,6 @@ > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_DNS > >-uint8_t werr_to_dns_err(WERROR werr) >-{ >- if (W_ERROR_EQUAL(WERR_OK, werr)) { >- return DNS_RCODE_OK; >- } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) { >- return DNS_RCODE_FORMERR; >- } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) { >- return DNS_RCODE_SERVFAIL; >- } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { >- return DNS_RCODE_NXDOMAIN; >- } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) { >- return DNS_RCODE_NXDOMAIN; >- } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { >- return DNS_RCODE_NOTIMP; >- } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { >- return DNS_RCODE_REFUSED; >- } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) { >- return DNS_RCODE_YXDOMAIN; >- } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) { >- return DNS_RCODE_YXRRSET; >- } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) { >- return DNS_RCODE_NXRRSET; >- } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) { >- return DNS_RCODE_NOTAUTH; >- } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) { >- return DNS_RCODE_NOTZONE; >- } else if (W_ERROR_EQUAL(DNS_ERR(BADKEY), werr)) { >- return DNS_RCODE_BADKEY; >- } >- DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr))); >- return DNS_RCODE_SERVFAIL; >-} >- > bool dns_name_match(const char *zone, const char *name, size_t *host_part_len) > { > size_t zl = strlen(zone); >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >new file mode 100644 >index 0000000..6b15d94 >--- /dev/null >+++ b/source4/dns_server/dnsserver_common.c >@@ -0,0 +1,68 @@ >+/* >+ Unix SMB/CIFS implementation. >+ >+ DNS server utils >+ >+ Copyright (C) 2014 Stefan Metzmacher >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "includes.h" >+#include "libcli/util/ntstatus.h" >+#include "libcli/util/werror.h" >+#include "librpc/ndr/libndr.h" >+#include "librpc/gen_ndr/ndr_dns.h" >+#include "librpc/gen_ndr/ndr_dnsp.h" >+#include <ldb.h> >+#include "dsdb/samdb/samdb.h" >+#include "dsdb/common/util.h" >+#include "dns_server/dnsserver_common.h" >+ >+#undef DBGC_CLASS >+#define DBGC_CLASS DBGC_DNS >+ >+uint8_t werr_to_dns_err(WERROR werr) >+{ >+ if (W_ERROR_EQUAL(WERR_OK, werr)) { >+ return DNS_RCODE_OK; >+ } else if (W_ERROR_EQUAL(DNS_ERR(FORMAT_ERROR), werr)) { >+ return DNS_RCODE_FORMERR; >+ } else if (W_ERROR_EQUAL(DNS_ERR(SERVER_FAILURE), werr)) { >+ return DNS_RCODE_SERVFAIL; >+ } else if (W_ERROR_EQUAL(DNS_ERR(NAME_ERROR), werr)) { >+ return DNS_RCODE_NXDOMAIN; >+ } else if (W_ERROR_EQUAL(WERR_DNS_ERROR_NAME_DOES_NOT_EXIST, werr)) { >+ return DNS_RCODE_NXDOMAIN; >+ } else if (W_ERROR_EQUAL(DNS_ERR(NOT_IMPLEMENTED), werr)) { >+ return DNS_RCODE_NOTIMP; >+ } else if (W_ERROR_EQUAL(DNS_ERR(REFUSED), werr)) { >+ return DNS_RCODE_REFUSED; >+ } else if (W_ERROR_EQUAL(DNS_ERR(YXDOMAIN), werr)) { >+ return DNS_RCODE_YXDOMAIN; >+ } else if (W_ERROR_EQUAL(DNS_ERR(YXRRSET), werr)) { >+ return DNS_RCODE_YXRRSET; >+ } else if (W_ERROR_EQUAL(DNS_ERR(NXRRSET), werr)) { >+ return DNS_RCODE_NXRRSET; >+ } else if (W_ERROR_EQUAL(DNS_ERR(NOTAUTH), werr)) { >+ return DNS_RCODE_NOTAUTH; >+ } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) { >+ return DNS_RCODE_NOTZONE; >+ } else if (W_ERROR_EQUAL(DNS_ERR(BADKEY), werr)) { >+ return DNS_RCODE_BADKEY; >+ } >+ DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr))); >+ return DNS_RCODE_SERVFAIL; >+} >+ >diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h >new file mode 100644 >index 0000000..41febe2 >--- /dev/null >+++ b/source4/dns_server/dnsserver_common.h >@@ -0,0 +1,28 @@ >+/* >+ Unix SMB/CIFS implementation. >+ >+ DNS server utils >+ >+ Copyright (C) 2014 Stefan Metzmacher >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#ifndef __DNSSERVER_COMMON_H__ >+#define __DNSSERVER_COMMON_H__ >+ >+uint8_t werr_to_dns_err(WERROR werr); >+#define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str >+ >+#endif /* __DNSSERVER_COMMON_H__ */ >diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build >index 280f8de..66e6b72 100644 >--- a/source4/dns_server/wscript_build >+++ b/source4/dns_server/wscript_build >@@ -1,10 +1,16 @@ > #!/usr/bin/env python > >+bld.SAMBA_LIBRARY('dnsserver_common', >+ source='dnsserver_common.c', >+ deps='samba-util errors ldbsamba clidns', >+ private_library=True, >+ ) >+ > bld.SAMBA_MODULE('service_dns', > source='dns_server.c dns_query.c dns_update.c dns_utils.c dns_crypto.c', > subsystem='service', > init_function='server_service_dns_init', >- deps='samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET ldbsamba clidns gensec auth samba_server_gensec', >+ deps='samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET ldbsamba clidns gensec auth samba_server_gensec dnsserver_common', > local_include=False, > internal_module=False, > enabled=bld.AD_DC_BUILD_IS_ENABLED() >-- >1.9.1 > > >From 59fab6314ac24e9153201af7b0aef7ded2196923 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 08:24:10 +0200 >Subject: [PATCH 04/19] s4:dns_server: split out dns_common_extract() and > dns_common_lookup() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_utils.c | 45 +------------------- > source4/dns_server/dnsserver_common.c | 77 +++++++++++++++++++++++++++++++++++ > source4/dns_server/dnsserver_common.h | 13 ++++++ > 3 files changed, 91 insertions(+), 44 deletions(-) > >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index 461e58d..3bfa98b 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -154,50 +154,7 @@ WERROR dns_lookup_records(struct dns_server *dns, > struct dnsp_DnssrvRpcRecord **records, > uint16_t *rec_count) > { >- static const char * const attrs[] = { "dnsRecord", NULL}; >- struct ldb_message_element *el; >- uint16_t ri; >- int ret; >- struct ldb_message *msg = NULL; >- struct dnsp_DnssrvRpcRecord *recs; >- >- *records = NULL; >- *rec_count = 0; >- >- ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn, >- LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)"); >- if (ret == LDB_ERR_NO_SUCH_OBJECT) { >- return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; >- } >- if (ret != LDB_SUCCESS) { >- /* TODO: we need to check if there's a glue record we need to >- * create a referral to */ >- return DNS_ERR(NAME_ERROR); >- } >- >- el = ldb_msg_find_element(msg, attrs[0]); >- if (el == NULL) { >- return DNS_ERR(NAME_ERROR); >- } >- >- recs = talloc_zero_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values); >- if (recs == NULL) { >- return WERR_NOMEM; >- } >- for (ri = 0; ri < el->num_values; ri++) { >- struct ldb_val *v = &el->values[ri]; >- enum ndr_err_code ndr_err; >- >- ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri], >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); >- return DNS_ERR(SERVER_FAILURE); >- } >- } >- *records = recs; >- *rec_count = el->num_values; >- return WERR_OK; >+ return dns_common_lookup(dns->samdb, mem_ctx, dn, records, rec_count); > } > > WERROR dns_replace_records(struct dns_server *dns, >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >index 6b15d94..2130e41 100644 >--- a/source4/dns_server/dnsserver_common.c >+++ b/source4/dns_server/dnsserver_common.c >@@ -66,3 +66,80 @@ uint8_t werr_to_dns_err(WERROR werr) > return DNS_RCODE_SERVFAIL; > } > >+WERROR dns_common_extract(const struct ldb_message_element *el, >+ TALLOC_CTX *mem_ctx, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *num_records) >+{ >+ uint16_t ri; >+ struct dnsp_DnssrvRpcRecord *recs; >+ >+ *records = NULL; >+ *num_records = 0; >+ >+ recs = talloc_zero_array(mem_ctx, struct dnsp_DnssrvRpcRecord, >+ el->num_values); >+ if (recs == NULL) { >+ return WERR_NOMEM; >+ } >+ for (ri = 0; ri < el->num_values; ri++) { >+ struct ldb_val *v = &el->values[ri]; >+ enum ndr_err_code ndr_err; >+ >+ ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri], >+ (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ TALLOC_FREE(recs); >+ DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ } >+ *records = recs; >+ *num_records = el->num_values; >+ return WERR_OK; >+} >+ >+WERROR dns_common_lookup(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *num_records) >+{ >+ static const char * const attrs[] = { >+ "dnsRecord", >+ NULL >+ }; >+ int ret; >+ WERROR werr; >+ struct ldb_message *msg = NULL; >+ struct ldb_message_element *el; >+ >+ *records = NULL; >+ *num_records = 0; >+ >+ ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, >+ LDB_SCOPE_BASE, attrs, 0, >+ "(objectClass=dnsNode)"); >+ if (ret == LDB_ERR_NO_SUCH_OBJECT) { >+ return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; >+ } >+ if (ret != LDB_SUCCESS) { >+ /* TODO: we need to check if there's a glue record we need to >+ * create a referral to */ >+ return DNS_ERR(NAME_ERROR); >+ } >+ >+ el = ldb_msg_find_element(msg, "dnsRecord"); >+ if (el == NULL) { >+ TALLOC_FREE(msg); >+ return DNS_ERR(NAME_ERROR); >+ } >+ >+ werr = dns_common_extract(el, mem_ctx, records, num_records); >+ TALLOC_FREE(msg); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ >+ return WERR_OK; >+} >diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h >index 41febe2..4731780 100644 >--- a/source4/dns_server/dnsserver_common.h >+++ b/source4/dns_server/dnsserver_common.h >@@ -25,4 +25,17 @@ > uint8_t werr_to_dns_err(WERROR werr); > #define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str > >+struct ldb_message_element; >+ >+WERROR dns_common_extract(const struct ldb_message_element *el, >+ TALLOC_CTX *mem_ctx, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *num_records); >+ >+WERROR dns_common_lookup(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ struct dnsp_DnssrvRpcRecord **records, >+ uint16_t *num_records); >+ > #endif /* __DNSSERVER_COMMON_H__ */ >-- >1.9.1 > > >From 7254f99b643d68d513b36c4fcf294ddcb4c46d13 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 11:32:02 +0200 >Subject: [PATCH 05/19] s4:dns_server: remove const from dns_replace_records() > >All callers are find we the record array gets modified. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_server.h | 2 +- > source4/dns_server/dns_utils.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > >diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h >index 2459616..12ccc9b 100644 >--- a/source4/dns_server/dns_server.h >+++ b/source4/dns_server/dns_server.h >@@ -101,7 +101,7 @@ WERROR dns_replace_records(struct dns_server *dns, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, > bool needs_add, >- const struct dnsp_DnssrvRpcRecord *records, >+ struct dnsp_DnssrvRpcRecord *records, > uint16_t rec_count); > WERROR dns_name2dn(struct dns_server *dns, > TALLOC_CTX *mem_ctx, >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index 3bfa98b..cf1adcc 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -161,7 +161,7 @@ WERROR dns_replace_records(struct dns_server *dns, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, > bool needs_add, >- const struct dnsp_DnssrvRpcRecord *records, >+ struct dnsp_DnssrvRpcRecord *records, > uint16_t rec_count) > { > struct ldb_message_element *el; >-- >1.9.1 > > >From 3556a692653e286ae1615dda58271eecc392f5b4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 18:27:56 +0200 >Subject: [PATCH 06/19] s4:dns_server: split out dns_common_replace() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_update.c | 2 - > source4/dns_server/dns_utils.c | 70 ++----------------------------- > source4/dns_server/dnsserver_common.c | 78 +++++++++++++++++++++++++++++++++++ > source4/dns_server/dnsserver_common.h | 8 ++++ > 4 files changed, 90 insertions(+), 68 deletions(-) > >diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c >index c439d8d..a589d63 100644 >--- a/source4/dns_server/dns_update.c >+++ b/source4/dns_server/dns_update.c >@@ -312,8 +312,6 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx, > r->wType = rrec->rr_type; > r->dwTtlSeconds = rrec->ttl; > r->rank = DNS_RANK_ZONE; >- /* TODO: Autogenerate this somehow */ >- r->dwSerial = 110; > > /* If we get QCLASS_ANY, we're done here */ > if (rrec->rr_class == DNS_QCLASS_ANY) { >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index cf1adcc..c3a27fe 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -164,72 +164,10 @@ WERROR dns_replace_records(struct dns_server *dns, > struct dnsp_DnssrvRpcRecord *records, > uint16_t rec_count) > { >- struct ldb_message_element *el; >- uint16_t i; >- int ret; >- struct ldb_message *msg = NULL; >- >- msg = ldb_msg_new(mem_ctx); >- W_ERROR_HAVE_NO_MEMORY(msg); >- >- msg->dn = dn; >- >- ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el); >- if (ret != LDB_SUCCESS) { >- return DNS_ERR(SERVER_FAILURE); >- } >- >- el->values = talloc_zero_array(el, struct ldb_val, rec_count); >- if (rec_count > 0) { >- W_ERROR_HAVE_NO_MEMORY(el->values); >- } >- >- for (i = 0; i < rec_count; i++) { >- static const struct dnsp_DnssrvRpcRecord zero; >- struct ldb_val *v = &el->values[el->num_values]; >- enum ndr_err_code ndr_err; >- >- if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { >- continue; >- } >- ndr_err = ndr_push_struct_blob(v, el->values, &records[i], >- (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n")); >- return DNS_ERR(SERVER_FAILURE); >- } >- el->num_values++; >- } >- >- >- if (el->num_values == 0) { >- if (needs_add) { >- return WERR_OK; >- } >- /* TODO: Delete object? */ >- el->flags = LDB_FLAG_MOD_DELETE; >- } >- >- if (needs_add) { >- ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); >- if (ret != LDB_SUCCESS) { >- return DNS_ERR(SERVER_FAILURE); >- } >- >- ret = ldb_add(dns->samdb, msg); >- if (ret != LDB_SUCCESS) { >- return DNS_ERR(SERVER_FAILURE); >- } >- >- return WERR_OK; >- } >- >- ret = ldb_modify(dns->samdb, msg); >- if (ret != LDB_SUCCESS) { >- return DNS_ERR(SERVER_FAILURE); >- } >- >- return WERR_OK; >+ /* TODO: Autogenerate this somehow */ >+ uint32_t dwSerial = 110; >+ return dns_common_replace(dns->samdb, mem_ctx, dn, >+ needs_add, dwSerial, records, rec_count); > } > > bool dns_authorative_for_zone(struct dns_server *dns, >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >index 2130e41..3c69ae3e 100644 >--- a/source4/dns_server/dnsserver_common.c >+++ b/source4/dns_server/dnsserver_common.c >@@ -143,3 +143,81 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > > return WERR_OK; > } >+ >+WERROR dns_common_replace(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ bool needs_add, >+ uint32_t serial, >+ struct dnsp_DnssrvRpcRecord *records, >+ uint16_t rec_count) >+{ >+ struct ldb_message_element *el; >+ uint16_t i; >+ int ret; >+ struct ldb_message *msg = NULL; >+ >+ msg = ldb_msg_new(mem_ctx); >+ W_ERROR_HAVE_NO_MEMORY(msg); >+ >+ msg->dn = dn; >+ >+ ret = ldb_msg_add_empty(msg, "dnsRecord", LDB_FLAG_MOD_REPLACE, &el); >+ if (ret != LDB_SUCCESS) { >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ >+ el->values = talloc_zero_array(el, struct ldb_val, rec_count); >+ if (rec_count > 0) { >+ W_ERROR_HAVE_NO_MEMORY(el->values); >+ } >+ >+ for (i = 0; i < rec_count; i++) { >+ static const struct dnsp_DnssrvRpcRecord zero; >+ struct ldb_val *v = &el->values[el->num_values]; >+ enum ndr_err_code ndr_err; >+ >+ if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { >+ continue; >+ } >+ >+ records[i].dwSerial = serial; >+ ndr_err = ndr_push_struct_blob(v, el->values, &records[i], >+ (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n")); >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ el->num_values++; >+ } >+ >+ if (needs_add) { >+ if (el->num_values == 0) { >+ return WERR_OK; >+ } >+ >+ ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); >+ if (ret != LDB_SUCCESS) { >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ >+ ret = ldb_add(samdb, msg); >+ if (ret != LDB_SUCCESS) { >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ >+ return WERR_OK; >+ } >+ >+ if (el->num_values == 0) { >+ el->flags = LDB_FLAG_MOD_DELETE; >+ } >+ >+ ret = ldb_modify(samdb, msg); >+ if (ret != LDB_SUCCESS) { >+ NTSTATUS nt = dsdb_ldb_err_to_ntstatus(ret); >+ return ntstatus_to_werror(nt); >+ } >+ >+ return WERR_OK; >+} >diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h >index 4731780..1117ad1 100644 >--- a/source4/dns_server/dnsserver_common.h >+++ b/source4/dns_server/dnsserver_common.h >@@ -38,4 +38,12 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > struct dnsp_DnssrvRpcRecord **records, > uint16_t *num_records); > >+WERROR dns_common_replace(struct ldb_context *samdb, >+ TALLOC_CTX *mem_ctx, >+ struct ldb_dn *dn, >+ bool needs_add, >+ uint32_t serial, >+ struct dnsp_DnssrvRpcRecord *records, >+ uint16_t rec_count); >+ > #endif /* __DNSSERVER_COMMON_H__ */ >-- >1.9.1 > > >From 871b875c80b21501573d05b3916517ea04540f62 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 09:32:00 +0200 >Subject: [PATCH 07/19] s4:dns_server: use .wType = DNS_TYPE_TOMBSTONE instead > of ZERO_STRUCT() > >The result is the same, but it is clearer. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_update.c | 20 +++++++++++++++----- > 1 file changed, 15 insertions(+), 5 deletions(-) > >diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c >index a589d63..4ff82b4 100644 >--- a/source4/dns_server/dns_update.c >+++ b/source4/dns_server/dns_update.c >@@ -521,7 +521,9 @@ static WERROR handle_one_update(struct dns_server *dns, > continue; > } > >- ZERO_STRUCT(recs[i]); >+ recs[i] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > } > > werror = dns_replace_records(dns, mem_ctx, dn, >@@ -570,12 +572,16 @@ static WERROR handle_one_update(struct dns_server *dns, > continue; > } > >- ZERO_STRUCT(recs[i]); >+ recs[i] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > } > > } else { > for (i = 0; i < rcount; i++) { >- ZERO_STRUCT(recs[i]); >+ recs[i] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > } > } > >@@ -591,7 +597,9 @@ static WERROR handle_one_update(struct dns_server *dns, > } > for (i = 0; i < rcount; i++) { > if (recs[i].wType == update->rr_type) { >- ZERO_STRUCT(recs[i]); >+ recs[i] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > } > } > >@@ -635,7 +643,9 @@ static WERROR handle_one_update(struct dns_server *dns, > > for (i = 0; i < rcount; i++) { > if (dns_records_match(del_rec, &recs[i])) { >- ZERO_STRUCT(recs[i]); >+ recs[i] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > } > } > >-- >1.9.1 > > >From 29610f93fd296dec63067a6e4fae1f235a64bcc4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 08:54:17 +0200 >Subject: [PATCH 08/19] s4:dns_server: make sure dns_common_lookup() doesn't > return tombstones > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_utils.c | 3 +- > source4/dns_server/dnsserver_common.c | 53 ++++++++++++++++++++++++++++++++--- > source4/dns_server/dnsserver_common.h | 3 +- > 3 files changed, 53 insertions(+), 6 deletions(-) > >diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c >index c3a27fe..c757c15 100644 >--- a/source4/dns_server/dns_utils.c >+++ b/source4/dns_server/dns_utils.c >@@ -154,7 +154,8 @@ WERROR dns_lookup_records(struct dns_server *dns, > struct dnsp_DnssrvRpcRecord **records, > uint16_t *rec_count) > { >- return dns_common_lookup(dns->samdb, mem_ctx, dn, records, rec_count); >+ return dns_common_lookup(dns->samdb, mem_ctx, dn, >+ records, rec_count, NULL); > } > > WERROR dns_replace_records(struct dns_server *dns, >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >index 3c69ae3e..0881c84 100644 >--- a/source4/dns_server/dnsserver_common.c >+++ b/source4/dns_server/dnsserver_common.c >@@ -103,10 +103,12 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, > struct dnsp_DnssrvRpcRecord **records, >- uint16_t *num_records) >+ uint16_t *num_records, >+ bool *tombstoned) > { > static const char * const attrs[] = { > "dnsRecord", >+ "dNSTombstoned", > NULL > }; > int ret; >@@ -117,9 +119,16 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > *records = NULL; > *num_records = 0; > >- ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, >- LDB_SCOPE_BASE, attrs, 0, >- "(objectClass=dnsNode)"); >+ if (tombstoned != NULL) { >+ *tombstoned = false; >+ ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, >+ LDB_SCOPE_BASE, attrs, 0, >+ "(objectClass=dnsNode)"); >+ } else { >+ ret = dsdb_search_one(samdb, mem_ctx, &msg, dn, >+ LDB_SCOPE_BASE, attrs, 0, >+ "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))"); >+ } > if (ret == LDB_ERR_NO_SUCH_OBJECT) { > return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; > } >@@ -129,9 +138,45 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > return DNS_ERR(NAME_ERROR); > } > >+ if (tombstoned != NULL) { >+ *tombstoned = ldb_msg_find_attr_as_bool(msg, >+ "dNSTombstoned", false); >+ } >+ > el = ldb_msg_find_element(msg, "dnsRecord"); > if (el == NULL) { > TALLOC_FREE(msg); >+ if (tombstoned != NULL) { >+ struct dnsp_DnssrvRpcRecord *recs; >+ /* >+ * records produced by older Samba releases >+ * keep dnsNode objects without dnsRecord and >+ * without setting dNSTombstoned=TRUE. >+ * >+ * We just pretend they're tombstones. >+ */ >+ recs = talloc_array(mem_ctx, >+ struct dnsp_DnssrvRpcRecord, >+ 1); >+ if (recs == NULL) { >+ return WERR_NOMEM; >+ } >+ recs[0] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ /* >+ * A value of timestamp != 0 >+ * indicated that the object was already >+ * a tombstone, this will be used >+ * in dns_common_replace() >+ */ >+ .data.timestamp = 1, >+ }; >+ >+ *tombstoned = true; >+ *records = recs; >+ *num_records = 1; >+ return WERR_OK; >+ } > return DNS_ERR(NAME_ERROR); > } > >diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h >index 1117ad1..becd243 100644 >--- a/source4/dns_server/dnsserver_common.h >+++ b/source4/dns_server/dnsserver_common.h >@@ -36,7 +36,8 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, > struct dnsp_DnssrvRpcRecord **records, >- uint16_t *num_records); >+ uint16_t *num_records, >+ bool *tombstoned); > > WERROR dns_common_replace(struct ldb_context *samdb, > TALLOC_CTX *mem_ctx, >-- >1.9.1 > > >From a86e72dc39315ee70a7e9d34a7b07c1d91960a0b Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 10:44:41 +0200 >Subject: [PATCH 09/19] s4:dns_server: add DNS_TYPE_TOMBSTONE support to > dns_common_replace() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dnsserver_common.c | 74 +++++++++++++++++++++++++++++++++-- > 1 file changed, 70 insertions(+), 4 deletions(-) > >diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c >index 0881c84..613608e 100644 >--- a/source4/dns_server/dnsserver_common.c >+++ b/source4/dns_server/dnsserver_common.c >@@ -189,6 +189,22 @@ WERROR dns_common_lookup(struct ldb_context *samdb, > return WERR_OK; > } > >+static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1, >+ const struct dnsp_DnssrvRpcRecord *r2) >+{ >+ if (r1->wType > r2->wType) { >+ /* >+ * The records are sorted with higher types first >+ */ >+ return -1; >+ } >+ >+ /* >+ * Then we need to sort from the oldest to newest timestamp >+ */ >+ return r1->dwTimeStamp - r2->dwTimeStamp; >+} >+ > WERROR dns_common_replace(struct ldb_context *samdb, > TALLOC_CTX *mem_ctx, > struct ldb_dn *dn, >@@ -201,6 +217,8 @@ WERROR dns_common_replace(struct ldb_context *samdb, > uint16_t i; > int ret; > struct ldb_message *msg = NULL; >+ bool need_tombstoned = false; >+ bool is_tombstoned = false; > > msg = ldb_msg_new(mem_ctx); > W_ERROR_HAVE_NO_MEMORY(msg); >@@ -212,17 +230,30 @@ WERROR dns_common_replace(struct ldb_context *samdb, > return DNS_ERR(SERVER_FAILURE); > } > >- el->values = talloc_zero_array(el, struct ldb_val, rec_count); >+ /* >+ * we have at least one value, >+ * which might be used for the tombstone marker >+ */ >+ el->values = talloc_zero_array(el, struct ldb_val, MAX(1, rec_count)); > if (rec_count > 0) { > W_ERROR_HAVE_NO_MEMORY(el->values); >+ >+ /* >+ * We store a sorted list with the high wType values first >+ * that's what windows does. It also simplifies the >+ * filtering of DNS_TYPE_TOMBSTONE records >+ */ >+ TYPESAFE_QSORT(records, rec_count, rec_cmp); > } > > for (i = 0; i < rec_count; i++) { >- static const struct dnsp_DnssrvRpcRecord zero; > struct ldb_val *v = &el->values[el->num_values]; > enum ndr_err_code ndr_err; > >- if (memcmp(&records[i], &zero, sizeof(zero)) == 0) { >+ if (records[i].wType == DNS_TYPE_TOMBSTONE) { >+ if (records[i].data.timestamp != 0) { >+ need_tombstoned = true; >+ } > continue; > } > >@@ -255,7 +286,42 @@ WERROR dns_common_replace(struct ldb_context *samdb, > } > > if (el->num_values == 0) { >- el->flags = LDB_FLAG_MOD_DELETE; >+ struct dnsp_DnssrvRpcRecord tbs; >+ struct ldb_val *v = &el->values[el->num_values]; >+ enum ndr_err_code ndr_err; >+ struct timeval tv; >+ >+ tv = timeval_current(); >+ tbs = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ .dwSerial = serial, >+ .data.timestamp = timeval_to_nttime(&tv), >+ }; >+ >+ ndr_err = ndr_push_struct_blob(v, el->values, &tbs, >+ (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ DEBUG(0, ("Failed to push dnsp_DnssrvRpcRecord\n")); >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ el->num_values++; >+ >+ need_tombstoned = true; >+ is_tombstoned = true; >+ } >+ >+ if (need_tombstoned) { >+ ret = ldb_msg_add_empty(msg, "dNSTombstoned", >+ LDB_FLAG_MOD_REPLACE, NULL); >+ if (ret != LDB_SUCCESS) { >+ return DNS_ERR(SERVER_FAILURE); >+ } >+ >+ ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s", >+ is_tombstoned ? "TRUE" : "FALSE"); >+ if (ret != LDB_SUCCESS) { >+ return DNS_ERR(SERVER_FAILURE); >+ } > } > > ret = ldb_modify(samdb, msg); >-- >1.9.1 > > >From 8bda0ffe389595edd8618df6d922e589abf2e287 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 09:35:26 +0200 >Subject: [PATCH 10/19] s4:dns_server: handle tombstones in handle_one_update() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dns_update.c | 41 +++++++++++++++++++++++++---------------- > 1 file changed, 25 insertions(+), 16 deletions(-) > >diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c >index 4ff82b4..04e7d9a 100644 >--- a/source4/dns_server/dns_update.c >+++ b/source4/dns_server/dns_update.c >@@ -400,7 +400,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")); >@@ -428,23 +430,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; >@@ -457,13 +465,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); >@@ -475,7 +484,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; >@@ -490,7 +499,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; > >@@ -540,7 +549,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; > } >@@ -562,7 +571,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; >@@ -578,7 +587,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, > }; >@@ -595,7 +604,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, >@@ -624,7 +633,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; >@@ -641,7 +650,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, >-- >1.9.1 > > >From 5a6840f3e8fab65a604d00447c1b0f6c927f3059 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 27 Feb 2014 09:59:51 +0100 >Subject: [PATCH 11/19] TODO/TEST: s4:dlz_bind9: avoid some compiler warnings > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 6 +++--- > source4/dns_server/dlz_minimal.h | 2 +- > source4/torture/dns/dlz_bind9.c | 7 ++++--- > 3 files changed, 8 insertions(+), 7 deletions(-) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index 3ffb06b..092f255 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -466,7 +466,7 @@ static isc_result_t b9_putnamedrr(struct dlz_bind9_data *state, > parse options > */ > static isc_result_t parse_options(struct dlz_bind9_data *state, >- unsigned int argc, char *argv[], >+ unsigned int argc, const char **argv, > struct b9_options *options) > { > int opt; >@@ -477,7 +477,7 @@ static isc_result_t parse_options(struct dlz_bind9_data *state, > { NULL } > }; > >- pc = poptGetContext("dlz_bind9", argc, (const char **)argv, long_options, >+ pc = poptGetContext("dlz_bind9", argc, argv, long_options, > POPT_CONTEXT_KEEP_FIRST); > while ((opt = poptGetNextOpt(pc)) != -1) { > switch (opt) { >@@ -571,7 +571,7 @@ static int dlz_state_debug_unregister(struct dlz_bind9_data *state) > called to initialise the driver > */ > _PUBLIC_ isc_result_t dlz_create(const char *dlzname, >- unsigned int argc, char *argv[], >+ unsigned int argc, const char **argv, > void **dbdata, ...) > { > struct dlz_bind9_data *state; >diff --git a/source4/dns_server/dlz_minimal.h b/source4/dns_server/dlz_minimal.h >index 5262cbd..98fb34e 100644 >--- a/source4/dns_server/dlz_minimal.h >+++ b/source4/dns_server/dlz_minimal.h >@@ -100,7 +100,7 @@ int dlz_version(unsigned int *flags); > /* > * dlz_create() is required for all DLZ external drivers. > */ >-isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...); >+isc_result_t dlz_create(const char *dlzname, unsigned int argc, const char **argv, void **dbdata, ...); > > /* > * dlz_destroy() is optional, and will be called when the driver is >diff --git a/source4/torture/dns/dlz_bind9.c b/source4/torture/dns/dlz_bind9.c >index b7d6957..0ee2f19 100644 >--- a/source4/torture/dns/dlz_bind9.c >+++ b/source4/torture/dns/dlz_bind9.c >@@ -61,7 +61,7 @@ static bool test_dlz_bind9_create(struct torture_context *tctx) > NULL > }; > tctx_static = tctx; >- torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, >+ torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, > "log", dlz_bind9_log_wrapper, NULL), ISC_R_SUCCESS, > "Failed to create samba_dlz"); > >@@ -109,7 +109,7 @@ static bool test_dlz_bind9_configure(struct torture_context *tctx) > NULL > }; > tctx_static = tctx; >- torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, >+ torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, > "log", dlz_bind9_log_wrapper, > "writeable_zone", dlz_bind9_writeable_zone_hook, NULL), > ISC_R_SUCCESS, >@@ -144,7 +144,7 @@ static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech > NULL > }; > tctx_static = tctx; >- torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, >+ torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, > "log", dlz_bind9_log_wrapper, > "writeable_zone", dlz_bind9_writeable_zone_hook, NULL), > ISC_R_SUCCESS, >@@ -216,6 +216,7 @@ static struct torture_suite *dlz_bind9_suite(TALLOC_CTX *ctx) > /** > * DNS torture module initialization > */ >+NTSTATUS torture_bind_dns_init(void); > NTSTATUS torture_bind_dns_init(void) > { > struct torture_suite *suite; >-- >1.9.1 > > >From 410646e5331f5cd52891b090d21e6840e4289d91 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 17:57:13 +0200 >Subject: [PATCH 12/19] TODO/TEST: s4:dlz_bind9: do an early > talloc_free(el_ctx) in dlz_allnodes() > >We don't have to keep everything arround while walking the whole zone. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index 092f255..83b6070 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -987,6 +987,8 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, > continue; > } > } >+ >+ talloc_free(el_ctx); > } > > talloc_free(tmp_ctx); >-- >1.9.1 > > >From 89e3bc0c1879c85838503f67252ebb93f9ab3d26 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 08:40:32 +0200 >Subject: [PATCH 13/19] TODO/TEST: s4:dlz_bind9: let dlz_bind9 use > dns_common_lookup() for name lookup > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 68 +++++++++++----------------------------- > source4/dns_server/wscript_build | 6 ++-- > 2 files changed, 21 insertions(+), 53 deletions(-) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index 83b6070..402de15 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -38,7 +38,7 @@ > #include "lib/cmdline/popt_common.h" > #include "lib/util/dlinklist.h" > #include "dlz_minimal.h" >- >+#include "dns_server/dnsserver_common.h" > > struct b9_options { > const char *url; >@@ -808,11 +808,10 @@ static isc_result_t dlz_lookup_types(struct dlz_bind9_data *state, > const char **types) > { > TALLOC_CTX *tmp_ctx = talloc_new(state); >- const char *attrs[] = { "dnsRecord", NULL }; >- int ret = LDB_SUCCESS, i; >- struct ldb_result *res; >- struct ldb_message_element *el; > struct ldb_dn *dn; >+ WERROR werr = WERR_DNS_ERROR_NAME_DOES_NOT_EXIST; >+ struct dnsp_DnssrvRpcRecord *records = NULL; >+ uint16_t num_records = 0, i; > > for (i=0; zone_prefixes[i]; i++) { > dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->samdb)); >@@ -826,38 +825,21 @@ static isc_result_t dlz_lookup_types(struct dlz_bind9_data *state, > return ISC_R_NOMEMORY; > } > >- ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, >- attrs, "objectClass=dnsNode"); >- if (ret == LDB_SUCCESS) { >+ werr = dns_common_lookup(state->samdb, tmp_ctx, dn, >+ &records, &num_records, NULL); >+ if (W_ERROR_IS_OK(werr)) { > break; > } > } >- if (ret != LDB_SUCCESS || res->count == 0) { >+ if (!W_ERROR_IS_OK(werr)) { > talloc_free(tmp_ctx); > return ISC_R_NOTFOUND; > } > >- el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); >- if (el == NULL || el->num_values == 0) { >- talloc_free(tmp_ctx); >- return ISC_R_NOTFOUND; >- } >- >- for (i=0; i<el->num_values; i++) { >- struct dnsp_DnssrvRpcRecord rec; >- enum ndr_err_code ndr_err; >+ for (i=0; i < num_records; i++) { > isc_result_t result; > >- ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec, >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(tmp_ctx); >- return ISC_R_FAILURE; >- } >- >- result = b9_putrr(state, lookup, &rec, types); >+ result = b9_putrr(state, lookup, &records[i], types); > if (result != ISC_R_SUCCESS) { > talloc_free(tmp_ctx); > return result; >@@ -1066,39 +1048,25 @@ _PUBLIC_ void dlz_closeversion(const char *zone, isc_boolean_t commit, > */ > static bool b9_has_soa(struct dlz_bind9_data *state, struct ldb_dn *dn, const char *zone) > { >- const char *attrs[] = { "dnsRecord", NULL }; >- struct ldb_result *res; >- struct ldb_message_element *el; > TALLOC_CTX *tmp_ctx = talloc_new(state); >- int ret, i; >+ WERROR werr; >+ struct dnsp_DnssrvRpcRecord *records = NULL; >+ uint16_t num_records = 0, i; > > if (!ldb_dn_add_child_fmt(dn, "DC=@,DC=%s", zone)) { > talloc_free(tmp_ctx); > return false; > } > >- ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, >- attrs, "objectClass=dnsNode"); >- if (ret != LDB_SUCCESS) { >- talloc_free(tmp_ctx); >- return false; >- } >- >- el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); >- if (el == NULL) { >+ werr = dns_common_lookup(state->samdb, tmp_ctx, dn, >+ &records, &num_records, NULL); >+ if (!W_ERROR_IS_OK(werr)) { > talloc_free(tmp_ctx); > return false; > } >- for (i=0; i<el->num_values; i++) { >- struct dnsp_DnssrvRpcRecord rec; >- enum ndr_err_code ndr_err; > >- ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec, >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- continue; >- } >- if (rec.wType == DNS_TYPE_SOA) { >+ for (i=0; i < num_records; i++) { >+ if (records[i].wType == DNS_TYPE_SOA) { > talloc_free(tmp_ctx); > return true; > } >diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build >index 66e6b72..a92ab67 100644 >--- a/source4/dns_server/wscript_build >+++ b/source4/dns_server/wscript_build >@@ -24,7 +24,7 @@ bld.SAMBA_LIBRARY('dlz_bind9', > link_name='modules/bind9/dlz_bind9.so', > realname='dlz_bind9.so', > install_path='${MODULESDIR}/bind9', >- deps='samba-hostconfig samdb-common gensec popt', >+ deps='samba-hostconfig samdb-common gensec popt dnsserver_common', > enabled=bld.AD_DC_BUILD_IS_ENABLED()) > > bld.SAMBA_LIBRARY('dlz_bind9_9', >@@ -34,12 +34,12 @@ bld.SAMBA_LIBRARY('dlz_bind9_9', > link_name='modules/bind9/dlz_bind9_9.so', > realname='dlz_bind9_9.so', > install_path='${MODULESDIR}/bind9', >- deps='samba-hostconfig samdb-common gensec popt', >+ deps='samba-hostconfig samdb-common gensec popt dnsserver_common', > enabled=bld.AD_DC_BUILD_IS_ENABLED()) > > bld.SAMBA_LIBRARY('dlz_bind9_for_torture', > source='dlz_bind9.c', > cflags='-DBIND_VERSION_9_8', > private_library=True, >- deps='samba-hostconfig samdb-common gensec popt', >+ deps='samba-hostconfig samdb-common gensec popt dnsserver_common', > enabled=bld.AD_DC_BUILD_IS_ENABLED()) >-- >1.9.1 > > >From 1953b48d5e2a724371effa47737441e2f91d5aef Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 17:59:08 +0200 >Subject: [PATCH 14/19] TODO/TEST: s4:dlz_bind9: let dlz_bind9 use > dns_common_extract() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 118 +++++++++++++++++++++-------------------- > 1 file changed, 61 insertions(+), 57 deletions(-) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index 402de15..0431307 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -918,6 +918,9 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, > TALLOC_CTX *el_ctx = talloc_new(tmp_ctx); > const char *rdn, *name; > const struct ldb_val *v; >+ WERROR werr; >+ struct dnsp_DnssrvRpcRecord *recs = NULL; >+ uint16_t num_recs = 0; > > el = ldb_msg_find_element(res->msgs[i], "dnsRecord"); > if (el == NULL || el->num_values == 0) { >@@ -951,20 +954,18 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata, > return ISC_R_NOMEMORY; > } > >- for (j=0; j<el->num_values; j++) { >- struct dnsp_DnssrvRpcRecord rec; >- enum ndr_err_code ndr_err; >- isc_result_t result; >+ werr = dns_common_extract(el, el_ctx, &recs, &num_recs); >+ if (!W_ERROR_IS_OK(werr)) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", >+ ldb_dn_get_linearized(dn), win_errstr(werr)); >+ talloc_free(el_ctx); >+ continue; >+ } > >- ndr_err = ndr_pull_struct_blob(&el->values[j], el_ctx, &rec, >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- continue; >- } >+ for (j=0; j < num_recs; j++) { >+ isc_result_t result; > >- result = b9_putnamedrr(state, allnodes, name, &rec); >+ result = b9_putnamedrr(state, allnodes, name, &recs[i]); > if (result != ISC_R_SUCCESS) { > continue; > } >@@ -1521,8 +1522,11 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > const char *attrs[] = { "dnsRecord", NULL }; > int ret, i; > struct ldb_message_element *el; >+ struct dnsp_DnssrvRpcRecord *recs = NULL; >+ uint16_t num_recs = 0; > enum ndr_err_code ndr_err; > NTTIME t; >+ WERROR werr; > > if (state->transaction_token != (void*)version) { > state->log(ISC_LOG_INFO, "samba_dlz: bad transaction version"); >@@ -1582,22 +1586,19 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > } > } > >+ werr = dns_common_extract(el, rec, &recs, &num_recs); >+ if (!W_ERROR_IS_OK(werr)) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", >+ ldb_dn_get_linearized(dn), win_errstr(werr)); >+ talloc_free(rec); >+ return ISC_R_FAILURE; >+ } >+ > /* there are existing records. We need to see if this will > * replace a record or add to it > */ >- for (i=0; i<el->num_values; i++) { >- struct dnsp_DnssrvRpcRecord rec2; >- >- ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2, >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(rec); >- return ISC_R_FAILURE; >- } >- >- if (b9_record_match(state, rec, &rec2)) { >+ for (i=0; i < num_recs; i++) { >+ if (b9_record_match(state, rec, &recs[i])) { > break; > } > } >@@ -1656,7 +1657,9 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo > const char *attrs[] = { "dnsRecord", NULL }; > int ret, i; > struct ldb_message_element *el; >- enum ndr_err_code ndr_err; >+ struct dnsp_DnssrvRpcRecord *recs = NULL; >+ uint16_t num_recs = 0; >+ WERROR werr; > > if (state->transaction_token != (void*)version) { > state->log(ISC_LOG_ERROR, "samba_dlz: bad transaction version"); >@@ -1698,19 +1701,16 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo > return ISC_R_FAILURE; > } > >- for (i=0; i<el->num_values; i++) { >- struct dnsp_DnssrvRpcRecord rec2; >- >- ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2, >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(rec); >- return ISC_R_FAILURE; >- } >+ werr = dns_common_extract(el, rec, &recs, &num_recs); >+ if (!W_ERROR_IS_OK(werr)) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", >+ ldb_dn_get_linearized(dn), win_errstr(werr)); >+ talloc_free(rec); >+ return ISC_R_FAILURE; >+ } > >- if (b9_record_match(state, rec, &rec2)) { >+ for (i=0; i < num_recs; i++) { >+ if (b9_record_match(state, rec, &recs[i])) { > break; > } > } >@@ -1762,11 +1762,15 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > isc_result_t result; > struct ldb_result *res; > const char *attrs[] = { "dnsRecord", NULL }; >- int ret, i; >+ int ret; > struct ldb_message_element *el; >- enum ndr_err_code ndr_err; >+ int vi = 0; > enum dns_record_type dns_type; > bool found = false; >+ struct dnsp_DnssrvRpcRecord *recs = NULL; >+ uint16_t num_recs = 0; >+ uint16_t ri = 0; >+ WERROR werr; > > if (state->transaction_token != (void*)version) { > state->log(ISC_LOG_ERROR, "samba_dlz: bad transaction version"); >@@ -1802,27 +1806,27 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > return ISC_R_NOTFOUND; > } > >- for (i=0; i<el->num_values; i++) { >- struct dnsp_DnssrvRpcRecord rec2; >+ werr = dns_common_extract(el, tmp_ctx, &recs, &num_recs); >+ if (!W_ERROR_IS_OK(werr)) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", >+ ldb_dn_get_linearized(dn), win_errstr(werr)); >+ talloc_free(tmp_ctx); >+ return ISC_R_FAILURE; >+ } > >- ndr_err = ndr_pull_struct_blob(&el->values[i], tmp_ctx, &rec2, >- (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(tmp_ctx); >- return ISC_R_FAILURE; >+ for (ri=0; ri < num_recs; ri++) { >+ if (dns_type != recs[ri].wType) { >+ vi += 1; >+ continue; > } > >- if (dns_type == rec2.wType) { >- if (i < el->num_values-1) { >- memmove(&el->values[i], &el->values[i+1], >- sizeof(el->values[0])*((el->num_values-1)-i)); >- } >- el->num_values--; >- i--; >- found = true; >+ found = true; >+ >+ if (vi < el->num_values-1) { >+ memmove(&el->values[vi], &el->values[vi+1], >+ sizeof(el->values[0])*((el->num_values-1)-vi)); > } >+ el->num_values--; > } > > if (!found) { >-- >1.9.1 > > >From 5648b384318b7db3275d64abc447121379d59841 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 18:51:39 +0200 >Subject: [PATCH 15/19] TODO/TEST: s4:dlz_bind9: let dlz_bind9 use > dns_common_replace() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 129 ++++++++++++++++------------------------- > 1 file changed, 49 insertions(+), 80 deletions(-) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index 0431307..a4f2228 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -1355,32 +1355,15 @@ static isc_result_t b9_add_record(struct dlz_bind9_data *state, const char *name > struct ldb_dn *dn, > struct dnsp_DnssrvRpcRecord *rec) > { >- struct ldb_message *msg; >- enum ndr_err_code ndr_err; >- struct ldb_val v; >- int ret; >- >- msg = ldb_msg_new(rec); >- if (msg == NULL) { >- return ISC_R_NOMEMORY; >- } >- msg->dn = dn; >- ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); >- if (ret != LDB_SUCCESS) { >- return ISC_R_FAILURE; >- } >- >- ndr_err = ndr_push_struct_blob(&v, rec, rec, (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- return ISC_R_FAILURE; >- } >- ret = ldb_msg_add_value(msg, "dnsRecord", &v, NULL); >- if (ret != LDB_SUCCESS) { >- return ISC_R_FAILURE; >- } >+ WERROR werr; > >- ret = ldb_add(state->samdb, msg); >- if (ret != LDB_SUCCESS) { >+ werr = dns_common_replace(state->samdb, rec, dn, >+ true,/* needs_add */ >+ state->soa_serial, >+ rec, 1); >+ if (!W_ERROR_IS_OK(werr)) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to add %s - %s", >+ ldb_dn_get_linearized(dn), win_errstr(werr)); > return ISC_R_FAILURE; > } > >@@ -1524,7 +1507,6 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > struct ldb_message_element *el; > struct dnsp_DnssrvRpcRecord *recs = NULL; > uint16_t num_recs = 0; >- enum ndr_err_code ndr_err; > NTTIME t; > WERROR werr; > >@@ -1543,7 +1525,6 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > t /= 3600; /* convert to hours */ > > rec->rank = DNS_RANK_ZONE; >- rec->dwSerial = state->soa_serial; > rec->dwTimeStamp = (uint32_t)t; > > if (!b9_parse(state, rdatastr, rec)) { >@@ -1602,25 +1583,26 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > break; > } > } >- if (i == el->num_values) { >+ if (i == UINT16_MAX) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to already %u dnsRecord values for %s", >+ i, ldb_dn_get_linearized(dn)); >+ talloc_free(rec); >+ return ISC_R_FAILURE; >+ } >+ >+ if (i == num_recs) { > /* adding a new value */ >- el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1); >- if (el->values == NULL) { >+ recs = talloc_realloc(rec, recs, >+ struct dnsp_DnssrvRpcRecord, >+ num_recs + 1); >+ if (recs == NULL) { > talloc_free(rec); > return ISC_R_NOMEMORY; > } >- el->num_values++; >- } >- >- ndr_err = ndr_push_struct_blob(&el->values[i], rec, rec, >- (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); >- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to push dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(rec); >- return ISC_R_FAILURE; >+ num_recs++; > } > >+ recs[i] = *rec; > > if (!b9_set_session_info(state, name)) { > talloc_free(rec); >@@ -1628,12 +1610,14 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > } > > /* modify the record */ >- el->flags = LDB_FLAG_MOD_REPLACE; >- ret = ldb_modify(state->samdb, res->msgs[0]); >+ werr = dns_common_replace(state->samdb, rec, dn, >+ false,/* needs_add */ >+ state->soa_serial, >+ recs, num_recs); > b9_reset_session_info(state); >- if (ret != LDB_SUCCESS) { >+ if (!W_ERROR_IS_OK(werr)) { > state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", >- ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); >+ ldb_dn_get_linearized(dn), win_errstr(werr)); > talloc_free(rec); > return ISC_R_FAILURE; > } >@@ -1711,35 +1695,27 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo > > for (i=0; i < num_recs; i++) { > if (b9_record_match(state, rec, &recs[i])) { >+ recs[i] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > break; > } > } >- if (i == el->num_values) { >- talloc_free(rec); >- return ISC_R_NOTFOUND; >- } >- >- if (i < el->num_values-1) { >- memmove(&el->values[i], &el->values[i+1], sizeof(el->values[0])*((el->num_values-1)-i)); >- } >- el->num_values--; > > if (!b9_set_session_info(state, name)) { > talloc_free(rec); > return ISC_R_FAILURE; > } > >- if (el->num_values == 0) { >- el->flags = LDB_FLAG_MOD_DELETE; >- } else { >- el->flags = LDB_FLAG_MOD_REPLACE; >- } >- ret = ldb_modify(state->samdb, res->msgs[0]); >- >+ /* modify the record */ >+ werr = dns_common_replace(state->samdb, rec, dn, >+ false,/* needs_add */ >+ state->soa_serial, >+ recs, num_recs); > b9_reset_session_info(state); >- if (ret != LDB_SUCCESS) { >+ if (!W_ERROR_IS_OK(werr)) { > state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", >- ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); >+ ldb_dn_get_linearized(dn), win_errstr(werr)); > talloc_free(rec); > return ISC_R_FAILURE; > } >@@ -1764,7 +1740,6 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > const char *attrs[] = { "dnsRecord", NULL }; > int ret; > struct ldb_message_element *el; >- int vi = 0; > enum dns_record_type dns_type; > bool found = false; > struct dnsp_DnssrvRpcRecord *recs = NULL; >@@ -1816,17 +1791,13 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > > for (ri=0; ri < num_recs; ri++) { > if (dns_type != recs[ri].wType) { >- vi += 1; > continue; > } > > found = true; >- >- if (vi < el->num_values-1) { >- memmove(&el->values[vi], &el->values[vi+1], >- sizeof(el->values[0])*((el->num_values-1)-vi)); >- } >- el->num_values--; >+ recs[ri] = (struct dnsp_DnssrvRpcRecord) { >+ .wType = DNS_TYPE_TOMBSTONE, >+ }; > } > > if (!found) { >@@ -1839,17 +1810,15 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > return ISC_R_FAILURE; > } > >- if (el->num_values == 0) { >- el->flags = LDB_FLAG_MOD_DELETE; >- } else { >- el->flags = LDB_FLAG_MOD_REPLACE; >- } >- ret = ldb_modify(state->samdb, res->msgs[0]); >- >+ /* modify the record */ >+ werr = dns_common_replace(state->samdb, tmp_ctx, dn, >+ false,/* needs_add */ >+ state->soa_serial, >+ recs, num_recs); > b9_reset_session_info(state); >- if (ret != LDB_SUCCESS) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to delete type %s in %s - %s", >- type, ldb_dn_get_linearized(dn), ldb_errstring(state->samdb)); >+ if (!W_ERROR_IS_OK(werr)) { >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", >+ ldb_dn_get_linearized(dn), win_errstr(werr)); > talloc_free(tmp_ctx); > return ISC_R_FAILURE; > } >-- >1.9.1 > > >From a2846d5cba8a2b96290c87a5212da499c3ecc9c7 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 30 Jul 2014 20:12:08 +0200 >Subject: [PATCH 16/19] TODO/TEST: s4:dlz_bind9: let dlz_bind9 use > dns_common_lookup() before removing records > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 53 ++++++------------------------------------ > 1 file changed, 7 insertions(+), 46 deletions(-) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index a4f2228..a0c42d1 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -1637,12 +1637,9 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo > struct dnsp_DnssrvRpcRecord *rec; > struct ldb_dn *dn; > isc_result_t result; >- struct ldb_result *res; >- const char *attrs[] = { "dnsRecord", NULL }; >- int ret, i; >- struct ldb_message_element *el; > struct dnsp_DnssrvRpcRecord *recs = NULL; > uint16_t num_recs = 0; >+ uint16_t i; > WERROR werr; > > if (state->transaction_token != (void*)version) { >@@ -1669,28 +1666,11 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo > } > > /* get the existing records */ >- ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); >- if (ret == LDB_ERR_NO_SUCH_OBJECT) { >- talloc_free(rec); >- return ISC_R_NOTFOUND; >- } >- >- /* there are existing records. We need to see if any match >- */ >- el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); >- if (el == NULL || el->num_values == 0) { >- state->log(ISC_LOG_ERROR, "samba_dlz: no dnsRecord attribute for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(rec); >- return ISC_R_FAILURE; >- } >- >- werr = dns_common_extract(el, rec, &recs, &num_recs); >+ werr = dns_common_lookup(state->samdb, rec, dn, >+ &recs, &num_recs, NULL); > if (!W_ERROR_IS_OK(werr)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", >- ldb_dn_get_linearized(dn), win_errstr(werr)); > talloc_free(rec); >- return ISC_R_FAILURE; >+ return ISC_R_NOTFOUND; > } > > for (i=0; i < num_recs; i++) { >@@ -1736,10 +1716,6 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > TALLOC_CTX *tmp_ctx; > struct ldb_dn *dn; > isc_result_t result; >- struct ldb_result *res; >- const char *attrs[] = { "dnsRecord", NULL }; >- int ret; >- struct ldb_message_element *el; > enum dns_record_type dns_type; > bool found = false; > struct dnsp_DnssrvRpcRecord *recs = NULL; >@@ -1767,26 +1743,11 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void * > } > > /* get the existing records */ >- ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); >- if (ret == LDB_ERR_NO_SUCH_OBJECT) { >- talloc_free(tmp_ctx); >- return ISC_R_NOTFOUND; >- } >- >- /* there are existing records. We need to see if any match the type >- */ >- el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); >- if (el == NULL || el->num_values == 0) { >- talloc_free(tmp_ctx); >- return ISC_R_NOTFOUND; >- } >- >- werr = dns_common_extract(el, tmp_ctx, &recs, &num_recs); >+ werr = dns_common_lookup(state->samdb, tmp_ctx, dn, >+ &recs, &num_recs, NULL); > if (!W_ERROR_IS_OK(werr)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", >- ldb_dn_get_linearized(dn), win_errstr(werr)); > talloc_free(tmp_ctx); >- return ISC_R_FAILURE; >+ return ISC_R_NOTFOUND; > } > > for (ri=0; ri < num_recs; ri++) { >-- >1.9.1 > > >From d517056d2596c1433ef8462b7d745e5b15e3b881 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 31 Jul 2014 09:30:16 +0200 >Subject: [PATCH 17/19] TODO/TEST: s4:dlz_bind9: let dlz_bind9 use > dns_common_lookup() before add/modify > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/dns_server/dlz_bind9.c | 66 +++++++----------------------------------- > 1 file changed, 11 insertions(+), 55 deletions(-) > >diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c >index a0c42d1..ac184b5 100644 >--- a/source4/dns_server/dlz_bind9.c >+++ b/source4/dns_server/dlz_bind9.c >@@ -1347,29 +1347,6 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const > return ISC_TRUE; > } > >- >-/* >- add a new record >- */ >-static isc_result_t b9_add_record(struct dlz_bind9_data *state, const char *name, >- struct ldb_dn *dn, >- struct dnsp_DnssrvRpcRecord *rec) >-{ >- WERROR werr; >- >- werr = dns_common_replace(state->samdb, rec, dn, >- true,/* needs_add */ >- state->soa_serial, >- rec, 1); >- if (!W_ERROR_IS_OK(werr)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to add %s - %s", >- ldb_dn_get_linearized(dn), win_errstr(werr)); >- return ISC_R_FAILURE; >- } >- >- return ISC_R_SUCCESS; >-} >- > /* > see if two DNS names are the same > */ >@@ -1501,12 +1478,11 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > struct dnsp_DnssrvRpcRecord *rec; > struct ldb_dn *dn; > isc_result_t result; >- struct ldb_result *res; >- const char *attrs[] = { "dnsRecord", NULL }; >- int ret, i; >- struct ldb_message_element *el; >+ bool tomstoned = false; >+ bool needs_add = false; > struct dnsp_DnssrvRpcRecord *recs = NULL; > uint16_t num_recs = 0; >+ uint16_t i; > NTTIME t; > WERROR werr; > >@@ -1541,33 +1517,12 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > } > > /* get any existing records */ >- ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode"); >- if (ret == LDB_ERR_NO_SUCH_OBJECT) { >- if (!b9_set_session_info(state, name)) { >- talloc_free(rec); >- return ISC_R_FAILURE; >- } >- result = b9_add_record(state, name, dn, rec); >- b9_reset_session_info(state); >- talloc_free(rec); >- if (result == ISC_R_SUCCESS) { >- state->log(ISC_LOG_INFO, "samba_dlz: added %s %s", name, rdatastr); >- } >- return result; >- } >- >- el = ldb_msg_find_element(res->msgs[0], "dnsRecord"); >- if (el == NULL) { >- ret = ldb_msg_add_empty(res->msgs[0], "dnsRecord", LDB_FLAG_MOD_ADD, &el); >- if (ret != LDB_SUCCESS) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to add dnsRecord for %s", >- ldb_dn_get_linearized(dn)); >- talloc_free(rec); >- return ISC_R_FAILURE; >- } >+ werr = dns_common_lookup(state->samdb, rec, dn, >+ &recs, &num_recs, &tomstoned); >+ if (!W_ERROR_EQUAL(werr, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) { >+ needs_add = true; >+ werr = WERR_OK; > } >- >- werr = dns_common_extract(el, rec, &recs, &num_recs); > if (!W_ERROR_IS_OK(werr)) { > state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s", > ldb_dn_get_linearized(dn), win_errstr(werr)); >@@ -1611,12 +1566,13 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo > > /* modify the record */ > werr = dns_common_replace(state->samdb, rec, dn, >- false,/* needs_add */ >+ needs_add, > state->soa_serial, > recs, num_recs); > b9_reset_session_info(state); > if (!W_ERROR_IS_OK(werr)) { >- state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s", >+ state->log(ISC_LOG_ERROR, "samba_dlz: failed to %s %s - %s", >+ needs_add ? "add" : "modify", > ldb_dn_get_linearized(dn), win_errstr(werr)); > talloc_free(rec); > return ISC_R_FAILURE; >-- >1.9.1 > > >From 85eac3f2f6a42068cd50f6e2d1caeb607bd3caa8 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 Aug 2014 16:23:37 +0200 >Subject: [PATCH 18/19] TODO dns_cleanup > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 >--- > source4/dns_server/dns_cleanup.c | 251 +++++++++++++++++++++++++++++++++++++++ > source4/dns_server/wscript_build | 10 ++ > 2 files changed, 261 insertions(+) > create mode 100644 source4/dns_server/dns_cleanup.c > >diff --git a/source4/dns_server/dns_cleanup.c b/source4/dns_server/dns_cleanup.c >new file mode 100644 >index 0000000..93e3420 >--- /dev/null >+++ b/source4/dns_server/dns_cleanup.c >@@ -0,0 +1,251 @@ >+/* >+ Unix SMB/CIFS implementation. >+ >+ DNS server cleanup >+ >+ Copyright (C) 2014 Stefan Metzmacher >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 3 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program. If not, see <http://www.gnu.org/licenses/>. >+*/ >+ >+#include "includes.h" >+#include "smbd/service_task.h" >+#include "smbd/service.h" >+#include "lib/events/events.h" >+#include "libcli/util/ntstatus.h" >+#include "param/param.h" >+#include "librpc/gen_ndr/dnsp.h" >+#include <ldb.h> >+#include "dsdb/samdb/samdb.h" >+#include "dsdb/common/util.h" >+#include "auth/session.h" >+#include "lib/util/dlinklist.h" >+#include "dns_server/dnsserver_common.h" >+ >+#undef DBGC_CLASS >+#define DBGC_CLASS DBGC_DNS >+ >+struct dns_cleanup { >+ struct task_server *task; >+ struct ldb_context *samdb; >+ >+ struct timeval next_event; >+ struct tevent_timer *te; >+}; >+ >+static void dns_cleanup_run_partition(struct dns_cleanup *dns, >+ struct ldb_dn *base_dn, >+ NTTIME expire_time) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ TALLOC_CTX *last = NULL; >+ int ret; >+ struct ldb_result *res = NULL; >+ int i; >+ static const char * const attrs[] = { >+ "dnsRecord", >+ NULL, >+ }; >+ >+ ret = ldb_search(dns->samdb, frame, &res, base_dn, >+ LDB_SCOPE_SUBTREE, attrs, >+ "(&(objectClass=dnsNode)" >+ "(|(dNSTombstoned=TRUE)(!(dnsRecord=*)))" >+ ")"); >+ if (ret != LDB_SUCCESS) { >+ TALLOC_FREE(frame); >+ return; >+ } >+ >+ for (i=0; i<res->count; i++) { >+ struct ldb_message *msg; >+ struct ldb_message_element *el; >+ WERROR werr; >+ struct dnsp_DnssrvRpcRecord *recs = NULL; >+ uint16_t num_recs = 0; >+ bool tombstoned = false; >+ NTTIME tbs_time = 0; >+ >+ TALLOC_FREE(last); >+ msg = res->msgs[i]; >+ res->msgs[i] = NULL; >+ last = msg; >+ >+ el = ldb_msg_find_element(msg, "dnsRecord"); >+ if (el != NULL) { >+ werr = dns_common_extract(el, msg->elements, &recs, &num_recs); >+ if (!W_ERROR_IS_OK(werr)) { >+ continue; >+ } >+ >+ if (num_recs >= 1 && recs[0].wType == DNS_TYPE_TOMBSTONE) { >+ tbs_time = recs[0].data.timestamp; >+ } >+ } >+ >+ if (tbs_time > expire_time) { >+ continue; >+ } >+ >+ msg->num_elements = 0; >+ TALLOC_FREE(msg->elements); >+ >+ /* >+ * It's very likely that we will delete this object, >+ * so check again under a transaction >+ */ >+ ret = ldb_transaction_start(dns->samdb); >+ if (ret != LDB_SUCCESS) { >+ continue; >+ } >+ >+ werr = dns_common_lookup(dns->samdb, msg, msg->dn, >+ &recs, &num_recs, &tombstoned); >+ if (!W_ERROR_IS_OK(werr)) { >+ ldb_transaction_cancel(dns->samdb); >+ continue; >+ } >+ >+ if (!tombstoned) { >+ ldb_transaction_cancel(dns->samdb); >+ continue; >+ } >+ >+ ret = ldb_delete(dns->samdb, msg->dn); >+ if (ret != LDB_SUCCESS) { >+ ldb_transaction_cancel(dns->samdb); >+ continue; >+ } >+ >+ ret = ldb_transaction_commit(dns->samdb); >+ if (ret != LDB_SUCCESS) { >+ continue; >+ } >+ } >+ >+ TALLOC_FREE(frame); >+} >+ >+static void dns_cleanup_run(struct dns_cleanup *dns) >+{ >+ struct ldb_dn *default_dn = ldb_get_default_basedn(dns->samdb); >+ struct ldb_dn *root_dn = ldb_get_root_basedn(dns->samdb); >+ struct ldb_dn *base_dns[3]; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ size_t i; >+ NTTIME expire_time; >+ time_t t; >+ >+ base_dns[0] = ldb_dn_copy(frame, default_dn); >+ ldb_dn_add_child_fmt(base_dns[0], "CN=MicrosoftDNS,CN=System"); >+ base_dns[1] = ldb_dn_copy(frame, default_dn); >+ ldb_dn_add_child_fmt(base_dns[1], "CN=MicrosoftDNS,DC=DomainDnsZones"); >+ base_dns[2] = ldb_dn_copy(frame, root_dn); >+ ldb_dn_add_child_fmt(base_dns[2], "CN=MicrosoftDNS,DC=ForestDnsZones"); >+ >+ t = time(NULL); >+ >+ t -= (60*60*24*14); >+ unix_to_nt_time(&expire_time, t); >+ >+ for (i=0; i < 3; i++) { >+ dns_cleanup_run_partition(dns, base_dns[i], expire_time); >+ } >+ >+ TALLOC_FREE(frame); >+} >+ >+static void dns_cleanup_timer(struct tevent_context *ev, >+ struct tevent_timer *te, >+ struct timeval current_time, >+ void *private_data) >+{ >+ struct dns_cleanup *dns = >+ talloc_get_type_abort(private_data, >+ struct dns_cleanup); >+ >+ dns->next_event = timeval_current_ofs(600, 0); >+ dns->te = tevent_add_timer(dns->task->event_ctx, dns, >+ dns->next_event, >+ dns_cleanup_timer, >+ dns); >+ if (dns->te == NULL) { >+ task_server_terminate(dns->task, >+ "dns_cleanup: tevent_add_time failed", true); >+ return; >+ } >+ >+ dns_cleanup_run(dns); >+} >+ >+static void dns_cleanup_task_init(struct task_server *task) >+{ >+ struct dns_cleanup *dns; >+ bool is_rodc = false; >+ >+ switch (lpcfg_server_role(task->lp_ctx)) { >+ case ROLE_STANDALONE: >+ task_server_terminate(task, "dns_cleanup: no DNS required in standalone configuration", false); >+ return; >+ case ROLE_DOMAIN_MEMBER: >+ task_server_terminate(task, "dns_cleanup: no DNS required in member server configuration", false); >+ return; >+ case ROLE_ACTIVE_DIRECTORY_DC: >+ /* Yes, we want a DNS */ >+ break; >+ } >+ >+ task_server_set_title(task, "task[dns_cleanup]"); >+ >+ dns = talloc_zero(task, struct dns_cleanup); >+ if (dns == NULL) { >+ task_server_terminate(task, "dns_cleanup: out of memory", true); >+ return; >+ } >+ >+ dns->task = task; >+ dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx, >+ system_session(dns->task->lp_ctx), 0); >+ if (dns->samdb == NULL) { >+ task_server_terminate(task, "dns_cleanup: samdb_connect failed", true); >+ return; >+ } >+ >+ if (samdb_rodc(dns->samdb, &is_rodc) != LDB_SUCCESS) { >+ task_server_terminate(task, "dns_cleanup: samdb_rodc failed", true); >+ return; >+ } >+ >+ if (is_rodc) { >+ task_server_terminate(task, "dns_cleanup: not required on a RODC", false); >+ return; >+ } >+ >+ dns->next_event = timeval_current_ofs(600, 0); >+ dns->te = tevent_add_timer(dns->task->event_ctx, dns, >+ dns->next_event, >+ dns_cleanup_timer, >+ dns); >+ if (dns->te == NULL) { >+ task_server_terminate(dns->task, >+ "dns_cleanup: tevent_add_time failed", true); >+ return; >+ } >+} >+ >+NTSTATUS server_service_dns_cleanup_init(void); >+NTSTATUS server_service_dns_cleanup_init(void) >+{ >+ return register_server_service("dns_cleanup", dns_cleanup_task_init); >+} >diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build >index a92ab67..c4974f7 100644 >--- a/source4/dns_server/wscript_build >+++ b/source4/dns_server/wscript_build >@@ -16,6 +16,16 @@ bld.SAMBA_MODULE('service_dns', > enabled=bld.AD_DC_BUILD_IS_ENABLED() > ) > >+bld.SAMBA_MODULE('service_dns_cleanup', >+ source='dns_cleanup.c', >+ subsystem='service', >+ init_function='server_service_dns_cleanup_init', >+ deps='samba-hostconfig ldbsamba clidns dnsserver_common', >+ local_include=False, >+ internal_module=False, >+ enabled=bld.AD_DC_BUILD_IS_ENABLED() >+ ) >+ > # a bind9 dlz module giving access to the Samba DNS SAM > bld.SAMBA_LIBRARY('dlz_bind9', > source='dlz_bind9.c', >-- >1.9.1 > > >From 867772e2b2f869c45cb41f412bc34e27ae42e1dd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 Aug 2014 22:32:04 +0200 >Subject: [PATCH 19/19] TODO start dns_cleanup > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=10749 >--- > docs-xml/smbdotconf/base/serverservices.xml | 2 +- > lib/param/loadparm.c | 2 +- > source3/param/loadparm.c | 2 +- > 3 files changed, 3 insertions(+), 3 deletions(-) > >diff --git a/docs-xml/smbdotconf/base/serverservices.xml b/docs-xml/smbdotconf/base/serverservices.xml >index e02e29d..4f592be 100644 >--- a/docs-xml/smbdotconf/base/serverservices.xml >+++ b/docs-xml/smbdotconf/base/serverservices.xml >@@ -13,6 +13,6 @@ > <constant>-</constant>. </para> > </description> > >-<value type="default">s3fs, rpc, nbt, wrepl, ldap, cldap, kdc, drepl, winbindd, ntp_signd, kcc, dnsupdate, dns</value> >+<value type="default">s3fs, rpc, nbt, wrepl, ldap, cldap, kdc, drepl, winbindd, ntp_signd, kcc, dnsupdate, dns, dns_cleanup</value> > <value type="example">-s3fs, +smb</value> > </samba:parameter> >diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c >index 4154260..ad453b5 100644 >--- a/lib/param/loadparm.c >+++ b/lib/param/loadparm.c >@@ -2431,7 +2431,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) > lpcfg_do_global_parameter(lp_ctx, "max connections", "0"); > > lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver"); >- lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns"); >+ lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns dns_cleanup"); > lpcfg_do_global_parameter(lp_ctx, "kccsrv:samba_kcc", "true"); > /* the winbind method for domain controllers is for both RODC > auth forwarding and for trusted domains */ >diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c >index c428c23..67a896e 100644 >--- a/source3/param/loadparm.c >+++ b/source3/param/loadparm.c >@@ -854,7 +854,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) > > string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR()); > >- Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL); >+ Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns dns_cleanup", NULL); > > Globals.dcerpc_endpoint_servers = (const char **)str_list_make_v3(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL); > >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 10749
:
10184
|
10202
|
10242
|
10243
|
10244
|
10248
|
10251
|
10252
|
10253
|
10255