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
,
43 struct ldb_dn
*source_dsa_dn
,
45 struct dreplsrv_partition_source_dsa
**_sdsa
)
47 struct dreplsrv_partition_source_dsa
*sdsa
;
48 struct ldb_context
*ldb
= service
->samdb
;
51 struct ldb_dn
*nc_root
;
52 struct dreplsrv_partition
*p
;
54 sdsa
= talloc_zero(service
, struct dreplsrv_partition_source_dsa
);
55 W_ERROR_HAVE_NO_MEMORY(sdsa
);
57 sdsa
->partition
= talloc_zero(sdsa
, struct dreplsrv_partition
);
58 if (!sdsa
->partition
) {
63 sdsa
->partition
->dn
= ldb_dn_copy(sdsa
->partition
, nc_dn
);
64 if (!sdsa
->partition
->dn
) {
68 sdsa
->partition
->nc
.dn
= ldb_dn_alloc_linearized(sdsa
->partition
, nc_dn
);
69 if (!sdsa
->partition
->nc
.dn
) {
73 ret
= dsdb_find_guid_by_dn(ldb
, nc_dn
, &sdsa
->partition
->nc
.guid
);
74 if (ret
!= LDB_SUCCESS
) {
75 DEBUG(0,(__location__
": Failed to find GUID for %s\n",
76 ldb_dn_get_linearized(nc_dn
)));
78 return WERR_DS_DRA_INTERNAL_ERROR
;
81 sdsa
->repsFrom1
= &sdsa
->_repsFromBlob
.ctr
.ctr1
;
82 ret
= dsdb_find_guid_by_dn(ldb
, source_dsa_dn
, &sdsa
->repsFrom1
->source_dsa_obj_guid
);
83 if (ret
!= LDB_SUCCESS
) {
84 DEBUG(0,(__location__
": Failed to find objectGUID for %s\n",
85 ldb_dn_get_linearized(source_dsa_dn
)));
87 return WERR_DS_DRA_INTERNAL_ERROR
;
90 sdsa
->repsFrom1
->other_info
= talloc_zero(sdsa
, struct repsFromTo1OtherInfo
);
91 if (!sdsa
->repsFrom1
->other_info
) {
96 sdsa
->repsFrom1
->other_info
->dns_name
= samdb_ntds_msdcs_dns_name(ldb
,
97 sdsa
->repsFrom1
->other_info
,
98 &sdsa
->repsFrom1
->source_dsa_obj_guid
);
99 if (!sdsa
->repsFrom1
->other_info
->dns_name
) {
104 werr
= dreplsrv_out_connection_attach(service
, sdsa
->repsFrom1
, &sdsa
->conn
);
105 if (!W_ERROR_IS_OK(werr
)) {
106 DEBUG(0,(__location__
": Failed to attach connection to %s\n",
107 ldb_dn_get_linearized(nc_dn
)));
112 ret
= dsdb_find_nc_root(service
->samdb
, sdsa
, nc_dn
, &nc_root
);
113 if (ret
!= LDB_SUCCESS
) {
114 DEBUG(0,(__location__
": Failed to find nc_root for %s\n",
115 ldb_dn_get_linearized(nc_dn
)));
117 return WERR_DS_DRA_INTERNAL_ERROR
;
120 /* use the partition uptodateness vector */
121 ret
= dsdb_load_udv_v2(service
->samdb
, nc_root
, sdsa
->partition
,
122 &sdsa
->partition
->uptodatevector
.cursors
,
123 &sdsa
->partition
->uptodatevector
.count
);
124 if (ret
!= LDB_SUCCESS
) {
125 DEBUG(0,(__location__
": Failed to load UDV for %s\n",
126 ldb_dn_get_linearized(nc_root
)));
128 return WERR_DS_DRA_INTERNAL_ERROR
;
131 /* find the highwatermark from the partitions list */
132 for (p
=service
->partitions
; p
; p
=p
->next
) {
133 if (ldb_dn_compare(p
->dn
, nc_root
) == 0) {
134 struct dreplsrv_partition_source_dsa
*s
;
135 werr
= dreplsrv_partition_source_dsa_by_guid(p
,
136 &sdsa
->repsFrom1
->source_dsa_obj_guid
,
138 if (W_ERROR_IS_OK(werr
)) {
139 sdsa
->repsFrom1
->highwatermark
= s
->repsFrom1
->highwatermark
;
140 sdsa
->repsFrom1
->replica_flags
= s
->repsFrom1
->replica_flags
;
145 if (!service
->am_rodc
) {
146 sdsa
->repsFrom1
->replica_flags
|= DRSUAPI_DRS_WRIT_REP
;
153 struct extended_op_data
{
154 dreplsrv_extended_callback_t callback
;
156 struct dreplsrv_partition_source_dsa
*sdsa
;
160 called when an extended op finishes
162 static void extended_op_callback(struct dreplsrv_service
*service
,
164 enum drsuapi_DsExtendedError exop_error
,
167 struct extended_op_data
*data
= talloc_get_type_abort(cb_data
, struct extended_op_data
);
168 talloc_free(data
->sdsa
);
169 data
->callback(service
, err
, exop_error
, data
->callback_data
);
174 schedule a getncchanges request to the role owner for an extended operation
176 WERROR
drepl_request_extended_op(struct dreplsrv_service
*service
,
177 struct ldb_dn
*nc_dn
,
178 struct ldb_dn
*source_dsa_dn
,
179 enum drsuapi_DsExtendedOperation extended_op
,
182 dreplsrv_extended_callback_t callback
,
186 struct extended_op_data
*data
;
187 struct dreplsrv_partition_source_dsa
*sdsa
;
189 werr
= drepl_create_extended_source_dsa(service
, nc_dn
, source_dsa_dn
, min_usn
, &sdsa
);
190 W_ERROR_NOT_OK_RETURN(werr
);
192 data
= talloc(service
, struct extended_op_data
);
193 W_ERROR_HAVE_NO_MEMORY(data
);
195 data
->callback
= callback
;
196 data
->callback_data
= callback_data
;
199 werr
= dreplsrv_schedule_partition_pull_source(service
, sdsa
,
200 0, extended_op
, fsmo_info
,
201 extended_op_callback
, data
);
202 if (!W_ERROR_IS_OK(werr
)) {
207 dreplsrv_run_pending_ops(service
);