diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-10-14 20:25:48 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-10-15 08:20:37 +1100 |
commit | 59818f2f793ecc6349b87ee0debc7dd558272552 (patch) | |
tree | f78dc83c7aa16b1dadb197cae9bf4f580899d4a5 /source4/rpc_server/drsuapi | |
parent | 41ba2f81895a8d7d0ccdd5bcbbf7a7d1f415ebaa (diff) | |
download | samba-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')
-rw-r--r-- | source4/rpc_server/drsuapi/dcesrv_drsuapi.h | 2 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/updaterefs.c | 88 |
2 files changed, 63 insertions, 27 deletions
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h index 82899c8432..e42d9569e7 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h @@ -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, 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); +} + + |