mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
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>
This commit is contained in:
parent
ee4324ddc2
commit
4fb29e9347
@ -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
|
||||
@ -761,16 +763,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;
|
||||
@ -866,50 +942,31 @@ 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
status = dns_startup_interfaces(dns, ifaces);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
task_server_terminate(task, "dns failed to setup interfaces", true);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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 = 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 reload handler", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS server_service_dns_init(void)
|
||||
|
448
source4/dsdb/samdb/ldb_modules/dns_notify.c
Normal file
448
source4/dsdb/samdb/ldb_modules/dns_notify.c
Normal file
@ -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);
|
||||
}
|
@ -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 };
|
||||
|
@ -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'
|
||||
)
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user