Line data Source code
1 : /*
2 : Unix SMB/CIFS Implementation.
3 :
4 : DSDB replication service - extended operation code
5 :
6 : Copyright (C) Andrew Tridgell 2010
7 : Copyright (C) Andrew Bartlett 2010
8 : Copyright (C) Nadezhda Ivanova 2010
9 :
10 : based on drepl_notify.c
11 :
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.
16 :
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.
21 :
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/>.
24 :
25 : */
26 :
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"
33 :
34 : #undef DBGC_CLASS
35 : #define DBGC_CLASS DBGC_DRS_REPL
36 :
37 :
38 : /*
39 : create the role owner source dsa structure
40 :
41 : nc_dn: the DN of the subtree being replicated
42 : source_dsa_dn: the DN of the server that we are replicating from
43 : */
44 1873 : 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)
50 : {
51 0 : struct dreplsrv_partition_source_dsa *sdsa;
52 1873 : struct ldb_context *ldb = service->samdb;
53 0 : int ret;
54 0 : WERROR werr;
55 0 : struct ldb_dn *nc_root;
56 0 : struct dreplsrv_partition *p;
57 :
58 1873 : sdsa = talloc_zero(service, struct dreplsrv_partition_source_dsa);
59 1873 : W_ERROR_HAVE_NO_MEMORY(sdsa);
60 :
61 1873 : sdsa->partition = talloc_zero(sdsa, struct dreplsrv_partition);
62 1873 : if (!sdsa->partition) {
63 0 : talloc_free(sdsa);
64 0 : return WERR_NOT_ENOUGH_MEMORY;
65 : }
66 :
67 1873 : sdsa->partition->dn = ldb_dn_copy(sdsa->partition, nc_dn);
68 1873 : if (!sdsa->partition->dn) {
69 0 : talloc_free(sdsa);
70 0 : return WERR_NOT_ENOUGH_MEMORY;
71 : }
72 1873 : sdsa->partition->nc.dn = ldb_dn_alloc_linearized(sdsa->partition, nc_dn);
73 1873 : if (!sdsa->partition->nc.dn) {
74 0 : talloc_free(sdsa);
75 0 : return WERR_NOT_ENOUGH_MEMORY;
76 : }
77 1873 : ret = dsdb_find_guid_by_dn(ldb, nc_dn, &sdsa->partition->nc.guid);
78 1873 : if (ret != LDB_SUCCESS) {
79 0 : DEBUG(0,(__location__ ": Failed to find GUID for %s\n",
80 : ldb_dn_get_linearized(nc_dn)));
81 0 : talloc_free(sdsa);
82 0 : return WERR_DS_DRA_INTERNAL_ERROR;
83 : }
84 :
85 1873 : sdsa->repsFrom1 = &sdsa->_repsFromBlob.ctr.ctr1;
86 1873 : ret = dsdb_find_guid_by_dn(ldb, source_dsa_dn, &sdsa->repsFrom1->source_dsa_obj_guid);
87 1873 : if (ret != LDB_SUCCESS) {
88 0 : DEBUG(0,(__location__ ": Failed to find objectGUID for %s\n",
89 : ldb_dn_get_linearized(source_dsa_dn)));
90 0 : talloc_free(sdsa);
91 0 : return WERR_DS_DRA_INTERNAL_ERROR;
92 : }
93 :
94 1873 : sdsa->repsFrom1->other_info = talloc_zero(sdsa, struct repsFromTo1OtherInfo);
95 1873 : if (!sdsa->repsFrom1->other_info) {
96 0 : talloc_free(sdsa);
97 0 : return WERR_NOT_ENOUGH_MEMORY;
98 : }
99 :
100 3746 : sdsa->repsFrom1->other_info->dns_name = samdb_ntds_msdcs_dns_name(ldb,
101 1873 : sdsa->repsFrom1->other_info,
102 1873 : &sdsa->repsFrom1->source_dsa_obj_guid);
103 1873 : if (!sdsa->repsFrom1->other_info->dns_name) {
104 0 : talloc_free(sdsa);
105 0 : return WERR_NOT_ENOUGH_MEMORY;
106 : }
107 :
108 1873 : werr = dreplsrv_out_connection_attach(service, sdsa->repsFrom1, &sdsa->conn);
109 1873 : if (!W_ERROR_IS_OK(werr)) {
110 0 : DEBUG(0,(__location__ ": Failed to attach connection to %s\n",
111 : ldb_dn_get_linearized(nc_dn)));
112 0 : talloc_free(sdsa);
113 0 : return werr;
114 : }
115 :
116 1873 : ret = dsdb_find_nc_root(service->samdb, sdsa, nc_dn, &nc_root);
117 1873 : if (ret != LDB_SUCCESS) {
118 0 : DEBUG(0,(__location__ ": Failed to find nc_root for %s\n",
119 : ldb_dn_get_linearized(nc_dn)));
120 0 : talloc_free(sdsa);
121 0 : return WERR_DS_DRA_INTERNAL_ERROR;
122 : }
123 :
124 : /* use the partition uptodateness vector */
125 1873 : ret = dsdb_load_udv_v2(service->samdb, nc_root, sdsa->partition,
126 1873 : &sdsa->partition->uptodatevector.cursors,
127 1873 : &sdsa->partition->uptodatevector.count);
128 1873 : if (ret != LDB_SUCCESS) {
129 0 : DEBUG(0,(__location__ ": Failed to load UDV for %s\n",
130 : ldb_dn_get_linearized(nc_root)));
131 0 : talloc_free(sdsa);
132 0 : return WERR_DS_DRA_INTERNAL_ERROR;
133 : }
134 :
135 : /* find the highwatermark from the partitions list */
136 11238 : for (p=service->partitions; p; p=p->next) {
137 9365 : if (ldb_dn_compare(p->dn, nc_root) == 0) {
138 0 : struct dreplsrv_partition_source_dsa *s;
139 1873 : werr = dreplsrv_partition_source_dsa_by_guid(p,
140 1873 : &sdsa->repsFrom1->source_dsa_obj_guid,
141 : &s);
142 1873 : if (W_ERROR_IS_OK(werr)) {
143 1873 : sdsa->repsFrom1->highwatermark = s->repsFrom1->highwatermark;
144 1873 : sdsa->repsFrom1->replica_flags = s->repsFrom1->replica_flags;
145 : }
146 : }
147 : }
148 :
149 1873 : if (!service->am_rodc) {
150 24 : sdsa->repsFrom1->replica_flags |= DRSUAPI_DRS_WRIT_REP;
151 : }
152 :
153 1873 : *_sdsa = sdsa;
154 1873 : return WERR_OK;
155 : }
156 :
157 : struct extended_op_data {
158 : dreplsrv_extended_callback_t callback;
159 : void *callback_data;
160 : struct dreplsrv_partition_source_dsa *sdsa;
161 : };
162 :
163 : /*
164 : called when an extended op finishes
165 : */
166 1873 : static void extended_op_callback(struct dreplsrv_service *service,
167 : WERROR err,
168 : enum drsuapi_DsExtendedError exop_error,
169 : void *cb_data)
170 : {
171 1873 : struct extended_op_data *data = talloc_get_type_abort(cb_data, struct extended_op_data);
172 1873 : talloc_unlink(data, data->sdsa);
173 1873 : data->callback(service, err, exop_error, data->callback_data);
174 1873 : talloc_free(data);
175 1873 : }
176 :
177 : /*
178 : schedule a getncchanges request to the role owner for an extended operation
179 : */
180 1873 : 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)
188 : {
189 0 : WERROR werr;
190 0 : struct extended_op_data *data;
191 :
192 1873 : data = talloc(service, struct extended_op_data);
193 1873 : W_ERROR_HAVE_NO_MEMORY(data);
194 :
195 1873 : werr = drepl_create_extended_source_dsa(service, data, nc_dn, source_dsa_dn, min_usn, &data->sdsa);
196 1873 : W_ERROR_NOT_OK_RETURN(werr);
197 :
198 1873 : data->callback = callback;
199 1873 : data->callback_data = callback_data;
200 :
201 1873 : werr = dreplsrv_schedule_partition_pull_source(service, data->sdsa,
202 : 0, extended_op, fsmo_info,
203 : extended_op_callback, data);
204 1873 : if (!W_ERROR_IS_OK(werr)) {
205 0 : talloc_free(data);
206 : }
207 :
208 1873 : dreplsrv_run_pending_ops(service);
209 :
210 1873 : return werr;
211 : }
|