s4-repl: split out the extended op handling
[idra/samba.git] / source4 / dsdb / repl / drepl_extended.c
1 /*
2    Unix SMB/CIFS mplementation.
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 "smbd/service.h"
31 #include "dsdb/repl/drepl_service.h"
32 #include "param/param.h"
33
34
35 /*
36   create the role owner source dsa structure
37
38   nc_dn: the DN of the subtree being replicated
39   source_dsa_dn: the DN of the server that we are replicating from
40  */
41 static WERROR drepl_create_extended_source_dsa(struct dreplsrv_service *service,
42                                                struct ldb_dn *nc_dn,
43                                                struct ldb_dn *source_dsa_dn,
44                                                struct dreplsrv_partition_source_dsa **_sdsa)
45 {
46         struct dreplsrv_partition_source_dsa *sdsa;
47         struct ldb_context *ldb = service->samdb;
48         int ret;
49         WERROR werr;
50
51         sdsa = talloc_zero(service, struct dreplsrv_partition_source_dsa);
52         W_ERROR_HAVE_NO_MEMORY(sdsa);
53
54         sdsa->partition = talloc_zero(sdsa, struct dreplsrv_partition);
55         if (!sdsa->partition) {
56                 talloc_free(sdsa);
57                 return WERR_NOMEM;
58         }
59
60         sdsa->partition->dn = ldb_dn_copy(sdsa->partition, nc_dn);
61         if (!sdsa->partition->dn) {
62                 talloc_free(sdsa);
63                 return WERR_NOMEM;
64         }
65         sdsa->partition->nc.dn = ldb_dn_alloc_linearized(sdsa->partition, nc_dn);
66         if (!sdsa->partition->nc.dn) {
67                 talloc_free(sdsa);
68                 return WERR_NOMEM;
69         }
70         ret = dsdb_find_guid_by_dn(ldb, nc_dn, &sdsa->partition->nc.guid);
71         if (ret != LDB_SUCCESS) {
72                 DEBUG(0,(__location__ ": Failed to find GUID for %s\n",
73                          ldb_dn_get_linearized(nc_dn)));
74                 talloc_free(sdsa);
75                 return WERR_DS_DRA_INTERNAL_ERROR;
76         }
77
78         sdsa->repsFrom1 = &sdsa->_repsFromBlob.ctr.ctr1;
79         ret = dsdb_find_guid_by_dn(ldb, source_dsa_dn, &sdsa->repsFrom1->source_dsa_obj_guid);
80         if (ret != LDB_SUCCESS) {
81                 DEBUG(0,(__location__ ": Failed to find objectGUID for %s\n",
82                          ldb_dn_get_linearized(source_dsa_dn)));
83                 talloc_free(sdsa);
84                 return WERR_DS_DRA_INTERNAL_ERROR;
85         }
86
87         sdsa->repsFrom1->other_info = talloc_zero(sdsa, struct repsFromTo1OtherInfo);
88         if (!sdsa->repsFrom1->other_info) {
89                 talloc_free(sdsa);
90                 return WERR_NOMEM;
91         }
92
93         sdsa->repsFrom1->other_info->dns_name =
94                 talloc_asprintf(sdsa->repsFrom1->other_info, "%s._msdcs.%s",
95                                 GUID_string(sdsa->repsFrom1->other_info, &sdsa->repsFrom1->source_dsa_obj_guid),
96                                 lpcfg_dnsdomain(service->task->lp_ctx));
97         if (!sdsa->repsFrom1->other_info->dns_name) {
98                 talloc_free(sdsa);
99                 return WERR_NOMEM;
100         }
101
102
103         werr = dreplsrv_out_connection_attach(service, sdsa->repsFrom1, &sdsa->conn);
104         if (!W_ERROR_IS_OK(werr)) {
105                 DEBUG(0,(__location__ ": Failed to attach connection to %s\n",
106                          ldb_dn_get_linearized(nc_dn)));
107                 talloc_free(sdsa);
108                 return werr;
109         }
110
111         *_sdsa = sdsa;
112         return WERR_OK;
113 }
114
115 struct extended_op_data {
116         dreplsrv_fsmo_callback_t callback;
117         void *callback_data;
118         struct dreplsrv_partition_source_dsa *sdsa;
119 };
120
121 /*
122   called when an extended op finishes
123  */
124 static void extended_op_callback(struct dreplsrv_service *service,
125                                  WERROR err,
126                                  enum drsuapi_DsExtendedError exop_error,
127                                  void *cb_data)
128 {
129         struct extended_op_data *data = talloc_get_type_abort(cb_data, struct extended_op_data);
130         talloc_free(data->sdsa);
131         data->callback(service, err, exop_error, data->callback_data);
132         talloc_free(data);
133 }
134
135 /*
136   schedule a getncchanges request to the role owner for an extended operation
137  */
138 WERROR drepl_request_extended_op(struct dreplsrv_service *service,
139                                  struct ldb_dn *role_owner_dn,
140                                  struct ldb_dn *fsmo_role_dn,
141                                  enum drsuapi_DsExtendedOperation extended_op,
142                                  uint64_t fsmo_info,
143                                  dreplsrv_fsmo_callback_t callback,
144                                  void *callback_data)
145 {
146         WERROR werr;
147         struct extended_op_data *data;
148         struct dreplsrv_partition_source_dsa *sdsa;
149
150         werr = drepl_create_extended_source_dsa(service, role_owner_dn, fsmo_role_dn, &sdsa);
151         W_ERROR_NOT_OK_RETURN(werr);
152
153         data = talloc(service, struct extended_op_data);
154         W_ERROR_HAVE_NO_MEMORY(data);
155
156         data->callback = callback;
157         data->callback_data = callback_data;
158         data->sdsa = sdsa;
159
160         werr = dreplsrv_schedule_partition_pull_source(service, sdsa,
161                                                        extended_op, fsmo_info,
162                                                        extended_op_callback, data);
163         if (!W_ERROR_IS_OK(werr)) {
164                 talloc_free(sdsa);
165                 talloc_free(data);
166         }
167         return werr;
168 }