s4:rpc-dnsserver: Cache DNS partition information
authorAmitay Isaacs <amitay@gmail.com>
Thu, 15 Dec 2011 06:44:32 +0000 (17:44 +1100)
committerAmitay Isaacs <amitay@gmail.com>
Fri, 23 Dec 2011 05:17:09 +0000 (16:17 +1100)
This information will be used for the RPC calls for partition
information.

source4/rpc_server/dnsserver/dcerpc_dnsserver.c
source4/rpc_server/dnsserver/dnsdb.c
source4/rpc_server/dnsserver/dnsserver.h
source4/rpc_server/dnsserver/dnsutils.c

index 98e935ca991ee3b8791014489806bbf996333680..715b8a6c37fa006637b0fe71643a2511a7ca4d0f 100644 (file)
@@ -31,6 +31,7 @@
 struct dnsserver_state {
        struct loadparm_context *lp_ctx;
        struct ldb_context *samdb;
+       struct dnsserver_partition *partitions;
        struct dnsserver_zone *zones;
        int zones_count;
        struct dnsserver_serverinfo *serverinfo;
@@ -42,7 +43,8 @@ struct dnsserver_state {
 static struct dnsserver_state *dnsserver_connect(struct dcesrv_call_state *dce_call)
 {
        struct dnsserver_state *dsstate;
-       struct dnsserver_zone *zones, *z;
+       struct dnsserver_zone *zones, *z, *znext;
+       struct dnsserver_partition *partitions, *p;
 
        dsstate = talloc_get_type(dce_call->context->private_data, struct dnsserver_state);
        if (dsstate != NULL) {
@@ -72,31 +74,30 @@ static struct dnsserver_state *dnsserver_connect(struct dcesrv_call_state *dce_c
                goto failed;
        }
 
-       /* Search for DNS zones */
-       zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, true);
-       if (zones == NULL) {
+       /* Search for DNS partitions */
+       partitions = dnsserver_db_enumerate_partitions(dsstate, dsstate->serverinfo, dsstate->samdb);
+       if (partitions == NULL) {
                goto failed;
        }
-       for (z = zones; z; z = z->next) {
-               z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo, true);
-               if (z->zoneinfo == NULL) {
-                       goto failed;
-               }
-               DLIST_ADD_END(dsstate->zones, z, NULL);
-               dsstate->zones_count++;
-       }
+       dsstate->partitions = partitions;
 
-       zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, false);
-       if (zones == NULL) {
-               goto failed;
-       }
-       for (z = zones; z; z = z->next) {
-               z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo, false);
-               if (z->zoneinfo == NULL) {
+       /* Search for DNS zones */
+       for (p = partitions; p; p = p->next) {
+               zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, p);
+               if (zones == NULL) {
                        goto failed;
                }
-               DLIST_ADD_END(dsstate->zones, z, NULL);
-               dsstate->zones_count++;
+               for (z = zones; z; ) {
+                       znext = z->next;
+                       z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo);
+                       if (z->zoneinfo == NULL) {
+                               goto failed;
+                       }
+                       DLIST_ADD_END(dsstate->zones, z, NULL);
+                       p->zones_count++;
+                       dsstate->zones_count++;
+                       z = znext;
+               }
        }
 
        dce_call->context->private_data = dsstate;
@@ -773,8 +774,8 @@ static WERROR dnsserver_query_zone(struct dnsserver_state *dsstate,
                        r->Zone->Flags = zoneinfo->Flags;
                        r->Zone->ZoneType = zoneinfo->dwZoneType;
                        r->Zone->Version = zoneinfo->Version;
-                       r->Zone->dwDpFlags = zoneinfo->dwDpFlags;
-                       r->Zone->pszDpFqdn = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
+                       r->Zone->dwDpFlags = z->partition->dwDpFlags;
+                       r->Zone->pszDpFqdn = talloc_strdup(mem_ctx, z->partition->pszDpFqdn);
                }
                return WERR_OK;
        }
@@ -835,8 +836,8 @@ static WERROR dnsserver_query_zone(struct dnsserver_state *dsstate,
                        r->ZoneInfoDotNet->dwForwarderTimeout = zoneinfo->dwForwarderTimeout;
                        r->ZoneInfoDotNet->fForwarderSlave = zoneinfo->fForwarderSlave;
                        r->ZoneInfoDotNet->aipLocalMasters = ip4_array_copy(mem_ctx, zoneinfo->aipLocalMasters);
-                       r->ZoneInfoDotNet->dwDpFlags = zoneinfo->dwDpFlags;
-                       r->ZoneInfoDotNet->pszDpFqdn = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
+                       r->ZoneInfoDotNet->dwDpFlags = z->partition->dwDpFlags;
+                       r->ZoneInfoDotNet->pszDpFqdn = talloc_strdup(mem_ctx, z->partition->pszDpFqdn);
                        r->ZoneInfoDotNet->pwszZoneDn = talloc_strdup(mem_ctx, zoneinfo->pwszZoneDn);
                        r->ZoneInfoDotNet->dwLastSuccessfulSoaCheck = zoneinfo->dwLastSuccessfulSoaCheck;
                        r->ZoneInfoDotNet->dwLastSuccessfulXfr = zoneinfo->dwLastSuccessfulXfr;
@@ -870,8 +871,8 @@ static WERROR dnsserver_query_zone(struct dnsserver_state *dsstate,
                        r->ZoneInfo->dwForwarderTimeout = zoneinfo->dwForwarderTimeout;
                        r->ZoneInfo->fForwarderSlave = zoneinfo->fForwarderSlave;
                        r->ZoneInfo->aipLocalMasters = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipLocalMasters);
-                       r->ZoneInfo->dwDpFlags = zoneinfo->dwDpFlags;
-                       r->ZoneInfo->pszDpFqdn = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
+                       r->ZoneInfo->dwDpFlags = z->partition->dwDpFlags;
+                       r->ZoneInfo->pszDpFqdn = talloc_strdup(mem_ctx, z->partition->pszDpFqdn);
                        r->ZoneInfo->pwszZoneDn = talloc_strdup(mem_ctx, zoneinfo->pwszZoneDn);
                        r->ZoneInfo->dwLastSuccessfulSoaCheck = zoneinfo->dwLastSuccessfulSoaCheck;
                        r->ZoneInfo->dwLastSuccessfulXfr = zoneinfo->dwLastSuccessfulXfr;
@@ -998,7 +999,7 @@ static WERROR dnsserver_query_zone(struct dnsserver_state *dsstate,
                answer_string = talloc_strdup(mem_ctx, zoneinfo->pszDataFile);
                is_string = 1;
        } else if (strcasecmp(operation, "ApplicationDirectoryPartition") == 0) {
-               answer_string = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
+               answer_string = talloc_strdup(mem_ctx, z->partition->pszDpFqdn);
                is_string = 1;
        } else if (strcasecmp(operation, "BreakOnNameUpdate") == 0) {
                answer_string = NULL;
@@ -1153,7 +1154,7 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate,
                                }
                                if (rin->Dword & DNS_ZONE_REQUEST_AUTO) {
                                        if (z->zoneinfo->fAutoCreated 
-                                               || z->zoneinfo->dwDpFlags & DNS_DP_AUTOCREATED) {
+                                               || z->partition->dwDpFlags & DNS_DP_AUTOCREATED) {
                                                found1 = true;
                                        }
                                }
@@ -1202,12 +1203,12 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate,
                                        }
                                }
                                if (rin->Dword & DNS_ZONE_REQUEST_DOMAIN_DP) {
-                                       if (!(z->zoneinfo->dwDpFlags & DNS_DP_DOMAIN_DEFAULT)) {
+                                       if (!(z->partition->dwDpFlags & DNS_DP_DOMAIN_DEFAULT)) {
                                                found3 = true;
                                        }
                                }
                                if (rin->Dword & DNS_ZONE_REQUEST_FOREST_DP) {
-                                       if (!(z->zoneinfo->dwDpFlags & DNS_DP_FOREST_DEFAULT)) {
+                                       if (!(z->partition->dwDpFlags & DNS_DP_FOREST_DEFAULT)) {
                                                found3 = true;
                                        }
                                }
@@ -1282,8 +1283,8 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate,
                                rout->ZoneList->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
                                rout->ZoneList->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
                                rout->ZoneList->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
-                               rout->ZoneList->ZoneArray[i]->dwDpFlags = zlist[i]->zoneinfo->dwDpFlags;
-                               rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, zlist[i]->zoneinfo->pszDpFqdn);
+                               rout->ZoneList->ZoneArray[i]->dwDpFlags = zlist[i]->partition->dwDpFlags;
+                               rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, zlist[i]->partition->pszDpFqdn);
                        }
                        rout->ZoneList->dwRpcStructureVersion = 1;
                        rout->ZoneList->dwZoneCount = zcount;
index ffa1757fddb09881f2a26838ed4c67dc03c2575a..a181e069b65df8ab663c7fd930dc0bf3e43326e0 100644 (file)
 #include "dnsserver.h"
 #include "lib/util/dlinklist.h"
 #include "librpc/gen_ndr/ndr_dnsp.h"
+#include "dsdb/samdb/samdb.h"
+
+/* There are only 2 fixed partitions for DNS */
+struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ctx,
+                                                       struct dnsserver_serverinfo *serverinfo,
+                                                       struct ldb_context *samdb)
+{
+       struct dnsserver_partition *partitions, *p;
+
+       partitions = NULL;
+
+       /* Domain partition */
+       p = talloc_zero(mem_ctx, struct dnsserver_partition);
+       if (p == NULL) {
+               goto failed;
+       }
+
+       p->partition_dn = ldb_dn_new(p, samdb, serverinfo->pszDomainDirectoryPartition);
+       if (p->partition_dn == NULL) {
+               goto failed;
+       }
+
+       p->pszDpFqdn = samdb_dn_to_dns_domain(p, p->partition_dn);
+       p->dwDpFlags = DNS_DP_AUTOCREATED | DNS_DP_DOMAIN_DEFAULT | DNS_DP_ENLISTED;
+       p->is_forest = false;
+
+       DLIST_ADD_END(partitions, p, NULL);
+
+       /* Forest Partition */
+       p = talloc_zero(mem_ctx, struct dnsserver_partition);
+       if (p == NULL) {
+               goto failed;
+       }
+
+       p->partition_dn = ldb_dn_new(p, samdb, serverinfo->pszForestDirectoryPartition);
+       if (p->partition_dn == NULL) {
+               goto failed;
+       }
+
+       p->pszDpFqdn = samdb_dn_to_dns_domain(p, p->partition_dn);
+       p->dwDpFlags = DNS_DP_AUTOCREATED | DNS_DP_FOREST_DEFAULT | DNS_DP_ENLISTED;
+       p->is_forest = true;
+
+       DLIST_ADD_END(partitions, p, NULL);
+
+       return partitions;
+
+failed:
+       return NULL;
+
+}
 
 struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
                                                struct ldb_context *samdb,
-                                               bool is_forest)
+                                               struct dnsserver_partition *p)
 {
        TALLOC_CTX *tmp_ctx;
-       const char *domain_prefix = "DC=DomainDnsZones";
-       const char *forest_prefix = "DC=ForestDnsZones";
-       const char *prefix;
        const char * const attrs[] = {"name", NULL};
-       struct ldb_dn *dn_base, *partition_dn, *dn;
+       struct ldb_dn *dn;
        struct ldb_result *res;
        struct dnsserver_zone *zones, *z;
        int i, ret;
@@ -43,28 +91,7 @@ struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       if (is_forest) {
-               dn_base = ldb_get_root_basedn(samdb);
-       } else {
-               dn_base = ldb_get_default_basedn(samdb);
-       }
-
-       partition_dn = ldb_dn_copy(tmp_ctx, dn_base);
-       if (partition_dn == NULL) {
-               goto failed;
-       }
-
-       if (is_forest) {
-               prefix = forest_prefix;
-       } else {
-               prefix = domain_prefix;
-       }
-
-       if (!ldb_dn_add_child_fmt(partition_dn, "%s", prefix)) {
-               goto failed;
-       }
-
-       dn = ldb_dn_copy(tmp_ctx, partition_dn);
+       dn = ldb_dn_copy(tmp_ctx, p->partition_dn);
        if (dn == NULL) {
                goto failed;
        }
@@ -73,7 +100,7 @@ struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
        }
 
        ret = ldb_search(samdb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
-                         attrs, "(&(objectClass=dnsZone)(!(name=RootDNSServers)))");
+                         attrs, "(objectClass=dnsZone)");
        if (ret != LDB_SUCCESS) {
                DEBUG(0, ("dnsserver: Failed to find DNS Zones in %s\n",
                        ldb_dn_get_linearized(dn)));
@@ -82,18 +109,25 @@ struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
 
        zones = NULL;
        for(i=0; i<res->count; i++) {
+               char *name;
                z = talloc_zero(mem_ctx, struct dnsserver_zone);
                if (z == NULL) {
                        goto failed;
                }
 
-               z->name = talloc_strdup(z,
+               z->partition = p;
+               name = talloc_strdup(z,
                                ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL));
-               DEBUG(2, ("dnsserver: Found DNS zone %s\n", z->name));
+               if (strcmp(name, "RootDNSServers") == 0) {
+                       talloc_free(name);
+                       z->name = talloc_strdup(z, ".");
+               } else {
+                       z->name = name;
+               }
                z->zone_dn = talloc_steal(z, res->msgs[i]->dn);
-               z->partition_dn = talloc_steal(z, partition_dn);
 
                DLIST_ADD_END(zones, z, NULL);
+               DEBUG(2, ("dnsserver: Found DNS zone %s\n", z->name));
        }
 
        return zones;
index 818dc60b626e23772e46794e5d2a659b40c413a4..938f2f4b01371a42abec91d71eae63c2786c9490 100644 (file)
@@ -126,8 +126,6 @@ struct dnsserver_zoneinfo {
 
        struct IP4_ARRAY * aipLocalMasters;
 
-       uint32_t        dwDpFlags;
-       char *          pszDpFqdn;
        char *          pwszZoneDn;
 
        uint32_t        dwLastSuccessfulSoaCheck;
@@ -142,10 +140,20 @@ struct dnsserver_zoneinfo {
 };
 
 
+struct dnsserver_partition {
+       struct dnsserver_partition *prev, *next;
+       struct ldb_dn *partition_dn;
+       const char *pszDpFqdn;
+       uint32_t dwDpFlags;
+       bool is_forest;
+       int zones_count;
+};
+
+
 struct dnsserver_zone {
        struct dnsserver_zone *prev, *next;
+       struct dnsserver_partition *partition;
        const char *name;
-       struct ldb_dn *partition_dn;
        struct ldb_dn *zone_dn;
        struct dnsserver_zoneinfo *zoneinfo;
 };
@@ -192,8 +200,9 @@ struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
                                        struct loadparm_context *lp_ctx,
                                        struct ldb_context *samdb);
 struct dnsserver_zoneinfo *dnsserver_init_zoneinfo(struct dnsserver_zone *zone,
-                                       struct dnsserver_serverinfo *serverinfo,
-                                       bool is_forest);
+                                       struct dnsserver_serverinfo *serverinfo);
+struct dnsserver_partition *dnsserver_find_partition(struct dnsserver_partition *partitions,
+                                       const char *dp_fqdn);
 struct dnsserver_zone *dnsserver_find_zone(struct dnsserver_zone *zones,
                                        const char *zone_name);
 struct ldb_dn *dnsserver_name_to_dn(TALLOC_CTX *mem_ctx, struct dnsserver_zone *z,
@@ -203,9 +212,12 @@ uint32_t dnsserver_zone_to_request_filter(const char *zone);
 
 /* Database functions from dnsdb.c */
 
+struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ctx,
+                                       struct dnsserver_serverinfo *serverinfo,
+                                       struct ldb_context *samdb);
 struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx,
                                        struct ldb_context *samdb,
-                                       bool is_forest);
+                                       struct dnsserver_partition *p);
 WERROR dnsserver_db_add_empty_node(TALLOC_CTX *mem_ctx,
                                        struct ldb_context *samdb,
                                        struct dnsserver_zone *z,
index 3ae47a8c5fb125a3458e1465150ee6015d659e2f..5390384e57e4e912cecdf32557529d0eff60d34d 100644 (file)
@@ -154,11 +154,9 @@ struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
 
 
 struct dnsserver_zoneinfo *dnsserver_init_zoneinfo(struct dnsserver_zone *zone,
-                                               struct dnsserver_serverinfo *serverinfo,
-                                               bool is_forest)
+                                               struct dnsserver_serverinfo *serverinfo)
 {
        struct dnsserver_zoneinfo *zoneinfo;
-       uint32_t dp_flags;
        uint32_t fReverse;
        const char *revzone = "in-addr.arpa";
        int len1, len2;
@@ -168,13 +166,6 @@ struct dnsserver_zoneinfo *dnsserver_init_zoneinfo(struct dnsserver_zone *zone,
                return NULL;
        }
 
-       dp_flags = DNS_DP_AUTOCREATED | DNS_DP_ENLISTED;
-       if (is_forest) {
-               dp_flags |= DNS_DP_FOREST_DEFAULT;
-       } else {
-               dp_flags |= DNS_DP_DOMAIN_DEFAULT;
-       }
-
        /* If the zone name ends with in-addr.arpa, it's reverse zone */
        fReverse = 0;
        len1 = strlen(zone->name);
@@ -184,32 +175,42 @@ struct dnsserver_zoneinfo *dnsserver_init_zoneinfo(struct dnsserver_zone *zone,
        }
 
        zoneinfo->Version = 0x32;
-       zoneinfo->Flags = DNS_RPC_ZONE_DSINTEGRATED | DNS_RPC_ZONE_UPDATE_SECURE;
-       zoneinfo->dwZoneType = DNS_ZONE_TYPE_PRIMARY;
+       zoneinfo->Flags = DNS_RPC_ZONE_DSINTEGRATED;
+
+       if (strcmp(zone->name, ".") == 0) {
+               zoneinfo->dwZoneType = DNS_ZONE_TYPE_CACHE;
+               zoneinfo->fAllowUpdate = DNS_ZONE_UPDATE_OFF;
+               zoneinfo->fSecureSecondaries = DNS_ZONE_SECSECURE_NO_SECURITY;
+               zoneinfo->fNotifyLevel = DNS_ZONE_NOTIFY_OFF;
+               zoneinfo->dwNoRefreshInterval = 0;
+               zoneinfo->dwRefreshInterval = 0;
+       } else {
+               zoneinfo->Flags |= DNS_RPC_ZONE_UPDATE_SECURE;
+               zoneinfo->dwZoneType = DNS_ZONE_TYPE_PRIMARY;
+               zoneinfo->fAllowUpdate = DNS_ZONE_UPDATE_SECURE;
+               zoneinfo->fSecureSecondaries = DNS_ZONE_SECSECURE_NO_XFER;
+               zoneinfo->fNotifyLevel = DNS_ZONE_NOTIFY_LIST_ONLY;
+               zoneinfo->dwNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
+               zoneinfo->dwRefreshInterval = serverinfo->dwDefaultRefreshInterval;
+       }
+
        zoneinfo->fReverse = fReverse;
-       zoneinfo->fAllowUpdate = DNS_ZONE_UPDATE_SECURE;
        zoneinfo->fPaused = 0;
        zoneinfo->fShutdown = 0;
        zoneinfo->fAutoCreated = 0;
        zoneinfo->fUseDatabase = 1;
        zoneinfo->pszDataFile = NULL;
        zoneinfo->aipMasters = NULL;
-       zoneinfo->fSecureSecondaries = DNS_ZONE_SECSECURE_NO_XFER;
-       zoneinfo->fNotifyLevel = DNS_ZONE_NOTIFY_LIST_ONLY;
        zoneinfo->aipSecondaries = NULL;
        zoneinfo->aipNotify = NULL;
        zoneinfo->fUseWins = 0;
        zoneinfo->fUseNbstat = 0;
        zoneinfo->fAging = 0;
-       zoneinfo->dwNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
-       zoneinfo->dwRefreshInterval = serverinfo->dwDefaultRefreshInterval;
        zoneinfo->dwAvailForScavengeTime = 0;
        zoneinfo->aipScavengeServers = NULL;
        zoneinfo->dwForwarderTimeout = 0;
        zoneinfo->fForwarderSlave = 0;
        zoneinfo->aipLocalMasters = NULL;
-       zoneinfo->dwDpFlags = dp_flags;
-       zoneinfo->pszDpFqdn = samdb_dn_to_dns_domain(zone, zone->partition_dn);
        zoneinfo->pwszZoneDn = discard_const_p(char, ldb_dn_get_linearized(zone->zone_dn));
        zoneinfo->dwLastSuccessfulSoaCheck = 0;
        zoneinfo->dwLastSuccessfulXfr = 0;
@@ -222,6 +223,20 @@ struct dnsserver_zoneinfo *dnsserver_init_zoneinfo(struct dnsserver_zone *zone,
        return zoneinfo;
 }
 
+struct dnsserver_partition *dnsserver_find_partition(struct dnsserver_partition *partitions,
+                                                    const char *dp_fqdn)
+{
+       struct dnsserver_partition *p = NULL;
+
+       for (p = partitions; p; p = p->next) {
+               if (strcmp(dp_fqdn, p->pszDpFqdn) == 0) {
+                       break;
+               }
+       }
+
+       return p;
+}
+
 struct dnsserver_zone *dnsserver_find_zone(struct dnsserver_zone *zones, const char *zone_name)
 {
        struct dnsserver_zone *z = NULL;