2 Unix SMB/CIFS mplementation.
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 "smbd/service.h"
31 #include "dsdb/repl/drepl_service.h"
32 #include "param/param.h"
36 create the role owner source dsa structure
38 nc_dn: the DN of the subtree being replicated
39 source_dsa_dn: the DN of the server that we are replicating from
41 static WERROR
drepl_create_extended_source_dsa(struct dreplsrv_service
*service
,
44 struct ldb_dn
*source_dsa_dn
,
46 struct dreplsrv_partition_source_dsa
**_sdsa
)
48 struct dreplsrv_partition_source_dsa
*sdsa
;
49 struct ldb_context
*ldb
= service
->samdb
;
52 struct ldb_dn
*nc_root
;
53 struct dreplsrv_partition
*p
;
55 sdsa
= talloc_zero(service
, struct dreplsrv_partition_source_dsa
);
56 W_ERROR_HAVE_NO_MEMORY(sdsa
);
58 sdsa
->partition
= talloc_zero(sdsa
, struct dreplsrv_partition
);
59 if (!sdsa
->partition
) {
64 sdsa
->partition
->dn
= ldb_dn_copy(sdsa
->partition
, nc_dn
);
65 if (!sdsa
->partition
->dn
) {
69 sdsa
->partition
->nc
.dn
= ldb_dn_alloc_linearized(sdsa
->partition
, nc_dn
);
70 if (!sdsa
->partition
->nc
.dn
) {
74 ret
= dsdb_find_guid_by_dn(ldb
, nc_dn
, &sdsa
->partition
->nc
.guid
);
75 if (ret
!= LDB_SUCCESS
) {
76 DEBUG(0,(__location__
": Failed to find GUID for %s\n",
77 ldb_dn_get_linearized(nc_dn
)));
79 return WERR_DS_DRA_INTERNAL_ERROR
;
82 sdsa
->repsFrom1
= &sdsa
->_repsFromBlob
.ctr
.ctr1
;
83 ret
= dsdb_find_guid_by_dn(ldb
, source_dsa_dn
, &sdsa
->repsFrom1
->source_dsa_obj_guid
);
84 if (ret
!= LDB_SUCCESS
) {
85 DEBUG(0,(__location__
": Failed to find objectGUID for %s\n",
86 ldb_dn_get_linearized(source_dsa_dn
)));
88 return WERR_DS_DRA_INTERNAL_ERROR
;
91 sdsa
->repsFrom1
->other_info
= talloc_zero(sdsa
, struct repsFromTo1OtherInfo
);
92 if (!sdsa
->repsFrom1
->other_info
) {
97 sdsa
->repsFrom1
->other_info
->dns_name
= samdb_ntds_msdcs_dns_name(ldb
,
98 sdsa
->repsFrom1
->other_info
,
99 &sdsa
->repsFrom1
->source_dsa_obj_guid
);
100 if (!sdsa
->repsFrom1
->other_info
->dns_name
) {
105 werr
= dreplsrv_out_connection_attach(service
, sdsa
->repsFrom1
, &sdsa
->conn
);
106 if (!W_ERROR_IS_OK(werr
)) {
107 DEBUG(0,(__location__
": Failed to attach connection to %s\n",
108 ldb_dn_get_linearized(nc_dn
)));
113 ret
= dsdb_find_nc_root(service
->samdb
, sdsa
, nc_dn
, &nc_root
);
114 if (ret
!= LDB_SUCCESS
) {
115 DEBUG(0,(__location__
": Failed to find nc_root for %s\n",
116 ldb_dn_get_linearized(nc_dn
)));
118 return WERR_DS_DRA_INTERNAL_ERROR
;
121 /* use the partition uptodateness vector */
122 ret
= dsdb_load_udv_v2(service
->samdb
, nc_root
, sdsa
->partition
,
123 &sdsa
->partition
->uptodatevector
.cursors
,
124 &sdsa
->partition
->uptodatevector
.count
);
125 if (ret
!= LDB_SUCCESS
) {
126 DEBUG(0,(__location__
": Failed to load UDV for %s\n",
127 ldb_dn_get_linearized(nc_root
)));
129 return WERR_DS_DRA_INTERNAL_ERROR
;
132 /* find the highwatermark from the partitions list */
133 for (p
=service
->partitions
; p
; p
=p
->next
) {
134 if (ldb_dn_compare(p
->dn
, nc_root
) == 0) {
135 struct dreplsrv_partition_source_dsa
*s
;
136 werr
= dreplsrv_partition_source_dsa_by_guid(p
,
137 &sdsa
->repsFrom1
->source_dsa_obj_guid
,
139 if (W_ERROR_IS_OK(werr
)) {
140 sdsa
->repsFrom1
->highwatermark
= s
->repsFrom1
->highwatermark
;
141 sdsa
->repsFrom1
->replica_flags
= s
->repsFrom1
->replica_flags
;
146 if (!service
->am_rodc
) {
147 sdsa
->repsFrom1
->replica_flags
|= DRSUAPI_DRS_WRIT_REP
;
154 struct extended_op_data
{
155 dreplsrv_extended_callback_t callback
;
157 struct dreplsrv_partition_source_dsa
*sdsa
;
161 called when an extended op finishes
163 static void extended_op_callback(struct dreplsrv_service
*service
,
165 enum drsuapi_DsExtendedError exop_error
,
168 struct extended_op_data
*data
= talloc_get_type_abort(cb_data
, struct extended_op_data
);
169 talloc_unlink(data
, data
->sdsa
);
170 data
->callback(service
, err
, exop_error
, data
->callback_data
);
175 schedule a getncchanges request to the role owner for an extended operation
177 WERROR
drepl_request_extended_op(struct dreplsrv_service
*service
,
178 struct ldb_dn
*nc_dn
,
179 struct ldb_dn
*source_dsa_dn
,
180 enum drsuapi_DsExtendedOperation extended_op
,
183 dreplsrv_extended_callback_t callback
,
187 struct extended_op_data
*data
;
189 data
= talloc(service
, struct extended_op_data
);
190 W_ERROR_HAVE_NO_MEMORY(data
);
192 werr
= drepl_create_extended_source_dsa(service
, data
, nc_dn
, source_dsa_dn
, min_usn
, &data
->sdsa
);
193 W_ERROR_NOT_OK_RETURN(werr
);
195 data
->callback
= callback
;
196 data
->callback_data
= callback_data
;
198 werr
= dreplsrv_schedule_partition_pull_source(service
, data
->sdsa
,
199 0, extended_op
, fsmo_info
,
200 extended_op_callback
, data
);
201 if (!W_ERROR_IS_OK(werr
)) {
205 dreplsrv_run_pending_ops(service
);