summaryrefslogtreecommitdiff
path: root/source4/dns_server/dns_server.c
diff options
context:
space:
mode:
authorSamuel Cabrero <samuelcabrero@kernevil.me>2014-12-16 10:58:50 +0100
committerGarming Sam <garming@samba.org>2014-12-22 05:57:08 +0100
commit4fb29e9347271acd66833d471a84e39a525f4f18 (patch)
tree57c4021f0da81907e1fd5029b00257ee92154730 /source4/dns_server/dns_server.c
parentee4324ddc24dc6d92b2fdcf87e8dc63c631e2444 (diff)
downloadsamba-4fb29e9347271acd66833d471a84e39a525f4f18.tar.gz
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>
Diffstat (limited to 'source4/dns_server/dns_server.c')
-rw-r--r--source4/dns_server/dns_server.c133
1 files changed, 95 insertions, 38 deletions
diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c
index f1a4c4c747f..3e18287bfa1 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
@@ -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,48 +942,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;
}
}