VERSION: Disable GIT_SNAPSHOT for the 4.16.2 release.
[Samba.git] / source4 / dsdb / repl / drepl_extended.c
blob8b5bb6faf6308d577ef225efa7465dd4fbca11e9
1 /*
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/>.
27 #include "includes.h"
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"
34 #undef DBGC_CLASS
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,
45 TALLOC_CTX *mem_ctx,
46 struct ldb_dn *nc_dn,
47 struct ldb_dn *source_dsa_dn,
48 uint64_t min_usn,
49 struct dreplsrv_partition_source_dsa **_sdsa)
51 struct dreplsrv_partition_source_dsa *sdsa;
52 struct ldb_context *ldb = service->samdb;
53 int ret;
54 WERROR werr;
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) {
63 talloc_free(sdsa);
64 return WERR_NOT_ENOUGH_MEMORY;
67 sdsa->partition->dn = ldb_dn_copy(sdsa->partition, nc_dn);
68 if (!sdsa->partition->dn) {
69 talloc_free(sdsa);
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) {
74 talloc_free(sdsa);
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)));
81 talloc_free(sdsa);
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)));
90 talloc_free(sdsa);
91 return WERR_DS_DRA_INTERNAL_ERROR;
94 sdsa->repsFrom1->other_info = talloc_zero(sdsa, struct repsFromTo1OtherInfo);
95 if (!sdsa->repsFrom1->other_info) {
96 talloc_free(sdsa);
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) {
104 talloc_free(sdsa);
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)));
112 talloc_free(sdsa);
113 return werr;
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)));
120 talloc_free(sdsa);
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)));
131 talloc_free(sdsa);
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,
141 &s);
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;
153 *_sdsa = sdsa;
154 return WERR_OK;
157 struct extended_op_data {
158 dreplsrv_extended_callback_t callback;
159 void *callback_data;
160 struct dreplsrv_partition_source_dsa *sdsa;
164 called when an extended op finishes
166 static void extended_op_callback(struct dreplsrv_service *service,
167 WERROR err,
168 enum drsuapi_DsExtendedError exop_error,
169 void *cb_data)
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);
174 talloc_free(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,
184 uint64_t fsmo_info,
185 uint64_t min_usn,
186 dreplsrv_extended_callback_t callback,
187 void *callback_data)
189 WERROR werr;
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)) {
205 talloc_free(data);
208 dreplsrv_run_pending_ops(service);
210 return werr;