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
=
97 talloc_asprintf(sdsa
->repsFrom1
->other_info
, "%s._msdcs.%s",
98 GUID_string(sdsa
->repsFrom1
->other_info
, &sdsa
->repsFrom1
->source_dsa_obj_guid
),
99 lpcfg_dnsdomain(service
->task
->lp_ctx
));
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_free(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
;
188 struct dreplsrv_partition_source_dsa
*sdsa
;
190 werr
= drepl_create_extended_source_dsa(service
, nc_dn
, source_dsa_dn
, min_usn
, &sdsa
);
191 W_ERROR_NOT_OK_RETURN(werr
);
193 data
= talloc(service
, struct extended_op_data
);
194 W_ERROR_HAVE_NO_MEMORY(data
);
196 data
->callback
= callback
;
197 data
->callback_data
= callback_data
;
200 werr
= dreplsrv_schedule_partition_pull_source(service
, sdsa
,
201 0, extended_op
, fsmo_info
,
202 extended_op_callback
, data
);
203 if (!W_ERROR_IS_OK(werr
)) {
208 dreplsrv_run_pending_ops(service
);