summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/kcc/kcc_topology.c789
1 files changed, 576 insertions, 213 deletions
diff --git a/source4/dsdb/kcc/kcc_topology.c b/source4/dsdb/kcc/kcc_topology.c
index 571bd8482e..50a1fee49b 100644
--- a/source4/dsdb/kcc/kcc_topology.c
+++ b/source4/dsdb/kcc/kcc_topology.c
@@ -25,14 +25,17 @@
#include "lib/messaging/irpc.h"
#include "librpc/gen_ndr/ndr_misc.h"
-#define NTDSTRANSPORT_OPT_IGNORE_SCHEDULES 0x00000001
+#define FLAG_CR_NTDS_DOMAIN 0x00000002
+
+#define NTDSSETTINGS_OPT_W2K3_BRIDGES_REQUIRED 0x00001000
+
#define NTDSTRANSPORT_OPT_BRIDGES_REQUIRED 0x00000002
/** replication parameters of a graph edge */
struct kcctpl_repl_info {
- int cost;
- int interval;
- int options;
+ uint32_t cost;
+ uint32_t interval;
+ uint32_t options;
uint8_t schedule[84];
};
@@ -42,7 +45,7 @@ enum kcctpl_color { RED, BLACK, WHITE };
/** a GUID array list */
struct GUID_list {
struct GUID *data;
- unsigned int count;
+ uint32_t count;
};
/** a vertex in the site graph */
@@ -53,7 +56,7 @@ struct kcctpl_vertex {
struct GUID_list accept_red_red;
struct GUID_list accept_black;
struct kcctpl_repl_info repl_info;
- int dist_to_red;
+ uint32_t dist_to_red;
/* Dijkstra data */
struct GUID root_id;
@@ -61,7 +64,7 @@ struct kcctpl_vertex {
/* Kruskal data */
struct GUID component_id;
- int component_index;
+ uint32_t component_index;
};
/** fully connected subgraph of vertices */
@@ -83,19 +86,19 @@ struct kcctpl_multi_edge_set {
/** a vertices array list */
struct kcctpl_vertex_list {
struct kcctpl_vertex *data;
- unsigned int count;
+ uint32_t count;
};
-/** an edges linked list */
+/** an edges array list */
struct kcctpl_multi_edge_list {
struct kcctpl_multi_edge *data;
- unsigned int count;
+ uint32_t count;
};
-/** an edge sets linked list */
+/** an edge sets array list */
struct kcctpl_multi_edge_set_list {
struct kcctpl_multi_edge_set *data;
- unsigned int count;
+ uint32_t count;
};
/** a site graph */
@@ -107,49 +110,166 @@ struct kcctpl_graph {
/** path found in the graph between two non-white vertices */
struct kcctpl_internal_edge {
- struct GUID v1id, v2id;
+ struct GUID v1id;
+ struct GUID v2id;
bool red_red;
struct kcctpl_repl_info repl_info;
struct GUID type;
};
+/** an internal edges array list */
+struct kcctpl_internal_edge_list {
+ struct kcctpl_internal_edge *data;
+ uint32_t count;
+};
+
+/** an LDB messages array list */
+struct message_list {
+ struct ldb_message *data;
+ uint32_t count;
+};
+
+/**
+ * find a graph vertex based on its GUID.
+ */
+static struct kcctpl_vertex *kcctpl_find_vertex_by_guid(struct kcctpl_graph *graph,
+ struct GUID guid)
+{
+ uint32_t i;
+
+ for (i = 0; i < graph->vertices.count; i++) {
+ if (GUID_equal(&graph->vertices.data[i].id, &guid)) {
+ return &graph->vertices.data[i];
+ }
+ }
+
+ return NULL;
+}
+
/**
* find a graph edge based on its GUID.
*/
static struct kcctpl_multi_edge *kcctpl_find_edge_by_guid(struct kcctpl_graph *graph,
struct GUID guid)
{
- unsigned int i;
+ uint32_t i;
for (i = 0; i < graph->edges.count; i++) {
- if (GUID_compare(&graph->edges.data[i].id, &guid) == 0) {
+ if (GUID_equal(&graph->edges.data[i].id, &guid)) {
return &graph->edges.data[i];
}
}
+
+ return NULL;
+}
+
+/**
+ * find a graph edge that contains a vertex with the specified GUID. the first
+ * occurrence will be returned.
+ */
+static struct kcctpl_multi_edge *kcctpl_find_edge_by_vertex_guid(struct kcctpl_graph *graph,
+ struct GUID guid)
+{
+ uint32_t i;
+
+ for (i = 0; i < graph->edges.count; i++) {
+ struct kcctpl_multi_edge *edge;
+ uint32_t j;
+
+ edge = &graph->edges.data[i];
+
+ for (j = 0; j < edge->vertex_ids.count; j++) {
+ struct GUID vertex_guid = edge->vertex_ids.data[j];
+
+ struct GUID *p = &guid;
+
+ if (GUID_equal(&vertex_guid, p)) {
+ return edge;
+ }
+ }
+ }
+
return NULL;
}
+
+/**
+ * get the Transports DN
+ * (CN=Inter-Site Transports,CN=Sites,CN=Configuration,DC=<domain>).
+ */
+static struct ldb_dn *kcctpl_transports_dn(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx)
+{
+ struct ldb_dn *sites_dn;
+ bool ok;
+
+ sites_dn = samdb_sites_dn(ldb, mem_ctx);
+ if (!sites_dn) {
+ return NULL;
+ }
+
+ ok = ldb_dn_add_child_fmt(sites_dn, "CN=Inter-Site Transports");
+ if (!ok) {
+ talloc_free(sites_dn);
+ return NULL;
+ }
+
+ return sites_dn;
+}
+/**
+ * get the domain local site object.
+ */
+static struct ldb_message *kcctpl_local_site(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx)
+{
+ int ret;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_dn *sites_dn;
+ struct ldb_result *res;
+ const char * const attrs[] = { "objectGUID", "options", NULL };
+
+ tmp_ctx = talloc_new(ldb);
+
+ sites_dn = samdb_sites_dn(ldb, tmp_ctx);
+ if (!sites_dn) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
+ "objectClass=site");
+
+ if (ret != LDB_SUCCESS || res->count == 0) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ talloc_steal(mem_ctx, res);
+ talloc_free(tmp_ctx);
+ return res->msgs[0];
+}
+
/**
* create a kcctpl_graph instance.
*/
static NTSTATUS kcctpl_create_graph(TALLOC_CTX *mem_ctx,
- struct GUID_list *guids,
+ struct GUID_list guids,
struct kcctpl_graph **_graph)
{
struct kcctpl_graph *graph;
- unsigned int i;
+ uint32_t i;
graph = talloc_zero(mem_ctx, struct kcctpl_graph);
NT_STATUS_HAVE_NO_MEMORY(graph);
- graph->vertices.count = guids->count;
+ graph->vertices.count = guids.count;
graph->vertices.data = talloc_zero_array(graph, struct kcctpl_vertex,
- guids->count);
+ guids.count);
NT_STATUS_HAVE_NO_MEMORY_AND_FREE(graph->vertices.data, graph);
- TYPESAFE_QSORT(guids->data, guids->count, GUID_compare);
+ TYPESAFE_QSORT(guids.data, guids.count, GUID_compare);
- for (i = 0; i < guids->count; i++) {
- graph->vertices.data[i].id = guids->data[i];
+ for (i = 0; i < guids.count; i++) {
+ graph->vertices.data[i].id = guids.data[i];
}
*_graph = graph;
@@ -166,84 +286,99 @@ static NTSTATUS kcctpl_create_edge(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
{
struct kcctpl_multi_edge *edge;
TALLOC_CTX *tmp_ctx;
+ struct ldb_dn *sites_dn;
struct ldb_result *res;
const char * const attrs[] = { "siteList", NULL };
int ret;
struct ldb_message_element *el;
- unsigned int i;
+ uint32_t i;
struct ldb_val val;
- edge = talloc(mem_ctx, struct kcctpl_multi_edge);
- NT_STATUS_HAVE_NO_MEMORY(edge);
+ tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ edge = talloc_zero(tmp_ctx, struct kcctpl_multi_edge);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(edge, tmp_ctx);
edge->id = samdb_result_guid(site_link, "objectGUID");
- tmp_ctx = talloc_new(mem_ctx);
- ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_BASE, attrs,
+ sites_dn = samdb_sites_dn(ldb, tmp_ctx);
+ if (!sites_dn) {
+ DEBUG(1, (__location__ ": failed to find our own Sites DN\n"));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
"objectGUID=%s", GUID_string(tmp_ctx, &edge->id));
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find siteLink object %s: %s\n",
- GUID_string(tmp_ctx, &edge->id), ldb_strerror(ret)));
- talloc_free(edge);
+ DEBUG(1, (__location__ ": failed to find siteLink object %s: "
+ "%s\n", GUID_string(tmp_ctx, &edge->id),
+ ldb_strerror(ret)));
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
if (res->count == 0) {
- DEBUG(0, ("failed to find siteLink object %s\n",
+ DEBUG(1, (__location__ ": failed to find siteLink object %s\n",
GUID_string(tmp_ctx, &edge->id)));
- talloc_free(edge);
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
el = ldb_msg_find_element(res->msgs[0], "siteList");
- edge->vertex_ids.count = el->num_values;
- edge->vertex_ids.data = talloc_array(edge, struct GUID, el->num_values);
- if (!edge->vertex_ids.data) {
- talloc_free(edge);
+ if (!el) {
+ DEBUG(1, (__location__ ": failed to find siteList attribute of "
+ "object %s\n",
+ ldb_dn_get_linearized(res->msgs[0]->dn)));
+
talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+ edge->vertex_ids.data = talloc_array(edge, struct GUID, el->num_values);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(edge->vertex_ids.data, tmp_ctx);
+ edge->vertex_ids.count = el->num_values;
+
for (i = 0; i < el->num_values; i++) {
struct ldb_dn *dn;
struct GUID guid;
val = el->values[i];
dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &val);
+ if (!dn) {
+ DEBUG(1, (__location__ ": failed to read a DN from "
+ "siteList attribute of %s\n",
+ ldb_dn_get_linearized(res->msgs[0]->dn)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
ret = dsdb_find_guid_by_dn(ldb, dn, &guid);
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find objectGUID for object %s: "
- "%s\n", ldb_dn_get_linearized(dn),
+ DEBUG(1, (__location__ ": failed to find objectGUID "
+ "for object %s: %s\n",
+ ldb_dn_get_linearized(dn),
ldb_strerror(ret)));
- talloc_free(edge);
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- edge->vertex_ids.data = talloc_realloc(edge,
- edge->vertex_ids.data,
- struct GUID,
- edge->vertex_ids.count + 1);
- if (!edge->vertex_ids.data) {
- talloc_free(edge);
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- edge->vertex_ids.data[edge->vertex_ids.count] = guid;
- edge->vertex_ids.count++;
+ edge->vertex_ids.data[i] = guid;
}
edge->repl_info.cost = samdb_result_int64(site_link, "cost", 0);
edge->repl_info.options = samdb_result_int64(site_link, "options", 0);
- edge->repl_info.interval = samdb_result_int64(site_link, "replInterval",
- 0);
- /* val = ldb_msg_find_ldb_val(site_link, "schedule");
- edge->repl_info.schedule = val->data; */
+ edge->repl_info.interval = samdb_result_int64(site_link,
+ "replInterval", 0);
+ /* TODO: edge->repl_info.schedule = site_link!schedule */
edge->type = type;
edge->directed = false;
- *_edge = edge;
+ *_edge = talloc_steal(mem_ctx, edge);
talloc_free(tmp_ctx);
return NT_STATUS_OK;
}
@@ -258,10 +393,14 @@ static NTSTATUS kcctpl_create_auto_edge_set(struct kcctpl_graph *graph,
struct kcctpl_multi_edge_set **_set)
{
struct kcctpl_multi_edge_set *set;
- unsigned int i;
+ TALLOC_CTX *tmp_ctx;
+ uint32_t i;
- set = talloc_zero(graph, struct kcctpl_multi_edge_set);
- NT_STATUS_HAVE_NO_MEMORY(set);
+ tmp_ctx = talloc_new(graph);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ set = talloc_zero(tmp_ctx, struct kcctpl_multi_edge_set);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(set, tmp_ctx);
for (i = 0; i < res_site_link->count; i++) {
struct GUID site_link_guid;
@@ -271,26 +410,28 @@ static NTSTATUS kcctpl_create_auto_edge_set(struct kcctpl_graph *graph,
"objectGUID");
edge = kcctpl_find_edge_by_guid(graph, site_link_guid);
if (!edge) {
- TALLOC_CTX *tmp_ctx = talloc_new(graph);
- DEBUG(0, ("failed to find a graph edge with ID=%s\n",
+ DEBUG(1, (__location__ ": failed to find a graph edge "
+ "with ID=%s\n",
GUID_string(tmp_ctx, &site_link_guid)));
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- if (GUID_compare(&edge->type, &type) == 0) {
- set->edge_ids.data = talloc_realloc(set,
- set->edge_ids.data,
- struct GUID,
- set->edge_ids.count + 1);
- NT_STATUS_HAVE_NO_MEMORY_AND_FREE(set->edge_ids.data,
- set);
- set->edge_ids.data[set->edge_ids.count] = site_link_guid;
+ if (GUID_equal(&edge->type, &type)) {
+ struct GUID *new_data;
+
+ new_data = talloc_realloc(set, set->edge_ids.data,
+ struct GUID,
+ set->edge_ids.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[set->edge_ids.count] = site_link_guid;
+ set->edge_ids.data = new_data;
set->edge_ids.count++;
}
}
- *_set = set;
+ *_set = talloc_steal(graph, set);
return NT_STATUS_OK;
}
@@ -304,68 +445,81 @@ static NTSTATUS kcctpl_create_edge_set(struct ldb_context *ldb,
struct kcctpl_multi_edge_set **_set)
{
struct kcctpl_multi_edge_set *set;
+ TALLOC_CTX *tmp_ctx;
struct ldb_message_element *el;
- unsigned int i;
+ uint32_t i;
- set = talloc_zero(graph, struct kcctpl_multi_edge_set);
- NT_STATUS_HAVE_NO_MEMORY(set);
+ tmp_ctx = talloc_new(ldb);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ set = talloc_zero(tmp_ctx, struct kcctpl_multi_edge_set);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(set, tmp_ctx);
set->id = samdb_result_guid(bridge, "objectGUID");
el = ldb_msg_find_element(bridge, "siteLinkList");
+ if (!el) {
+ DEBUG(1, (__location__ ": failed to find siteLinkList "
+ "attribute of object %s\n",
+ ldb_dn_get_linearized(bridge->dn)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
for (i = 0; i < el->num_values; i++) {
struct ldb_val val;
- TALLOC_CTX *tmp_ctx;
struct ldb_dn *dn;
struct GUID site_link_guid;
int ret;
struct kcctpl_multi_edge *edge;
val = el->values[i];
- tmp_ctx = talloc_new(graph);
dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &val);
- if (!ldb_dn_validate(dn)) {
- DEBUG(0, ("invalid DN in siteLinkList attr of %s\n",
- GUID_string(tmp_ctx, &set->id)));
- talloc_free(set);
+ if (!dn) {
+ DEBUG(1, (__location__ ": failed to read a DN from "
+ "siteList attribute of %s\n",
+ ldb_dn_get_linearized(bridge->dn)));
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret = dsdb_find_guid_by_dn(ldb, dn, &site_link_guid);
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find objectGUID for object %s: "
- "%s\n", ldb_dn_get_linearized(dn),
+ DEBUG(1, (__location__ ": failed to find objectGUID "
+ "for object %s: %s\n",
+ ldb_dn_get_linearized(dn),
ldb_strerror(ret)));
- talloc_free(set);
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
edge = kcctpl_find_edge_by_guid(graph, site_link_guid);
if (!edge) {
- DEBUG(0, ("failed to find a graph edge with ID=%s\n",
+ DEBUG(1, (__location__ ": failed to find a graph edge "
+ "with ID=%s\n",
GUID_string(tmp_ctx, &site_link_guid)));
- talloc_free(set);
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- talloc_free(tmp_ctx);
+ if (GUID_equal(&edge->type, &type)) {
+ struct GUID *new_data;
- if (GUID_compare(&edge->type, &type) == 0) {
- set->edge_ids.data = talloc_realloc(set,
- set->edge_ids.data,
- struct GUID,
- set->edge_ids.count + 1);
- NT_STATUS_HAVE_NO_MEMORY_AND_FREE(set->edge_ids.data,
- set);
- set->edge_ids.data[set->edge_ids.count] = site_link_guid;
+ new_data = talloc_realloc(set, set->edge_ids.data,
+ struct GUID,
+ set->edge_ids.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[set->edge_ids.count] = site_link_guid;
+ set->edge_ids.data = new_data;
set->edge_ids.count++;
}
}
- *_set = set;
+ *_set = talloc_steal(graph, set);
+ talloc_free(tmp_ctx);
return NT_STATUS_OK;
}
@@ -378,14 +532,11 @@ static NTSTATUS kcctpl_setup_graph(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
struct kcctpl_graph **_graph)
{
struct kcctpl_graph *graph;
- struct ldb_dn *config_dn, *base_dn;
+ struct ldb_dn *sites_dn, *transports_dn;
TALLOC_CTX *tmp_ctx;
- bool ok;
struct ldb_result *res;
- const char * const site_link_attrs[] = { "objectGUID", NULL };
- const char * const inter_site_transport_attrs[] = { "objectGUID",
- "distinguishedName",
- NULL };
+ const char * const transport_attrs[] = { "objectGUID", NULL };
+ const char * const site_attrs[] = { "objectGUID", "options", NULL };
const char * const attrs[] = { "objectGUID", "cost", "options",
"replInterval", "schedule", NULL };
const char * const site_link_bridge_attrs[] = { "objectGUID",
@@ -393,82 +544,83 @@ static NTSTATUS kcctpl_setup_graph(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
NULL };
int ret;
struct GUID_list vertex_ids;
- unsigned int i;
+ uint32_t i;
NTSTATUS status;
-
- config_dn = samdb_config_dn(ldb);
- if (!config_dn) {
- DEBUG(0, ("failed to find our own Config DN\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
+ struct ldb_message *site;
+ uint64_t site_opts;
tmp_ctx = talloc_new(mem_ctx);
- base_dn = ldb_dn_copy(tmp_ctx, config_dn);
- if (!base_dn) {
- DEBUG(0, ("failed to copy Config DN %s\n",
- ldb_dn_get_linearized(config_dn)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ sites_dn = samdb_sites_dn(ldb, tmp_ctx);
+ if (!sites_dn) {
+ DEBUG(1, (__location__ ": failed to find our own Sites DN\n"));
- ok = ldb_dn_add_child_fmt(base_dn, "CN=Sites");
- if (!ok) {
- if (ldb_dn_validate(base_dn)) {
- DEBUG(0, ("failed to format DN %s\n",
- ldb_dn_get_linearized(base_dn)));
- }
talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- ret = ldb_search(ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
- site_link_attrs, "objectClass=siteLink");
+ ret = ldb_search(ldb, tmp_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE,
+ site_attrs, "objectClass=site");
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find siteLink objects under %s: %s\n",
- ldb_dn_get_linearized(base_dn), ldb_strerror(ret)));
+ DEBUG(1, (__location__ ": failed to find site objects under "
+ "%s: %s\n", ldb_dn_get_linearized(sites_dn),
+ ldb_strerror(ret)));
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ZERO_STRUCT(vertex_ids);
for (i = 0; i < res->count; i++) {
- struct GUID guid;
+ struct GUID guid, *new_data;
guid = samdb_result_guid(res->msgs[i], "objectGUID");
- vertex_ids.data = talloc_realloc(tmp_ctx, vertex_ids.data,
- struct GUID,
- vertex_ids.count + 1);
- NT_STATUS_HAVE_NO_MEMORY_AND_FREE(vertex_ids.data, tmp_ctx);
- vertex_ids.data[vertex_ids.count] = guid;
+
+ new_data = talloc_realloc(tmp_ctx, vertex_ids.data, struct GUID,
+ vertex_ids.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[vertex_ids.count] = guid;
+ vertex_ids.data = new_data;
vertex_ids.count++;
}
- status = kcctpl_create_graph(mem_ctx, &vertex_ids, &graph);
+ status = kcctpl_create_graph(tmp_ctx, vertex_ids, &graph);
if (NT_STATUS_IS_ERR(status)) {
- DEBUG(0, ("failed to create graph: %s\n", nt_errstr(status)));
+ DEBUG(1, (__location__ ": failed to create graph: %s\n",
+ nt_errstr(status)));
+
talloc_free(tmp_ctx);
return status;
}
- /* get site of local DC */
+ site = kcctpl_local_site(ldb, tmp_ctx);
+ if (!site) {
+ DEBUG(1, (__location__ ": failed to find our own local DC's "
+ "site\n"));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ site_opts = samdb_result_int64(site, "options", 0);
+
+ transports_dn = kcctpl_transports_dn(ldb, tmp_ctx);
+ if (!transports_dn) {
+ DEBUG(1, (__location__ ": failed to find our own Inter-Site "
+ "Transports DN\n"));
- ok = ldb_dn_add_child_fmt(base_dn, "CN=Inter-Site Transports");
- if (!ok) {
- if (ldb_dn_validate(base_dn)) {
- DEBUG(0, ("failed to format DN %s\n",
- ldb_dn_get_linearized(base_dn)));
- }
talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- ret = ldb_search(ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
- inter_site_transport_attrs,
- "objectClass=interSiteTransport");
+ ret = ldb_search(ldb, tmp_ctx, &res, transports_dn, LDB_SCOPE_ONELEVEL,
+ transport_attrs, "objectClass=interSiteTransport");
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find interSiteTransport objects under %s: "
- "%s\n", ldb_dn_get_linearized(base_dn),
+ DEBUG(1, (__location__ ": failed to find interSiteTransport "
+ "objects under %s: %s\n",
+ ldb_dn_get_linearized(transports_dn),
ldb_strerror(ret)));
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -478,106 +630,89 @@ static NTSTATUS kcctpl_setup_graph(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
struct ldb_result *res_site_link;
struct GUID transport_guid;
unsigned int j;
- int options;
+ uint64_t transport_opts;
transport = res->msgs[i];
- base_dn = samdb_result_dn(ldb, tmp_ctx, transport,
- "distinguishedName", NULL);
- if (!base_dn) {
- DEBUG(0, ("failed to find DN for interSiteTransport "
- "object\n"));
- talloc_free(graph);
- talloc_free(tmp_ctx);
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* TODO: don't need to ldb_search again; search in res. */
- ret = ldb_search(ldb, tmp_ctx, &res_site_link, base_dn,
+ ret = ldb_search(ldb, tmp_ctx, &res_site_link, transport->dn,
LDB_SCOPE_SUBTREE, attrs,
"objectClass=siteLink");
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find siteLink objects under %s: "
- "%s\n", ldb_dn_get_linearized(base_dn),
+ DEBUG(1, (__location__ ": failed to find siteLink "
+ "objects under %s: %s\n",
+ ldb_dn_get_linearized(transport->dn),
ldb_strerror(ret)));
- talloc_free(graph);
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
transport_guid = samdb_result_guid(transport, "objectGUID");
for (j = 0; j < res_site_link->count; j++) {
- struct kcctpl_multi_edge *edge;
+ struct kcctpl_multi_edge *edge, *new_data;
status = kcctpl_create_edge(ldb, graph, transport_guid,
res_site_link->msgs[j],
&edge);
if (NT_STATUS_IS_ERR(status)) {
- DEBUG(0, ("failed to create edge: %s\n",
- nt_errstr(status)));
- talloc_free(graph);
+ DEBUG(1, (__location__ ": failed to create "
+ "edge: %s\n", nt_errstr(status)));
talloc_free(tmp_ctx);
return status;
}
- graph->edges.data = talloc_realloc(graph,
- graph->edges.data,
- struct kcctpl_multi_edge,
- graph->edges.count + 1);
- if (!graph->edges.data) {
- talloc_free(graph);
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- graph->edges.data[graph->edges.count] = *edge;
+ new_data = talloc_realloc(graph, graph->edges.data,
+ struct kcctpl_multi_edge,
+ graph->edges.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[graph->edges.count] = *edge;
+ graph->edges.data = new_data;
graph->edges.count++;
}
- options = samdb_result_int64(transport, "options", 0);
- if ((options & NTDSTRANSPORT_OPT_BRIDGES_REQUIRED) == 0) {
- struct kcctpl_multi_edge_set *edge_set;
+ transport_opts = samdb_result_int64(transport, "options", 0);
+ if (!(transport_opts & NTDSTRANSPORT_OPT_BRIDGES_REQUIRED) &&
+ !(site_opts & NTDSSETTINGS_OPT_W2K3_BRIDGES_REQUIRED)) {
+ struct kcctpl_multi_edge_set *edge_set, *new_data;
status = kcctpl_create_auto_edge_set(graph,
transport_guid,
res_site_link,
&edge_set);
if (NT_STATUS_IS_ERR(status)) {
- DEBUG(0, ("failed to create edge set: %s\n",
- nt_errstr(status)));
- talloc_free(graph);
+ DEBUG(1, (__location__ ": failed to create "
+ "edge set: %s\n", nt_errstr(status)));
talloc_free(tmp_ctx);
return status;
}
- graph->edge_sets.data = talloc_realloc(graph,
- graph->edge_sets.data,
- struct kcctpl_multi_edge_set,
- graph->edge_sets.count + 1);
- if (!graph->edge_sets.data) {
- talloc_free(graph);
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- graph->edge_sets.data[graph->edge_sets.count] = *edge_set;
+ new_data = talloc_realloc(graph, graph->edge_sets.data,
+ struct kcctpl_multi_edge_set,
+ graph->edge_sets.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[graph->edge_sets.count] = *edge_set;
+ graph->edge_sets.data = new_data;
graph->edge_sets.count++;
} else {
- ret = ldb_search(ldb, tmp_ctx, &res_site_link, base_dn,
- LDB_SCOPE_SUBTREE,
+ ret = ldb_search(ldb, tmp_ctx, &res_site_link,
+ transport->dn, LDB_SCOPE_SUBTREE,
site_link_bridge_attrs,
"objectClass=siteLinkBridge");
if (ret != LDB_SUCCESS) {
- DEBUG(0, ("failed to find siteLinkBridge "
- "objects under %s: %s\n",
- ldb_dn_get_linearized(base_dn),
+ DEBUG(1, (__location__ ": failed to find "
+ "siteLinkBridge objects under %s: "
+ "%s\n",
+ ldb_dn_get_linearized(transport->dn),
ldb_strerror(ret)));
- talloc_free(graph);
+
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
for (j = 0; j < res_site_link->count; j++) {
struct ldb_message *bridge;
- struct kcctpl_multi_edge_set *edge_set;
+ struct kcctpl_multi_edge_set *edge_set,
+ *new_data;
bridge = res_site_link->msgs[j];
status = kcctpl_create_edge_set(ldb, graph,
@@ -585,29 +720,257 @@ static NTSTATUS kcctpl_setup_graph(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
bridge,
&edge_set);
if (NT_STATUS_IS_ERR(status)) {
- DEBUG(0, ("failed to create edge set: "
- "%s\n", nt_errstr(status)));
- talloc_free(graph);
+ DEBUG(1, (__location__ ": failed to "
+ "create edge set: %s\n",
+ nt_errstr(status)));
+
talloc_free(tmp_ctx);
return status;
}
- graph->edge_sets.data = talloc_realloc(graph,
- graph->edge_sets.data,
- struct kcctpl_multi_edge_set,
- graph->edge_sets.count + 1);
- if (!graph->edge_sets.data) {
- talloc_free(graph);
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- graph->edge_sets.data[graph->edge_sets.count] = *edge_set;
+ new_data = talloc_realloc(graph,
+ graph->edge_sets.data,
+ struct kcctpl_multi_edge_set,
+ graph->edge_sets.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data,
+ tmp_ctx);
+ new_data[graph->edge_sets.count] = *edge_set;
+ graph->edge_sets.data = new_data;
graph->edge_sets.count++;
}
}
}
- *_graph = graph;
+ *_graph = talloc_steal(mem_ctx, graph);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+/**
+ * get a bridgehead DC.
+ */
+static NTSTATUS kcctpl_get_bridgehead_dc(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct GUID site_guid,
+ struct ldb_message *cross_ref,
+ struct ldb_message *transport,
+ bool partial_replica_okay,
+ bool detect_failed_dcs,
+ struct ldb_message **_dsa)
+{
+ return NT_STATUS_OK;
+}
+
+/*
+ * color each vertex to indicate which kinds of NC replicas it contains.
+ */
+static NTSTATUS kcctpl_color_vertices(struct ldb_context *ldb,
+ struct kcctpl_graph *graph,
+ struct ldb_message *cross_ref,
+ bool detect_failed_dcs,
+ bool *_found_failed_dcs)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_dn *sites_dn;
+ bool found_failed_dcs, partial_replica_okay;
+ uint32_t i;
+ struct ldb_message *site;
+ struct ldb_result *res;
+ int ret, cr_flags;
+ struct GUID site_guid;
+ struct kcctpl_vertex *site_vertex;
+
+ found_failed_dcs = false;
+
+ tmp_ctx = talloc_new(ldb);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ sites_dn = samdb_sites_dn(ldb, tmp_ctx);
+ if (!sites_dn) {
+ DEBUG(1, (__location__ ": failed to find our own Sites DN\n"));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ for (i = 0; i < graph->vertices.count; i++) {
+ struct kcctpl_vertex *vertex;
+ struct ldb_dn *nc_name;
+ /* TODO: set 'attrs' with its corresponding values */
+ const char * const attrs[] = { NULL };
+
+ vertex = &graph->vertices.data[i];
+
+ ret = ldb_search(ldb, tmp_ctx, &res, sites_dn,
+ LDB_SCOPE_SUBTREE, attrs, "objectGUID=%s",
+ GUID_string(tmp_ctx, &vertex->id));
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, (__location__ ": failed to find site object "
+ "%s: %s\n", GUID_string(tmp_ctx, &vertex->id),
+ ldb_strerror(ret)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (res->count == 0) {
+ DEBUG(1, (__location__ ": failed to find site object "
+ "%s\n", GUID_string(tmp_ctx, &vertex->id)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ site = res->msgs[0];
+
+ nc_name = samdb_result_dn(ldb, tmp_ctx, cross_ref,
+ "nCName", NULL);
+ if (!nc_name) {
+ DEBUG(1, (__location__ ": failed to find nCName "
+ "attribute of object %s\n",
+ ldb_dn_get_linearized(cross_ref->dn)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (true) { /* TODO: site contains 1+ DCs with full replicas of
+ 'nc_name' */
+ vertex->color = RED;
+ } else if (true) { /* TODO: site contains 1+ partial replicas of
+ 'nc_name' */
+ vertex->color = BLACK;
+ } else {
+ vertex->color = WHITE;
+ }
+ }
+
+ site = kcctpl_local_site(ldb, tmp_ctx);
+ if (!site) {
+ DEBUG(1, (__location__ ": failed to find our own local DC's "
+ "site\n"));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ site_guid = samdb_result_guid(site, "objectGUID");
+
+ site_vertex = kcctpl_find_vertex_by_guid(graph, site_guid);
+ if (!site_vertex) {
+ DEBUG(1, (__location__ ": failed to find a vertex edge with "
+ "GUID=%s\n", GUID_string(tmp_ctx, &site_guid)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ partial_replica_okay = (site_vertex->color == BLACK);
+
+ cr_flags = samdb_result_int64(cross_ref, "systemFlags", 0);
+
+ for (i = 0; i < graph->vertices.count; i++) {
+ struct kcctpl_vertex *vertex;
+ struct ldb_dn *transports_dn;
+ const char * const attrs[] = { "objectGUID", "name",
+ "transportAddressAttribute",
+ NULL };
+ uint32_t j;
+
+ vertex = &graph->vertices.data[i];
+
+ transports_dn = kcctpl_transports_dn(ldb, tmp_ctx);
+ if (!transports_dn) {
+ DEBUG(1, (__location__ ": failed to find our own "
+ "Inter-Site Transports DN\n"));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, transports_dn,
+ LDB_SCOPE_ONELEVEL, attrs,
+ "objectClass=interSiteTransport");
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, (__location__ ": failed to find "
+ "interSiteTransport objects under %s: %s\n",
+ ldb_dn_get_linearized(transports_dn),
+ ldb_strerror(ret)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ for (j = 0; j < res->count; j++) {
+ struct ldb_message *transport, *bridgehead;
+ const char *transport_name;
+ struct GUID transport_guid, *new_data;
+ NTSTATUS status;
+
+ transport = res->msgs[j];
+
+ transport_name = samdb_result_string(transport,
+ "name", NULL);
+ if (!transport_name) {
+ DEBUG(1, (__location__ ": failed to find name "
+ "attribute of object %s\n",
+ ldb_dn_get_linearized(transport->dn)));
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ transport_guid = samdb_result_guid(transport,
+ "objectGUID");
+
+ if (site_vertex->color == RED &&
+ strncmp(transport_name, "IP", 2) != 0 &&
+ (cr_flags & FLAG_CR_NTDS_DOMAIN)) {
+ continue;
+ }
+
+ if (!kcctpl_find_edge_by_vertex_guid(graph,
+ vertex->id)) {
+ continue;
+ }
+
+ status = kcctpl_get_bridgehead_dc(ldb, tmp_ctx,
+ site_vertex->id,
+ cross_ref, transport,
+ partial_replica_okay,
+ detect_failed_dcs,
+ &bridgehead);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(1, (__location__ ": failed to get a "
+ "bridgehead DC: %s\n",
+ nt_errstr(status)));
+
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ if (!bridgehead) {
+ found_failed_dcs = true;
+ continue;
+ }
+
+ new_data = talloc_realloc(vertex,
+ vertex->accept_red_red.data,
+ struct GUID,
+ vertex->accept_red_red.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[vertex->accept_red_red.count + 1] = transport_guid;
+ vertex->accept_red_red.data = new_data;
+ vertex->accept_red_red.count++;
+
+ new_data = talloc_realloc(vertex,
+ vertex->accept_black.data,
+ struct GUID,
+ vertex->accept_black.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(new_data, tmp_ctx);
+ new_data[vertex->accept_black.count + 1] = transport_guid;
+ vertex->accept_black.data = new_data;
+ vertex->accept_black.count++;
+ }
+ }
+
+ *_found_failed_dcs = found_failed_dcs;
talloc_free(tmp_ctx);
return NT_STATUS_OK;
}