summaryrefslogtreecommitdiff
path: root/source4/rpc_server/drsuapi/updaterefs.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-10-14 20:25:48 +1100
committerAndrew Tridgell <tridge@samba.org>2009-10-15 08:20:37 +1100
commit59818f2f793ecc6349b87ee0debc7dd558272552 (patch)
treef78dc83c7aa16b1dadb197cae9bf4f580899d4a5 /source4/rpc_server/drsuapi/updaterefs.c
parent41ba2f81895a8d7d0ccdd5bcbbf7a7d1f415ebaa (diff)
downloadsamba-59818f2f793ecc6349b87ee0debc7dd558272552.tar.gz
samba-59818f2f793ecc6349b87ee0debc7dd558272552.tar.bz2
samba-59818f2f793ecc6349b87ee0debc7dd558272552.zip
s4-drs: implement more of DsUpdateRefs
The DsUpdateRefs calls takes a set of flags that indicates if the server should ignore specific add/delete error codes. This patch also exposes the core UpdateRefs call into a public function, so that it can be called from DsGetNCChanges
Diffstat (limited to 'source4/rpc_server/drsuapi/updaterefs.c')
-rw-r--r--source4/rpc_server/drsuapi/updaterefs.c88
1 files changed, 61 insertions, 27 deletions
diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c
index d01fabf575..60a70c5032 100644
--- a/source4/rpc_server/drsuapi/updaterefs.c
+++ b/source4/rpc_server/drsuapi/updaterefs.c
@@ -35,16 +35,29 @@ struct repsTo {
add a replication destination for a given partition GUID
*/
static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
- struct ldb_dn *dn, struct repsFromTo1 *dest)
+ struct ldb_dn *dn, struct repsFromTo1 *dest,
+ uint32_t options)
{
struct repsTo reps;
WERROR werr;
+ int i;
werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
+ for (i=0; i<reps.count; i++) {
+ if (GUID_compare(&dest->source_dsa_obj_guid,
+ &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) {
+ if (options & DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK) {
+ return WERR_OK;
+ } else {
+ return WERR_DS_DRA_REF_ALREADY_EXISTS;
+ }
+ }
+ }
+
reps.r = talloc_realloc(mem_ctx, reps.r, struct repsFromToBlob, reps.count+1);
if (reps.r == NULL) {
return WERR_DS_DRA_INTERNAL_ERROR;
@@ -66,11 +79,13 @@ static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
delete a replication destination for a given partition GUID
*/
static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
- struct ldb_dn *dn, struct GUID *dest_guid)
+ struct ldb_dn *dn, struct GUID *dest_guid,
+ uint32_t options)
{
struct repsTo reps;
WERROR werr;
int i;
+ bool found = false;
werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count);
if (!W_ERROR_IS_OK(werr)) {
@@ -83,6 +98,7 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
memmove(&reps.r[i], &reps.r[i+1], sizeof(reps.r[i])*(reps.count-(i+1)));
}
reps.count--;
+ found = true;
}
}
@@ -91,35 +107,22 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
return werr;
}
+ if (!found && !(options & DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK)) {
+ return WERR_DS_DRA_REF_NOT_FOUND;
+ }
+
return WERR_OK;
}
/*
- drsuapi_DsReplicaUpdateRefs
+ drsuapi_DsReplicaUpdateRefs - a non RPC version callable from getncchanges
*/
-WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct drsuapi_DsReplicaUpdateRefs *r)
+WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaUpdateRefsRequest1 *req)
{
- struct drsuapi_DsReplicaUpdateRefsRequest1 *req;
WERROR werr;
struct ldb_dn *dn;
- struct dcesrv_handle *h;
- struct drsuapi_bind_state *b_state;
-
- DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
- b_state = h->data;
-
- werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs");
- if (!W_ERROR_IS_OK(werr)) {
- return werr;
- }
- if (r->in.level != 1) {
- DEBUG(0,("DrReplicUpdateRefs - unsupported level %u\n", r->in.level));
- return WERR_DS_DRA_INVALID_PARAMETER;
- }
-
- req = &r->in.req.req1;
DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n",
req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid),
req->options,
@@ -136,10 +139,10 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA
}
if (req->options & DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE) {
- werr = uref_del_dest(b_state->sam_ctx, mem_ctx, dn, &req->dest_dsa_guid);
+ werr = uref_del_dest(b_state->sam_ctx, mem_ctx, dn, &req->dest_dsa_guid, req->options);
if (!W_ERROR_IS_OK(werr)) {
DEBUG(0,("Failed to delete repsTo for %s\n",
- GUID_string(dce_call, &req->dest_dsa_guid)));
+ GUID_string(mem_ctx, &req->dest_dsa_guid)));
goto failed;
}
}
@@ -156,10 +159,10 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA
dest.source_dsa_obj_guid = req->dest_dsa_guid;
dest.replica_flags = req->options;
- werr = uref_add_dest(b_state->sam_ctx, mem_ctx, dn, &dest);
+ werr = uref_add_dest(b_state->sam_ctx, mem_ctx, dn, &dest, req->options);
if (!W_ERROR_IS_OK(werr)) {
- DEBUG(0,("Failed to delete repsTo for %s\n",
- GUID_string(dce_call, &dest.source_dsa_obj_guid)));
+ DEBUG(0,("Failed to add repsTo for %s\n",
+ GUID_string(mem_ctx, &dest.source_dsa_obj_guid)));
goto failed;
}
}
@@ -175,3 +178,34 @@ failed:
ldb_transaction_cancel(b_state->sam_ctx);
return werr;
}
+
+/*
+ drsuapi_DsReplicaUpdateRefs
+*/
+WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaUpdateRefs *r)
+{
+ struct dcesrv_handle *h;
+ struct drsuapi_bind_state *b_state;
+ struct drsuapi_DsReplicaUpdateRefsRequest1 *req;
+ WERROR werr;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
+ b_state = h->data;
+
+ werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs");
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ if (r->in.level != 1) {
+ DEBUG(0,("DrReplicUpdateRefs - unsupported level %u\n", r->in.level));
+ return WERR_DS_DRA_INVALID_PARAMETER;
+ }
+
+ req = &r->in.req.req1;
+
+ return drsuapi_UpdateRefs(b_state, mem_ctx, req);
+}
+
+