From 5673e2cec946502da84956f866658718e7632a3e Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Thu, 15 Dec 2011 17:44:32 +1100 Subject: s4:rpc-dnsserver: Cache DNS partition information This information will be used for the RPC calls for partition information. --- source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 67 ++++++++--------- source4/rpc_server/dnsserver/dnsdb.c | 96 +++++++++++++++++-------- source4/rpc_server/dnsserver/dnsserver.h | 24 +++++-- source4/rpc_server/dnsserver/dnsutils.c | 53 +++++++++----- 4 files changed, 151 insertions(+), 89 deletions(-) diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index 98e935ca99..715b8a6c37 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -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; diff --git a/source4/rpc_server/dnsserver/dnsdb.c b/source4/rpc_server/dnsserver/dnsdb.c index ffa1757fdd..a181e069b6 100644 --- a/source4/rpc_server/dnsserver/dnsdb.c +++ b/source4/rpc_server/dnsserver/dnsdb.c @@ -23,17 +23,65 @@ #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; icount; 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; diff --git a/source4/rpc_server/dnsserver/dnsserver.h b/source4/rpc_server/dnsserver/dnsserver.h index 818dc60b62..938f2f4b01 100644 --- a/source4/rpc_server/dnsserver/dnsserver.h +++ b/source4/rpc_server/dnsserver/dnsserver.h @@ -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, diff --git a/source4/rpc_server/dnsserver/dnsutils.c b/source4/rpc_server/dnsserver/dnsutils.c index 3ae47a8c5f..5390384e57 100644 --- a/source4/rpc_server/dnsserver/dnsutils.c +++ b/source4/rpc_server/dnsserver/dnsutils.c @@ -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; -- cgit