The Samba-Bugzilla – Attachment 10822 Details for
Bug 9404
Adding a zone via the dnsserver RPC interface should trigger a zone reload in the internal DNS server
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
4.2 patch cherry-picked from master
dns-zone-reload-4.2.patch (text/plain), 34.74 KB, created by
Andrew Bartlett
on 2015-03-06 00:17:48 UTC
(
hide
)
Description:
4.2 patch cherry-picked from master
Filename:
MIME Type:
Creator:
Andrew Bartlett
Created:
2015-03-06 00:17:48 UTC
Size:
34.74 KB
patch
obsolete
>From e7abed8389e4bfaaf1a1c861db9f6a22582568a6 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 19 Dec 2014 14:58:01 +1300 >Subject: [PATCH 1/7] selftest: Run samba.tests.dns in :local environment so it > can access credentials > >This allows it to access the machine account, and use that to modify the DNS zones > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit ee4324ddc24dc6d92b2fdcf87e8dc63c631e2444) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > source4/selftest/tests.py | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py >index 8d03b40..4826191 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -278,7 +278,7 @@ for f in sorted(os.listdir(os.path.join(samba4srcdir, "../pidl/tests"))): > planperltestsuite("pidl.%s" % f[:-3], os.path.normpath(os.path.join(samba4srcdir, "../pidl/tests", f))) > > # DNS tests >-planpythontestsuite("fl2003dc", "samba.tests.dns") >+planpythontestsuite("fl2003dc:local", "samba.tests.dns") > for t in smbtorture4_testsuites("dns_internal."): > plansmbtorture4testsuite(t, "dc:local", '//$SERVER/whavever') > >-- >2.1.4 > > >From 4b7af45e4681f8d236f0a8abf55b7dffde215010 Mon Sep 17 00:00:00 2001 >From: Samuel Cabrero <samuelcabrero@kernevil.me> >Date: Tue, 16 Dec 2014 10:58:50 +0100 >Subject: [PATCH 2/7] s4-dns: Reload DNS zones from dsdb when zones are > modified through RPC or DRS > >Setup a RPC management call on the internal DNS server triggered a new LDB >module which sniffs dnsZone object add, delete and modify operations. This >way the notification is triggered when zones are modified either from RPC or >replicated by inbound DRS. > >Signed-off-by: Samuel Cabrero <samuelcabrero@kernevil.me> >(shadowed variable error corrected by abartlet) >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> > >(cherry picked from commit 4fb29e9347271acd66833d471a84e39a525f4f18) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > source4/dns_server/dns_server.c | 133 ++++-- > source4/dsdb/samdb/ldb_modules/dns_notify.c | 448 +++++++++++++++++++++ > source4/dsdb/samdb/ldb_modules/samba_dsdb.c | 3 +- > .../dsdb/samdb/ldb_modules/wscript_build_server | 9 + > source4/librpc/idl/irpc.idl | 11 + > 5 files changed, 565 insertions(+), 39 deletions(-) > create mode 100644 source4/dsdb/samdb/ldb_modules/dns_notify.c > >diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c >index 7ea70db..c432236 100644 >--- a/source4/dns_server/dns_server.c >+++ b/source4/dns_server/dns_server.c >@@ -45,6 +45,8 @@ > #include "lib/util/tevent_werror.h" > #include "auth/auth.h" > #include "auth/credentials/credentials.h" >+#include "librpc/gen_ndr/ndr_irpc.h" >+#include "lib/messaging/irpc.h" > > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_DNS >@@ -760,16 +762,90 @@ static struct dns_server_tkey_store *tkey_store_init(TALLOC_CTX *mem_ctx, > return buffer; > } > >+static NTSTATUS dns_server_reload_zones(struct dns_server *dns) >+{ >+ int ret; >+ static const char * const attrs[] = { "name", NULL}; >+ struct ldb_result *res; >+ int i; >+ struct dns_server_zone *new_list = NULL; >+ struct dns_server_zone *old_list = NULL; >+ struct dns_server_zone *old_zone; >+ >+ // TODO: this search does not work against windows >+ ret = dsdb_search(dns->samdb, dns, &res, NULL, LDB_SCOPE_SUBTREE, >+ attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)"); >+ if (ret != LDB_SUCCESS) { >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ >+ TYPESAFE_QSORT(res->msgs, res->count, dns_server_sort_zones); >+ >+ for (i=0; i < res->count; i++) { >+ struct dns_server_zone *z; >+ >+ z = talloc_zero(dns, struct dns_server_zone); >+ if (z == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL); >+ z->dn = talloc_move(z, &res->msgs[i]->dn); >+ /* >+ * Ignore the RootDNSServers zone and zones that we don't support yet >+ * RootDNSServers should never be returned (Windows DNS server don't) >+ * ..TrustAnchors should never be returned as is, (Windows returns >+ * TrustAnchors) and for the moment we don't support DNSSEC so we'd better >+ * not return this zone. >+ */ >+ if ((strcmp(z->name, "RootDNSServers") == 0) || >+ (strcmp(z->name, "..TrustAnchors") == 0)) >+ { >+ DEBUG(10, ("Ignoring zone %s\n", z->name)); >+ talloc_free(z); >+ continue; >+ } >+ DLIST_ADD_END(new_list, z, NULL); >+ } >+ >+ old_list = dns->zones; >+ dns->zones = new_list; >+ while ((old_zone = DLIST_TAIL(old_list)) != NULL) { >+ DLIST_REMOVE(old_list, old_zone); >+ talloc_free(old_zone); >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+/** >+ * Called when the internal DNS server should reload the zones from DB, for >+ * example, when zones are added or deleted through RPC or replicated by >+ * inbound DRS. >+ */ >+static NTSTATUS dns_reload_zones(struct irpc_message *msg, >+ struct dnssrv_reload_dns_zones *r) >+{ >+ struct dns_server *dns; >+ >+ dns = talloc_get_type(msg->private_data, struct dns_server); >+ if (dns == NULL) { >+ r->out.result = NT_STATUS_INTERNAL_ERROR; >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ r->out.result = dns_server_reload_zones(dns); >+ >+ return NT_STATUS_OK; >+} >+ > static void dns_task_init(struct task_server *task) > { > struct dns_server *dns; > NTSTATUS status; > struct interface *ifaces = NULL; > int ret; >- struct ldb_result *res; >- static const char * const attrs[] = { "name", NULL}; > static const char * const attrs_none[] = { NULL}; >- unsigned int i; > struct ldb_message *dns_acc; > char *hostname_lower; > char *dns_spn; >@@ -865,48 +941,29 @@ static void dns_task_init(struct task_server *task) > return; > } > >- // TODO: this search does not work against windows >- ret = dsdb_search(dns->samdb, dns, &res, NULL, LDB_SCOPE_SUBTREE, >- attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)"); >- if (ret != LDB_SUCCESS) { >- task_server_terminate(task, >- "dns: failed to look up root DNS zones", >- true); >+ status = dns_server_reload_zones(dns); >+ if (!NT_STATUS_IS_OK(status)) { >+ task_server_terminate(task, "dns: failed to load DNS zones", true); > return; > } > >- TYPESAFE_QSORT(res->msgs, res->count, dns_server_sort_zones); >- >- for (i=0; i < res->count; i++) { >- struct dns_server_zone *z; >- >- z = talloc_zero(dns, struct dns_server_zone); >- if (z == NULL) { >- task_server_terminate(task, "dns failed to allocate memory", true); >- } >+ status = dns_startup_interfaces(dns, ifaces); >+ if (!NT_STATUS_IS_OK(status)) { >+ task_server_terminate(task, "dns failed to setup interfaces", true); >+ return; >+ } > >- z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL); >- z->dn = talloc_move(z, &res->msgs[i]->dn); >- /* >- * Ignore the RootDNSServers zone and zones that we don't support yet >- * RootDNSServers should never be returned (Windows DNS server don't) >- * ..TrustAnchors should never be returned as is, (Windows returns >- * TrustAnchors) and for the moment we don't support DNSSEC so we'd better >- * not return this zone. >- */ >- if ((strcmp(z->name, "RootDNSServers") == 0) || >- (strcmp(z->name, "..TrustAnchors") == 0)) >- { >- DEBUG(10, ("Ignoring zone %s\n", z->name)); >- talloc_free(z); >- continue; >- } >- DLIST_ADD_END(dns->zones, z, NULL); >+ /* Setup the IRPC interface and register handlers */ >+ status = irpc_add_name(task->msg_ctx, "dnssrv"); >+ if (!NT_STATUS_IS_OK(status)) { >+ task_server_terminate(task, "dns: failed to register IRPC name", true); >+ return; > } > >- status = dns_startup_interfaces(dns, ifaces); >+ status = IRPC_REGISTER(task->msg_ctx, irpc, DNSSRV_RELOAD_DNS_ZONES, >+ dns_reload_zones, dns); > if (!NT_STATUS_IS_OK(status)) { >- task_server_terminate(task, "dns failed to setup interfaces", true); >+ task_server_terminate(task, "dns: failed to setup reload handler", true); > return; > } > } >diff --git a/source4/dsdb/samdb/ldb_modules/dns_notify.c b/source4/dsdb/samdb/ldb_modules/dns_notify.c >new file mode 100644 >index 0000000..28a1be9 >--- /dev/null >+++ b/source4/dsdb/samdb/ldb_modules/dns_notify.c >@@ -0,0 +1,448 @@ >+/* >+ ldb database library >+ >+ Copyright (C) Samuel Cabrero <samuelcabrero@kernevil.me> 2014 >+ >+ 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/>. >+*/ >+ >+/* >+ * Name: ldb >+ * >+ * Component: ldb dns_notify module >+ * >+ * Description: Notify the DNS server when zones are changed, either by direct >+ * RPC management calls or DRS inbound replication. >+ * >+ * Author: Samuel Cabrero <samuelcabrero@kernevil.me> >+ */ >+ >+#include "includes.h" >+#include "ldb_module.h" >+#include "dsdb/samdb/ldb_modules/util.h" >+#include "dsdb/samdb/samdb.h" >+#include "dsdb/common/proto.h" >+#include "librpc/gen_ndr/ndr_irpc.h" >+#include "lib/messaging/irpc.h" >+#include "librpc/gen_ndr/ndr_irpc_c.h" >+#include "param/param.h" >+#include "dlinklist.h" >+ >+struct dns_notify_watched_dn { >+ struct dns_notify_watched_dn *next, *prev; >+ struct ldb_dn *dn; >+}; >+ >+struct dns_notify_private { >+ struct dns_notify_watched_dn *watched; >+ bool reload_zones; >+}; >+ >+struct dns_notify_dnssrv_state { >+ struct imessaging_context *msg_ctx; >+ struct dnssrv_reload_dns_zones r; >+}; >+ >+static void dns_notify_dnssrv_done(struct tevent_req *req) >+{ >+ NTSTATUS status; >+ struct dns_notify_dnssrv_state *state; >+ >+ state = tevent_req_callback_data(req, struct dns_notify_dnssrv_state); >+ >+ status = dcerpc_dnssrv_reload_dns_zones_r_recv(req, state); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(1, ("%s: Error notifiying dns server: %s\n", >+ __func__, nt_errstr(status))); >+ } >+ imessaging_cleanup(state->msg_ctx); >+ >+ talloc_free(req); >+ talloc_free(state); >+} >+ >+static void dns_notify_dnssrv_send(struct ldb_module *module) >+{ >+ struct ldb_context *ldb; >+ struct loadparm_context *lp_ctx; >+ struct dns_notify_dnssrv_state *state; >+ struct dcerpc_binding_handle *handle; >+ struct tevent_req *req; >+ >+ ldb = ldb_module_get_ctx(module); >+ >+ lp_ctx = ldb_get_opaque(ldb, "loadparm"); >+ if (lp_ctx == NULL) { >+ return; >+ } >+ >+ state = talloc_zero(module, struct dns_notify_dnssrv_state); >+ if (state == NULL) { >+ return; >+ } >+ >+ /* Initialize messaging client */ >+ state->msg_ctx = imessaging_client_init(state, lp_ctx, >+ ldb_get_event_context(ldb)); >+ if (state->msg_ctx == NULL) { >+ ldb_asprintf_errstring(ldb, "Failed to generate client messaging context in %s", >+ lpcfg_imessaging_path(state, lp_ctx)); >+ talloc_free(state); >+ return; >+ } >+ >+ /* Get a handle to notify the DNS server */ >+ handle = irpc_binding_handle_by_name(state, state->msg_ctx, >+ "dnssrv", >+ &ndr_table_irpc); >+ if (handle == NULL) { >+ imessaging_cleanup(state->msg_ctx); >+ talloc_free(state); >+ return; >+ } >+ >+ /* Send the notifications */ >+ req = dcerpc_dnssrv_reload_dns_zones_r_send(state, >+ ldb_get_event_context(ldb), >+ handle, >+ &state->r); >+ if (req == NULL) { >+ imessaging_cleanup(state->msg_ctx); >+ talloc_free(state); >+ return; >+ } >+ tevent_req_set_callback(req, dns_notify_dnssrv_done, state); >+} >+ >+static int dns_notify_add(struct ldb_module *module, struct ldb_request *req) >+{ >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ struct dns_notify_watched_dn *w; >+ struct dsdb_schema *schema; >+ const struct dsdb_class *objectclass; >+ >+ if (ldb_dn_is_special(req->op.add.message->dn)) { >+ return ldb_next_request(module, req); >+ } >+ >+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { >+ return ldb_next_request(module, req); >+ } >+ >+ ldb = ldb_module_get_ctx(module); >+ data = talloc_get_type(ldb_module_get_private(module), >+ struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ for (w = data->watched; w; w = w->next) { >+ if (ldb_dn_compare_base(w->dn, req->op.add.message->dn) == 0) { >+ schema = dsdb_get_schema(ldb, req); >+ if (schema == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ objectclass = dsdb_get_structural_oc_from_msg(schema, req->op.add.message); >+ if (objectclass == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ if (strcasecmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { >+ data->reload_zones = true; >+ break; >+ } >+ } >+ } >+ >+ return ldb_next_request(module, req); >+} >+ >+static int dns_notify_modify(struct ldb_module *module, struct ldb_request *req) >+{ >+ TALLOC_CTX *tmp_ctx; >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ struct dns_notify_watched_dn *w; >+ struct ldb_dn *dn; >+ struct ldb_result *res; >+ struct dsdb_schema *schema; >+ const struct dsdb_class *objectclass; >+ int ret; >+ >+ if (ldb_dn_is_special(req->op.mod.message->dn)) { >+ return ldb_next_request(module, req); >+ } >+ >+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { >+ return ldb_next_request(module, req); >+ } >+ >+ ldb = ldb_module_get_ctx(module); >+ data = talloc_get_type(ldb_module_get_private(module), >+ struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ tmp_ctx = talloc_new(module); >+ if (tmp_ctx == NULL) { >+ return ldb_oom(ldb); >+ } >+ >+ for (w = data->watched; w; w = w->next) { >+ if (ldb_dn_compare_base(w->dn, req->op.add.message->dn) == 0) { >+ dn = ldb_dn_copy(tmp_ctx, req->op.mod.message->dn); >+ >+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, NULL, >+ DSDB_FLAG_NEXT_MODULE | >+ DSDB_SEARCH_SHOW_RECYCLED | >+ DSDB_SEARCH_REVEAL_INTERNALS | >+ DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req); >+ if (ret != LDB_SUCCESS) { >+ ldb_asprintf_errstring(ldb_module_get_ctx(module), >+ "%s: Failed to modify %s, because we failed to find it: %s\n", >+ __func__, >+ ldb_dn_get_linearized(dn), >+ ldb_errstring(ldb_module_get_ctx(module))); >+ talloc_free(tmp_ctx); >+ return ret; >+ } >+ >+ schema = dsdb_get_schema(ldb, req); >+ if (schema == NULL) { >+ talloc_free(tmp_ctx); >+ return ldb_operr(ldb); >+ } >+ >+ objectclass = dsdb_get_structural_oc_from_msg(schema, res->msgs[0]); >+ if (objectclass == NULL) { >+ talloc_free(tmp_ctx); >+ return ldb_operr(ldb); >+ } >+ >+ if (strcasecmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { >+ data->reload_zones = true; >+ break; >+ } >+ } >+ } >+ >+ talloc_free(tmp_ctx); >+ return ldb_next_request(module, req); >+} >+ >+static int dns_notify_delete(struct ldb_module *module, struct ldb_request *req) >+{ >+ TALLOC_CTX *tmp_ctx; >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ struct dns_notify_watched_dn *w; >+ struct ldb_dn *old_dn; >+ struct ldb_result *res; >+ struct dsdb_schema *schema; >+ const struct dsdb_class *objectclass; >+ int ret; >+ >+ if (ldb_dn_is_special(req->op.del.dn)) { >+ return ldb_next_request(module, req); >+ } >+ >+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { >+ return ldb_next_request(module, req); >+ } >+ >+ ldb = ldb_module_get_ctx(module); >+ data = talloc_get_type(ldb_module_get_private(module), >+ struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ tmp_ctx = talloc_new(module); >+ if (tmp_ctx == NULL) { >+ return ldb_oom(ldb); >+ } >+ >+ for (w = data->watched; w; w = w->next) { >+ if (ldb_dn_compare_base(w->dn, req->op.add.message->dn) == 0) { >+ old_dn = ldb_dn_copy(tmp_ctx, req->op.del.dn); >+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, old_dn, NULL, >+ DSDB_FLAG_NEXT_MODULE | >+ DSDB_SEARCH_SHOW_RECYCLED | >+ DSDB_SEARCH_REVEAL_INTERNALS | >+ DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req); >+ if (ret != LDB_SUCCESS) { >+ ldb_asprintf_errstring(ldb_module_get_ctx(module), >+ "%s: Failed to delete %s, because we failed to find it: %s\n", >+ __func__, >+ ldb_dn_get_linearized(old_dn), >+ ldb_errstring(ldb_module_get_ctx(module))); >+ talloc_free(tmp_ctx); >+ return ret; >+ } >+ >+ schema = dsdb_get_schema(ldb, req); >+ if (schema == NULL) { >+ talloc_free(tmp_ctx); >+ return ldb_operr(ldb); >+ } >+ >+ objectclass = dsdb_get_structural_oc_from_msg(schema, res->msgs[0]); >+ if (objectclass == NULL) { >+ talloc_free(tmp_ctx); >+ return ldb_operr(ldb); >+ } >+ >+ if (strcasecmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { >+ data->reload_zones = true; >+ break; >+ } >+ } >+ } >+ >+ talloc_free(tmp_ctx); >+ return ldb_next_request(module, req); >+} >+ >+static int dns_notify_start_trans(struct ldb_module *module) >+{ >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ >+ ldb = ldb_module_get_ctx(module); >+ data = talloc_get_type(ldb_module_get_private(module), >+ struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ data->reload_zones = false; >+ >+ return ldb_next_start_trans(module); >+} >+ >+static int dns_notify_end_trans(struct ldb_module *module) >+{ >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ int ret; >+ >+ ldb = ldb_module_get_ctx(module); >+ data = talloc_get_type(ldb_module_get_private(module), >+ struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ ret = ldb_next_end_trans(module); >+ if (ret == LDB_SUCCESS) { >+ if (data->reload_zones) { >+ dns_notify_dnssrv_send(module); >+ } >+ } >+ >+ return ret; >+} >+ >+static int dns_notify_del_trans(struct ldb_module *module) >+{ >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ >+ ldb = ldb_module_get_ctx(module); >+ data = talloc_get_type(ldb_module_get_private(module), >+ struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_operr(ldb); >+ } >+ >+ data->reload_zones = false; >+ >+ return ldb_next_del_trans(module); >+} >+ >+static int dns_notify_init(struct ldb_module *module) >+{ >+ struct ldb_context *ldb; >+ struct dns_notify_private *data; >+ struct dns_notify_watched_dn *watched; >+ struct ldb_dn *domain_dn; >+ struct ldb_dn *forest_dn; >+ >+ ldb = ldb_module_get_ctx(module); >+ >+ data = talloc_zero(module, struct dns_notify_private); >+ if (data == NULL) { >+ return ldb_oom(ldb); >+ } >+ >+ domain_dn = ldb_get_default_basedn(ldb); >+ forest_dn = ldb_get_root_basedn(ldb); >+ >+ /* Register hook on domain partition */ >+ watched = talloc_zero(data, struct dns_notify_watched_dn); >+ if (watched == NULL) { >+ talloc_free(data); >+ return ldb_oom(ldb); >+ } >+ watched->dn = ldb_dn_new_fmt(watched, ldb, >+ "CN=MicrosoftDNS,CN=System,%s", >+ ldb_dn_get_linearized(domain_dn)); >+ if (watched->dn == NULL) { >+ talloc_free(data); >+ return ldb_oom(ldb); >+ } >+ DLIST_ADD(data->watched, watched); >+ >+ /* Check for DomainDnsZones partition and register hook */ >+ watched = talloc_zero(data, struct dns_notify_watched_dn); >+ if (watched == NULL) { >+ talloc_free(data); >+ return ldb_oom(ldb); >+ } >+ watched->dn = ldb_dn_new_fmt(watched, ldb, "CN=MicrosoftDNS,DC=DomainDnsZones,%s", ldb_dn_get_linearized(forest_dn)); >+ DLIST_ADD(data->watched, watched); >+ >+ /* Check for ForestDnsZones partition and register hook */ >+ watched = talloc_zero(data, struct dns_notify_watched_dn); >+ if (watched == NULL) { >+ talloc_free(data); >+ return ldb_oom(ldb); >+ } >+ watched->dn = ldb_dn_new_fmt(watched, ldb, "CN=MicrosoftDNS,DC=ForestDnsZones,%s", ldb_dn_get_linearized(forest_dn)); >+ DLIST_ADD(data->watched, watched); >+ >+ ldb_module_set_private(module, data); >+ >+ return ldb_next_init(module); >+} >+ >+static const struct ldb_module_ops ldb_dns_notify_module_ops = { >+ .name = "dns_notify", >+ .init_context = dns_notify_init, >+ .add = dns_notify_add, >+ .modify = dns_notify_modify, >+ .del = dns_notify_delete, >+ .start_transaction = dns_notify_start_trans, >+ .end_transaction = dns_notify_end_trans, >+ .del_transaction = dns_notify_del_trans, >+}; >+ >+int ldb_dns_notify_module_init(const char *version) >+{ >+ LDB_MODULE_CHECK_VERSION(version); >+ return ldb_register_module(&ldb_dns_notify_module_ops); >+} >diff --git a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c >index 086b11f..26c583e 100644 >--- a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c >+++ b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c >@@ -302,7 +302,8 @@ static int samba_dsdb_init(struct ldb_module *module) > const char *extended_dn_module_openldap = "extended_dn_out_openldap"; > const char *extended_dn_in_module = "extended_dn_in"; > >- static const char *modules_list2[] = {"show_deleted", >+ static const char *modules_list2[] = {"dns_notify", >+ "show_deleted", > "new_partition", > "partition", > NULL }; >diff --git a/source4/dsdb/samdb/ldb_modules/wscript_build_server b/source4/dsdb/samdb/ldb_modules/wscript_build_server >index 0307aea..8848fd2 100755 >--- a/source4/dsdb/samdb/ldb_modules/wscript_build_server >+++ b/source4/dsdb/samdb/ldb_modules/wscript_build_server >@@ -364,3 +364,12 @@ bld.SAMBA_MODULE('ldb_dirsync', > internal_module=False, > deps='talloc samba-security samdb DSDB_MODULE_HELPERS' > ) >+ >+bld.SAMBA_MODULE('ldb_dns_notify', >+ source='dns_notify.c', >+ subsystem='ldb', >+ init_function='ldb_dns_notify_module_init', >+ module_init_name='ldb_init_module', >+ internal_module=False, >+ deps='talloc samdb DSDB_MODULE_HELPERS MESSAGING RPC_NDR_IRPC' >+ ) >\ No newline at end of file >diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl >index 6a55eef..65ae4b6 100644 >--- a/source4/librpc/idl/irpc.idl >+++ b/source4/librpc/idl/irpc.idl >@@ -207,4 +207,15 @@ import "misc.idl", "security.idl", "nbt.idl", "netlogon.idl", "server_id.idl"; > [in] uint32 dns_ttl, > [in,out,ref] NL_DNS_NAME_INFO_ARRAY *dns_names > ); >+ >+ /****************************************************** >+ * Management calls for the dns server >+ ******************************************************/ >+ /** >+ * Force internal DNS server to reload the DNS zones. >+ * >+ * Called when zones are added or deleted through RPC >+ * or replicated by DRS. >+ */ >+ NTSTATUS dnssrv_reload_dns_zones(); > } >-- >2.1.4 > > >From a1d4a7c1907bd5f08eee56bbc1b06218509369f9 Mon Sep 17 00:00:00 2001 >From: Samuel Cabrero <samuelcabrero@kernevil.me> >Date: Tue, 16 Dec 2014 18:04:13 +0100 >Subject: [PATCH 3/7] dns.py: Test dns server reload zones from DSDB when are > created or deleted > >Signed-off-by: Samuel Cabrero <samuelcabrero@kernevil.me> > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >(cherry picked from commit 336ffb29b50298a0597c15b9f60416adb745bc3d) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > python/samba/tests/dns.py | 78 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 78 insertions(+) > >diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py >index f93e13f..b8ce32a 100644 >--- a/python/samba/tests/dns.py >+++ b/python/samba/tests/dns.py >@@ -21,7 +21,9 @@ import random > import socket > import samba.ndr as ndr > import samba.dcerpc.dns as dns >+from samba import credentials, param > from samba.tests import TestCase >+from samba.dcerpc import dnsp, dnsserver > > FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) > >@@ -862,6 +864,82 @@ class TestInvalidQueries(DNSTest): > if s is not None: > s.close() > >+class TestZones(DNSTest): >+ def get_loadparm(self): >+ lp = param.LoadParm() >+ lp.load(os.getenv("SMB_CONF_PATH")) >+ return lp >+ >+ def get_credentials(self, lp): >+ creds = credentials.Credentials() >+ creds.guess(lp) >+ creds.set_machine_account(lp) >+ creds.set_krb_forwardable(credentials.NO_KRB_FORWARDABLE) >+ return creds >+ >+ def setUp(self): >+ super(TestZones, self).setUp() >+ self.lp = self.get_loadparm() >+ self.creds = self.get_credentials(self.lp) >+ self.server = os.getenv("SERVER_IP") >+ self.zone = "test.lan" >+ self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s" % (self.server), >+ self.lp, self.creds) >+ >+ def create_zone(self, zone): >+ zone_create = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN() >+ zone_create.pszZoneName = zone >+ zone_create.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY >+ zone_create.fAllowUpdate = dnsp.DNS_ZONE_UPDATE_SECURE >+ zone_create.fAging = 0 >+ zone_create.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT >+ self.rpc_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, >+ 0, >+ self.server, >+ None, >+ 0, >+ 'ZoneCreate', >+ dnsserver.DNSSRV_TYPEID_ZONE_CREATE, >+ zone_create) >+ >+ def delete_zone(self, zone): >+ self.rpc_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN, >+ 0, >+ self.server, >+ zone, >+ 0, >+ 'DeleteZoneFromDs', >+ dnsserver.DNSSRV_TYPEID_NULL, >+ None) >+ >+ def test_soa_query(self): >+ zone = "test.lan" >+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY) >+ questions = [] >+ >+ q = self.make_name_question(zone, dns.DNS_QTYPE_SOA, 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) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 0) >+ >+ self.create_zone(zone) >+ response = self.dns_transaction_udp(p) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 1) >+ self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_SOA) >+ >+ self.delete_zone(zone) >+ response = self.dns_transaction_udp(p) >+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN) >+ self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) >+ self.assertEquals(response.ancount, 0) >+ >+ > > if __name__ == "__main__": > import unittest >-- >2.1.4 > > >From e6353e12698d0e19cef05f7065c9f31ce81f1971 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 19 Dec 2014 14:40:28 +1300 >Subject: [PATCH 4/7] dsdb: Use ldb_attr_cmp() for comparing objectclass names > >This is the same as strcasecmp, but it is best to remain consistent. > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit e9f6dc730df7c496b743f258b03d6fbcef76211e) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > source4/dsdb/samdb/ldb_modules/dns_notify.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > >diff --git a/source4/dsdb/samdb/ldb_modules/dns_notify.c b/source4/dsdb/samdb/ldb_modules/dns_notify.c >index 28a1be9..2d3ed86 100644 >--- a/source4/dsdb/samdb/ldb_modules/dns_notify.c >+++ b/source4/dsdb/samdb/ldb_modules/dns_notify.c >@@ -160,7 +160,7 @@ static int dns_notify_add(struct ldb_module *module, struct ldb_request *req) > return ldb_operr(ldb); > } > >- if (strcasecmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { >+ if (ldb_attr_cmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { > data->reload_zones = true; > break; > } >@@ -233,7 +233,7 @@ static int dns_notify_modify(struct ldb_module *module, struct ldb_request *req) > return ldb_operr(ldb); > } > >- if (strcasecmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { >+ if (ldb_attr_cmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { > data->reload_zones = true; > break; > } >@@ -306,7 +306,7 @@ static int dns_notify_delete(struct ldb_module *module, struct ldb_request *req) > return ldb_operr(ldb); > } > >- if (strcasecmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { >+ if (ldb_attr_cmp(objectclass->lDAPDisplayName, "dnsZone") == 0) { > data->reload_zones = true; > break; > } >-- >2.1.4 > > >From 204854507cfc3f484e10a30e2e8e428e1ed278ea Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 19 Dec 2014 14:41:40 +1300 >Subject: [PATCH 5/7] dsdb: Use a fixed set of attributes in search in > dns_notify module > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit bb886401e8b1c991684c0b9d855b976728e44f13) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > source4/dsdb/samdb/ldb_modules/dns_notify.c | 6 ++++-- > 1 file changed, 4 insertions(+), 2 deletions(-) > >diff --git a/source4/dsdb/samdb/ldb_modules/dns_notify.c b/source4/dsdb/samdb/ldb_modules/dns_notify.c >index 2d3ed86..bee6a6e 100644 >--- a/source4/dsdb/samdb/ldb_modules/dns_notify.c >+++ b/source4/dsdb/samdb/ldb_modules/dns_notify.c >@@ -180,6 +180,7 @@ static int dns_notify_modify(struct ldb_module *module, struct ldb_request *req) > struct ldb_result *res; > struct dsdb_schema *schema; > const struct dsdb_class *objectclass; >+ const char * const attrs[] = { "objectClass", NULL }; > int ret; > > if (ldb_dn_is_special(req->op.mod.message->dn)) { >@@ -206,7 +207,7 @@ static int dns_notify_modify(struct ldb_module *module, struct ldb_request *req) > if (ldb_dn_compare_base(w->dn, req->op.add.message->dn) == 0) { > dn = ldb_dn_copy(tmp_ctx, req->op.mod.message->dn); > >- ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, NULL, >+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs, > DSDB_FLAG_NEXT_MODULE | > DSDB_SEARCH_SHOW_RECYCLED | > DSDB_SEARCH_REVEAL_INTERNALS | >@@ -254,6 +255,7 @@ static int dns_notify_delete(struct ldb_module *module, struct ldb_request *req) > struct ldb_result *res; > struct dsdb_schema *schema; > const struct dsdb_class *objectclass; >+ const char * const attrs[] = { "objectClass", NULL }; > int ret; > > if (ldb_dn_is_special(req->op.del.dn)) { >@@ -279,7 +281,7 @@ static int dns_notify_delete(struct ldb_module *module, struct ldb_request *req) > for (w = data->watched; w; w = w->next) { > if (ldb_dn_compare_base(w->dn, req->op.add.message->dn) == 0) { > old_dn = ldb_dn_copy(tmp_ctx, req->op.del.dn); >- ret = dsdb_module_search_dn(module, tmp_ctx, &res, old_dn, NULL, >+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, old_dn, attrs, > DSDB_FLAG_NEXT_MODULE | > DSDB_SEARCH_SHOW_RECYCLED | > DSDB_SEARCH_REVEAL_INTERNALS | >-- >2.1.4 > > >From a957f66483b913c1fdf6ac0313cd7610385e904c Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 19 Dec 2014 14:42:08 +1300 >Subject: [PATCH 6/7] dsdb: Ignore errors from search in dns_notify module > >This ensures the error messages are unchanged > >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit eabc177bf674a43f6b9442c8a89af0203befb3f1) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > source4/dsdb/samdb/ldb_modules/dns_notify.c | 26 ++++++++++++-------------- > 1 file changed, 12 insertions(+), 14 deletions(-) > >diff --git a/source4/dsdb/samdb/ldb_modules/dns_notify.c b/source4/dsdb/samdb/ldb_modules/dns_notify.c >index bee6a6e..2481a41 100644 >--- a/source4/dsdb/samdb/ldb_modules/dns_notify.c >+++ b/source4/dsdb/samdb/ldb_modules/dns_notify.c >@@ -213,13 +213,12 @@ static int dns_notify_modify(struct ldb_module *module, struct ldb_request *req) > DSDB_SEARCH_REVEAL_INTERNALS | > DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req); > if (ret != LDB_SUCCESS) { >- ldb_asprintf_errstring(ldb_module_get_ctx(module), >- "%s: Failed to modify %s, because we failed to find it: %s\n", >- __func__, >- ldb_dn_get_linearized(dn), >- ldb_errstring(ldb_module_get_ctx(module))); >- talloc_free(tmp_ctx); >- return ret; >+ /* >+ * We want the give the caller the >+ * error from trying the actual >+ * request, below >+ */ >+ break; > } > > schema = dsdb_get_schema(ldb, req); >@@ -287,13 +286,12 @@ static int dns_notify_delete(struct ldb_module *module, struct ldb_request *req) > DSDB_SEARCH_REVEAL_INTERNALS | > DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req); > if (ret != LDB_SUCCESS) { >- ldb_asprintf_errstring(ldb_module_get_ctx(module), >- "%s: Failed to delete %s, because we failed to find it: %s\n", >- __func__, >- ldb_dn_get_linearized(old_dn), >- ldb_errstring(ldb_module_get_ctx(module))); >- talloc_free(tmp_ctx); >- return ret; >+ /* >+ * We want the give the caller the >+ * error from trying the actual >+ * request, below >+ */ >+ break; > } > > schema = dsdb_get_schema(ldb, req); >-- >2.1.4 > > >From e91a9daa4ce3085dcb603c3aa2bf70deb7422399 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Fri, 19 Dec 2014 15:14:22 +1300 >Subject: [PATCH 7/7] dns.py: Always remove the test zone in tearDown() > >Change-Id: Ic6d6c51579f8859b4e396179123974382c253bf7 >Signed-off-by: Garming Sam <garming@catalyst.net.nz> >Pair-programmed-with: Garming Sam <garming@catalyst.net.nz> >Signed-off-by: Andrew Bartlett <abartlet@samba.org> > >Autobuild-User(master): Garming Sam <garming@samba.org> >Autobuild-Date(master): Mon Dec 22 08:21:22 CET 2014 on sn-devel-104 > >(cherry picked from commit ad074795e33b676595aa7fb1b0129a0b5b8cbf24) >BUG: https://bugzilla.samba.org/show_bug.cgi?id=9404 >--- > python/samba/tests/dns.py | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py >index b8ce32a..92b94a6 100644 >--- a/python/samba/tests/dns.py >+++ b/python/samba/tests/dns.py >@@ -886,6 +886,14 @@ class TestZones(DNSTest): > self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s" % (self.server), > self.lp, self.creds) > >+ def tearDown(self): >+ super(TestZones, self).tearDown() >+ try: >+ self.delete_zone(self.zone) >+ except RuntimeError, (num, string): >+ if num != 9601: #WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST >+ raise >+ > def create_zone(self, zone): > zone_create = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN() > zone_create.pszZoneName = zone >-- >2.1.4 >
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
Flags:
garming
:
review+
abartlet
:
review?
(
metze
)
Actions:
View
Attachments on
bug 9404
:
10524
|
10525
|
10821
| 10822