s4:rpc-dnsserver: Implement DirectoryPartitionInfo RPC operation
authorAmitay Isaacs <amitay@gmail.com>
Fri, 16 Dec 2011 01:11:42 +0000 (12:11 +1100)
committerAmitay Isaacs <amitay@gmail.com>
Fri, 23 Dec 2011 05:18:24 +0000 (16:18 +1100)
source4/rpc_server/dnsserver/dcerpc_dnsserver.c
source4/rpc_server/dnsserver/dnsdb.c
source4/rpc_server/dnsserver/dnsserver.h

index 345cfb814e859c54774e6f9baf9b61ffb404df0e..8aaa36b6f0a34c828843bf906496c53f499cab57 100644 (file)
@@ -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) {
index 707f7b842cd33a0e9bf79de9eddbf59c93d0b553..e7bd28d38278c47f87f7fbe2497ec914f4940f63 100644 (file)
@@ -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; i<el->num_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)
index 938f2f4b01371a42abec91d71eae63c2786c9490..63224c55c14a10d4e23b9f2158a043498d5ce674 100644 (file)
@@ -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,