From 3d139b49cbf2d036bc59bf34f657643c1069ebc0 Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Fri, 16 Dec 2011 12:11:42 +1100 Subject: s4:rpc-dnsserver: Implement DirectoryPartitionInfo RPC operation --- source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 42 ++++++++++- source4/rpc_server/dnsserver/dnsdb.c | 99 +++++++++++++++++++++++++ source4/rpc_server/dnsserver/dnsserver.h | 11 +++ 3 files changed, 151 insertions(+), 1 deletion(-) (limited to 'source4/rpc_server/dnsserver') diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index 345cfb814e..8aaa36b6f0 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1329,7 +1329,47 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate, } return WERR_OK; } else if (strcasecmp(operation, "DirectoryPartitionInfo") == 0) { - valid_operation = true; + struct dnsserver_partition *p; + struct dnsserver_partition_info *partinfo; + struct DNS_RPC_DP_INFO *dpinfo = NULL; + + if (typeid_in != DNSSRV_TYPEID_LPSTR) { + return WERR_DNS_ERROR_INVALID_PROPERTY; + } + + *typeid_out = DNSSRV_TYPEID_DP_INFO; + + for (p = dsstate->partitions; p; p = p->next) { + if (strcmp(p->pszDpFqdn, rin->String) == 0) { + dpinfo = talloc_zero(mem_ctx, struct DNS_RPC_DP_INFO); + W_ERROR_HAVE_NO_MEMORY(dpinfo); + + partinfo = dnsserver_db_partition_info(mem_ctx, dsstate->samdb, p); + W_ERROR_HAVE_NO_MEMORY(partinfo); + + dpinfo->pszDpFqdn = talloc_strdup(dpinfo, p->pszDpFqdn); + dpinfo->pszDpDn = talloc_strdup(dpinfo, ldb_dn_get_linearized(p->partition_dn)); + dpinfo->pszCrDn = talloc_steal(dpinfo, partinfo->pszCrDn); + dpinfo->dwFlags = p->dwDpFlags; + dpinfo->dwZoneCount = p->zones_count; + dpinfo->dwState = partinfo->dwState; + dpinfo->dwReplicaCount = partinfo->dwReplicaCount; + if (partinfo->dwReplicaCount > 0) { + dpinfo->ReplicaArray = talloc_steal(dpinfo, + partinfo->ReplicaArray); + } else { + dpinfo->ReplicaArray = NULL; + } + break; + } + } + + if (dpinfo == NULL) { + return WERR_DNS_ERROR_DP_DOES_NOT_EXIST; + } + + rout->DirectoryPartition = dpinfo; + return WERR_OK; } else if (strcasecmp(operation, "Statistics") == 0) { valid_operation = true; } else if (strcasecmp(operation, "IpValidate") == 0) { diff --git a/source4/rpc_server/dnsserver/dnsdb.c b/source4/rpc_server/dnsserver/dnsdb.c index 707f7b842c..e7bd28d382 100644 --- a/source4/rpc_server/dnsserver/dnsdb.c +++ b/source4/rpc_server/dnsserver/dnsdb.c @@ -140,6 +140,105 @@ failed: } +/* Find DNS partition information */ +struct dnsserver_partition_info *dnsserver_db_partition_info(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, + struct dnsserver_partition *p) +{ + const char * const attrs[] = { "instanceType", "msDs-masteredBy", NULL }; + const char * const attrs_none[] = { NULL }; + struct ldb_result *res; + struct ldb_message_element *el; + struct ldb_dn *dn; + struct dnsserver_partition_info *partinfo; + int i, ret, instance_type; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return NULL; + } + + partinfo = talloc_zero(mem_ctx, struct dnsserver_partition_info); + if (partinfo == NULL) { + talloc_free(tmp_ctx); + return NULL; + } + + /* Search for the active replica and state */ + ret = ldb_search(samdb, tmp_ctx, &res, p->partition_dn, LDB_SCOPE_BASE, + attrs, NULL); + if (ret != LDB_SUCCESS || res->count != 1) { + goto failed; + } + + /* Set the state of the partition */ + instance_type = ldb_msg_find_attr_as_int(res->msgs[0], "instanceType", -1); + if (instance_type == -1) { + partinfo->dwState = DNS_DP_STATE_UNKNOWN; + } else if (instance_type & INSTANCE_TYPE_NC_COMING) { + partinfo->dwState = DNS_DP_STATE_REPL_INCOMING; + } else if (instance_type & INSTANCE_TYPE_NC_GOING) { + partinfo->dwState = DNS_DP_STATE_REPL_OUTGOING; + } else { + partinfo->dwState = DNS_DP_OKAY; + } + + el = ldb_msg_find_element(res->msgs[0], "msDs-masteredBy"); + if (el == NULL) { + partinfo->dwReplicaCount = 0; + partinfo->ReplicaArray = NULL; + } else { + partinfo->dwReplicaCount = el->num_values; + partinfo->ReplicaArray = talloc_zero_array(partinfo, + struct DNS_RPC_DP_REPLICA *, + el->num_values); + if (partinfo->ReplicaArray == NULL) { + goto failed; + } + for (i=0; inum_values; i++) { + partinfo->ReplicaArray[i] = talloc_zero(partinfo, + struct DNS_RPC_DP_REPLICA); + if (partinfo->ReplicaArray[i] == NULL) { + goto failed; + } + partinfo->ReplicaArray[i]->pszReplicaDn = talloc_strdup( + partinfo, + (const char *)el->values[i].data); + if (partinfo->ReplicaArray[i]->pszReplicaDn == NULL) { + goto failed; + } + } + } + talloc_free(res); + + /* Search for cross-reference object */ + dn = ldb_dn_copy(tmp_ctx, ldb_get_config_basedn(samdb)); + if (dn == NULL) { + goto failed; + } + + ret = ldb_search(samdb, tmp_ctx, &res, dn, LDB_SCOPE_DEFAULT, attrs_none, + "(nCName=%s)", ldb_dn_get_linearized(p->partition_dn)); + if (ret != LDB_SUCCESS || res->count != 1) { + goto failed; + } + partinfo->pszCrDn = talloc_strdup(partinfo, ldb_dn_get_linearized(res->msgs[0]->dn)); + if (partinfo->pszCrDn == NULL) { + goto failed; + } + talloc_free(res); + + talloc_free(tmp_ctx); + return partinfo; + +failed: + talloc_free(tmp_ctx); + talloc_free(partinfo); + return NULL; +} + + static unsigned int dnsserver_update_soa(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct dnsserver_zone *z) diff --git a/source4/rpc_server/dnsserver/dnsserver.h b/source4/rpc_server/dnsserver/dnsserver.h index 938f2f4b01..63224c55c1 100644 --- a/source4/rpc_server/dnsserver/dnsserver.h +++ b/source4/rpc_server/dnsserver/dnsserver.h @@ -150,6 +150,14 @@ struct dnsserver_partition { }; +struct dnsserver_partition_info { + const char *pszCrDn; + uint32_t dwState; + uint32_t dwReplicaCount; + struct DNS_RPC_DP_REPLICA **ReplicaArray; +}; + + struct dnsserver_zone { struct dnsserver_zone *prev, *next; struct dnsserver_partition *partition; @@ -218,6 +226,9 @@ struct dnsserver_partition *dnsserver_db_enumerate_partitions(TALLOC_CTX *mem_ct struct dnsserver_zone *dnsserver_db_enumerate_zones(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct dnsserver_partition *p); +struct dnsserver_partition_info *dnsserver_db_partition_info(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, + struct dnsserver_partition *p); WERROR dnsserver_db_add_empty_node(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct dnsserver_zone *z, -- cgit