1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-09 08:58:35 +03:00

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
This commit is contained in:
Andrew Tridgell 2009-10-14 20:25:48 +11:00
parent 41ba2f8189
commit 59818f2f79
2 changed files with 63 additions and 27 deletions

View File

@ -39,6 +39,8 @@ struct drsuapi_bind_state {
/* prototypes of internal functions */
WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
struct drsuapi_DsReplicaUpdateRefsRequest1 *req);
WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct drsuapi_DsReplicaUpdateRefs *r);
WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,

View File

@ -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);
}