From 6356f4c25524e81cad3301a5cdf907272612948f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 Sep 2011 16:45:17 +1000 Subject: s4-kcc: if we are a GC, auto-add partial replicas when we are a global catalog server, the KCC needs to add partial replicas for all domain partitions that we don't have copies of --- source4/dsdb/kcc/kcc_periodic.c | 150 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/kcc/kcc_periodic.c b/source4/dsdb/kcc/kcc_periodic.c index 2654f9f2d9..d9a716f61f 100644 --- a/source4/dsdb/kcc/kcc_periodic.c +++ b/source4/dsdb/kcc/kcc_periodic.c @@ -35,6 +35,7 @@ #include "librpc/gen_ndr/ndr_drsblobs.h" #include "librpc/gen_ndr/ndr_irpc_c.h" #include "param/param.h" +#include "dsdb/common/util.h" /* * see if two repsFromToBlob blobs are for the same source DSA @@ -309,6 +310,145 @@ NTSTATUS kccsrv_add_repsFrom(struct kccsrv_service *s, TALLOC_CTX *mem_ctx, } + +/* + form a unique list of DNs from a search result and a given set of attributes + */ +static int kccsrv_dn_list(struct ldb_context *ldb, struct ldb_result *res, + TALLOC_CTX *mem_ctx, + const char **attrs, + struct ldb_dn ***dn_list, int *dn_count) +{ + int i; + struct ldb_dn **nc_list = NULL; + int nc_count = 0; + + nc_list = talloc_array(mem_ctx, struct ldb_dn *, 0); + if (nc_list == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* gather up a list of all NCs in this forest */ + for (i=0; icount; i++) { + struct ldb_message *msg = res->msgs[i]; + int j; + for (j=0; attrs[j]; j++) { + struct ldb_message_element *el; + int k; + + el = ldb_msg_find_element(msg, attrs[j]); + if (el == NULL) continue; + for (k=0; knum_values; k++) { + struct ldb_dn *dn; + dn = ldb_dn_from_ldb_val(nc_list, ldb, &el->values[k]); + if (dn != NULL) { + int l; + for (l=0; lsamdb, res, tmp_ctx, attrs1, &nc_list, &nc_count); + if (ret != LDB_SUCCESS) { + DEBUG(1,("Failed to get NC list for GC update - %s\n", ldb_errstring(s->samdb))); + talloc_free(tmp_ctx); + return ret; + } + + /* get a list of what NCs we are already replicating */ + ret = dsdb_search_dn(s->samdb, tmp_ctx, &res2, samdb_ntds_settings_dn(s->samdb), attrs2, 0); + if (ret != LDB_SUCCESS) { + DEBUG(1,("Failed to get our NC list attributes for GC update - %s\n", ldb_errstring(s->samdb))); + talloc_free(tmp_ctx); + return ret; + } + + ret = kccsrv_dn_list(s->samdb, res2, tmp_ctx, attrs2, &our_nc_list, &our_nc_count); + if (ret != LDB_SUCCESS) { + DEBUG(1,("Failed to get our NC list for GC update - %s\n", ldb_errstring(s->samdb))); + talloc_free(tmp_ctx); + return ret; + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + talloc_free(tmp_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + msg->dn = res2->msgs[0]->dn; + + /* see if we are missing any */ + for (i=0; inum_elements == 0) { + /* none to add */ + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } + msg->elements[0].flags = LDB_FLAG_MOD_ADD; + + ret = dsdb_modify(s->samdb, msg, 0); + if (ret != LDB_SUCCESS) { + DEBUG(0,("Failed to add hasPartialReplicaNCs - %s\n", + ldb_errstring(s->samdb))); + } + + talloc_free(tmp_ctx); + return ret; +} + + /* this is the core of our initial simple KCC We just add a repsFrom entry for all DCs we find that have nTDSDSA @@ -319,18 +459,22 @@ NTSTATUS kccsrv_simple_update(struct kccsrv_service *s, TALLOC_CTX *mem_ctx) struct ldb_result *res; unsigned int i; int ret; - const char *attrs[] = { "objectGUID", "invocationID", "msDS-hasMasterNCs", "hasMasterNCs", NULL }; + const char *attrs[] = { "objectGUID", "invocationID", "msDS-hasMasterNCs", "hasMasterNCs", "msDS-HasDomainNCs", NULL }; struct repsFromToBlob *reps = NULL; uint32_t count = 0; struct kcc_connection_list *ntds_conn, *dsa_conn; - ret = ldb_search(s->samdb, mem_ctx, &res, s->config_dn, LDB_SCOPE_SUBTREE, - attrs, "objectClass=nTDSDSA"); + ret = dsdb_search(s->samdb, mem_ctx, &res, s->config_dn, LDB_SCOPE_SUBTREE, + attrs, DSDB_SEARCH_SHOW_EXTENDED_DN, "objectClass=nTDSDSA"); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed nTDSDSA search - %s\n", ldb_errstring(s->samdb))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + if (samdb_is_gc(s->samdb)) { + kccsrv_gc_update(s, res); + } + /* get the current list of connections */ ntds_conn = kccsrv_find_connections(s, mem_ctx); -- cgit