2 Unix SMB/CIFS Implementation.
4 DSDB replication service - extended operation code
6 Copyright (C) Andrew Tridgell 2010
7 Copyright (C) Andrew Bartlett 2010
8 Copyright (C) Nadezhda Ivanova 2010
10 based on drepl_notify.c
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "ldb_module.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "samba/service.h"
31 #include "dsdb/repl/drepl_service.h"
32 #include "param/param.h"
35 #define DBGC_CLASS DBGC_DRS_REPL
39 create the role owner source dsa structure
41 nc_dn: the DN of the subtree being replicated
42 source_dsa_dn: the DN of the server that we are replicating from
44 static WERROR
drepl_create_extended_source_dsa(struct dreplsrv_service
*service
,
47 struct ldb_dn
*source_dsa_dn
,
49 struct dreplsrv_partition_source_dsa
**_sdsa
)
51 struct dreplsrv_partition_source_dsa
*sdsa
;
52 struct ldb_context
*ldb
= service
->samdb
;
55 struct ldb_dn
*nc_root
;
56 struct dreplsrv_partition
*p
;
58 sdsa
= talloc_zero(service
, struct dreplsrv_partition_source_dsa
);
59 W_ERROR_HAVE_NO_MEMORY(sdsa
);
61 sdsa
->partition
= talloc_zero(sdsa
, struct dreplsrv_partition
);
62 if (!sdsa
->partition
) {
64 return WERR_NOT_ENOUGH_MEMORY
;
67 sdsa
->partition
->dn
= ldb_dn_copy(sdsa
->partition
, nc_dn
);
68 if (!sdsa
->partition
->dn
) {
70 return WERR_NOT_ENOUGH_MEMORY
;
72 sdsa
->partition
->nc
.dn
= ldb_dn_alloc_linearized(sdsa
->partition
, nc_dn
);
73 if (!sdsa
->partition
->nc
.dn
) {
75 return WERR_NOT_ENOUGH_MEMORY
;
77 ret
= dsdb_find_guid_by_dn(ldb
, nc_dn
, &sdsa
->partition
->nc
.guid
);
78 if (ret
!= LDB_SUCCESS
) {
79 DEBUG(0,(__location__
": Failed to find GUID for %s\n",
80 ldb_dn_get_linearized(nc_dn
)));
82 return WERR_DS_DRA_INTERNAL_ERROR
;
85 sdsa
->repsFrom1
= &sdsa
->_repsFromBlob
.ctr
.ctr1
;
86 ret
= dsdb_find_guid_by_dn(ldb
, source_dsa_dn
, &sdsa
->repsFrom1
->source_dsa_obj_guid
);
87 if (ret
!= LDB_SUCCESS
) {
88 DEBUG(0,(__location__
": Failed to find objectGUID for %s\n",
89 ldb_dn_get_linearized(source_dsa_dn
)));
91 return WERR_DS_DRA_INTERNAL_ERROR
;
94 sdsa
->repsFrom1
->other_info
= talloc_zero(sdsa
, struct repsFromTo1OtherInfo
);
95 if (!sdsa
->repsFrom1
->other_info
) {
97 return WERR_NOT_ENOUGH_MEMORY
;
100 sdsa
->repsFrom1
->other_info
->dns_name
= samdb_ntds_msdcs_dns_name(ldb
,
101 sdsa
->repsFrom1
->other_info
,
102 &sdsa
->repsFrom1
->source_dsa_obj_guid
);
103 if (!sdsa
->repsFrom1
->other_info
->dns_name
) {
105 return WERR_NOT_ENOUGH_MEMORY
;
108 werr
= dreplsrv_out_connection_attach(service
, sdsa
->repsFrom1
, &sdsa
->conn
);
109 if (!W_ERROR_IS_OK(werr
)) {
110 DEBUG(0,(__location__
": Failed to attach connection to %s\n",
111 ldb_dn_get_linearized(nc_dn
)));
116 ret
= dsdb_find_nc_root(service
->samdb
, sdsa
, nc_dn
, &nc_root
);
117 if (ret
!= LDB_SUCCESS
) {
118 DEBUG(0,(__location__
": Failed to find nc_root for %s\n",
119 ldb_dn_get_linearized(nc_dn
)));
121 return WERR_DS_DRA_INTERNAL_ERROR
;
124 /* use the partition uptodateness vector */
125 ret
= dsdb_load_udv_v2(service
->samdb
, nc_root
, sdsa
->partition
,
126 &sdsa
->partition
->uptodatevector
.cursors
,
127 &sdsa
->partition
->uptodatevector
.count
);
128 if (ret
!= LDB_SUCCESS
) {
129 DEBUG(0,(__location__
": Failed to load UDV for %s\n",
130 ldb_dn_get_linearized(nc_root
)));
132 return WERR_DS_DRA_INTERNAL_ERROR
;
135 /* find the highwatermark from the partitions list */
136 for (p
=service
->partitions
; p
; p
=p
->next
) {
137 if (ldb_dn_compare(p
->dn
, nc_root
) == 0) {
138 struct dreplsrv_partition_source_dsa
*s
;
139 werr
= dreplsrv_partition_source_dsa_by_guid(p
,
140 &sdsa
->repsFrom1
->source_dsa_obj_guid
,
142 if (W_ERROR_IS_OK(werr
)) {
143 sdsa
->repsFrom1
->highwatermark
= s
->repsFrom1
->highwatermark
;
144 sdsa
->repsFrom1
->replica_flags
= s
->repsFrom1
->replica_flags
;
149 if (!service
->am_rodc
) {
150 sdsa
->repsFrom1
->replica_flags
|= DRSUAPI_DRS_WRIT_REP
;
157 struct extended_op_data
{
158 dreplsrv_extended_callback_t callback
;
160 struct dreplsrv_partition_source_dsa
*sdsa
;
164 called when an extended op finishes
166 static void extended_op_callback(struct dreplsrv_service
*service
,
168 enum drsuapi_DsExtendedError exop_error
,
171 struct extended_op_data
*data
= talloc_get_type_abort(cb_data
, struct extended_op_data
);
172 talloc_unlink(data
, data
->sdsa
);
173 data
->callback(service
, err
, exop_error
, data
->callback_data
);
178 schedule a getncchanges request to the role owner for an extended operation
180 WERROR
drepl_request_extended_op(struct dreplsrv_service
*service
,
181 struct ldb_dn
*nc_dn
,
182 struct ldb_dn
*source_dsa_dn
,
183 enum drsuapi_DsExtendedOperation extended_op
,
186 dreplsrv_extended_callback_t callback
,
190 struct extended_op_data
*data
;
192 data
= talloc(service
, struct extended_op_data
);
193 W_ERROR_HAVE_NO_MEMORY(data
);
195 werr
= drepl_create_extended_source_dsa(service
, data
, nc_dn
, source_dsa_dn
, min_usn
, &data
->sdsa
);
196 W_ERROR_NOT_OK_RETURN(werr
);
198 data
->callback
= callback
;
199 data
->callback_data
= callback_data
;
201 werr
= dreplsrv_schedule_partition_pull_source(service
, data
->sdsa
,
202 0, extended_op
, fsmo_info
,
203 extended_op_callback
, data
);
204 if (!W_ERROR_IS_OK(werr
)) {
208 dreplsrv_run_pending_ops(service
);