• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/dsdb/repl/
1/*
2   Unix SMB/CIFS mplementation.
3   DSDB replication service outgoing Pull-Replication
4
5   Copyright (C) Stefan Metzmacher 2007
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20*/
21
22#include "includes.h"
23#include "dsdb/samdb/samdb.h"
24#include "auth/auth.h"
25#include "smbd/service.h"
26#include "lib/events/events.h"
27#include "lib/messaging/irpc.h"
28#include "dsdb/repl/drepl_service.h"
29#include "lib/ldb/include/ldb_errors.h"
30#include "../lib/util/dlinklist.h"
31#include "librpc/gen_ndr/ndr_misc.h"
32#include "librpc/gen_ndr/ndr_drsuapi.h"
33#include "librpc/gen_ndr/ndr_drsblobs.h"
34#include "libcli/composite/composite.h"
35
36static WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
37						      struct dreplsrv_partition *p,
38						      struct dreplsrv_partition_source_dsa *source,
39						      TALLOC_CTX *mem_ctx)
40{
41	struct dreplsrv_out_operation *op;
42
43	op = talloc_zero(mem_ctx, struct dreplsrv_out_operation);
44	W_ERROR_HAVE_NO_MEMORY(op);
45
46	op->service	= s;
47	op->source_dsa	= source;
48
49	DLIST_ADD_END(s->ops.pending, op, struct dreplsrv_out_operation *);
50	talloc_steal(s, op);
51	return WERR_OK;
52}
53
54static WERROR dreplsrv_schedule_partition_pull(struct dreplsrv_service *s,
55					       struct dreplsrv_partition *p,
56					       TALLOC_CTX *mem_ctx)
57{
58	WERROR status;
59	struct dreplsrv_partition_source_dsa *cur;
60
61	for (cur = p->sources; cur; cur = cur->next) {
62		status = dreplsrv_schedule_partition_pull_source(s, p, cur, mem_ctx);
63		W_ERROR_NOT_OK_RETURN(status);
64	}
65
66	return WERR_OK;
67}
68
69WERROR dreplsrv_schedule_pull_replication(struct dreplsrv_service *s, TALLOC_CTX *mem_ctx)
70{
71	WERROR status;
72	struct dreplsrv_partition *p;
73
74	for (p = s->partitions; p; p = p->next) {
75		status = dreplsrv_schedule_partition_pull(s, p, mem_ctx);
76		W_ERROR_NOT_OK_RETURN(status);
77	}
78
79	return WERR_OK;
80}
81
82
83/* force an immediate of the specified partition by GUID  */
84WERROR dreplsrv_schedule_partition_pull_by_guid(struct dreplsrv_service *s, TALLOC_CTX *mem_ctx,
85						struct GUID *guid)
86{
87	struct dreplsrv_partition *p;
88
89	for (p = s->partitions; p; p = p->next) {
90		if (GUID_compare(&p->nc.guid, guid) == 0) {
91			return dreplsrv_schedule_partition_pull(s, p, mem_ctx);
92		}
93	}
94
95	return WERR_NOT_FOUND;
96}
97
98static void dreplsrv_pending_op_callback(struct dreplsrv_out_operation *op)
99{
100	struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
101	struct dreplsrv_service *s = op->service;
102	time_t t;
103	NTTIME now;
104
105	t = time(NULL);
106	unix_to_nt_time(&now, t);
107
108	rf->result_last_attempt = dreplsrv_op_pull_source_recv(op->creq);
109	if (W_ERROR_IS_OK(rf->result_last_attempt)) {
110		rf->consecutive_sync_failures	= 0;
111		rf->last_success		= now;
112		DEBUG(3,("dreplsrv_op_pull_source(%s)\n",
113			win_errstr(rf->result_last_attempt)));
114		goto done;
115	}
116
117	rf->consecutive_sync_failures++;
118
119	DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n",
120		win_errstr(rf->result_last_attempt),
121		nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
122		rf->consecutive_sync_failures));
123
124done:
125	talloc_free(op);
126	s->ops.current = NULL;
127	dreplsrv_run_pending_ops(s);
128	dreplsrv_notify_run_ops(s);
129}
130
131static void dreplsrv_pending_op_callback_creq(struct composite_context *creq)
132{
133	struct dreplsrv_out_operation *op = talloc_get_type(creq->async.private_data,
134							   struct dreplsrv_out_operation);
135	dreplsrv_pending_op_callback(op);
136}
137
138void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
139{
140	struct dreplsrv_out_operation *op;
141	time_t t;
142	NTTIME now;
143
144	if (s->ops.current || s->ops.n_current) {
145		/* if there's still one running, we're done */
146		return;
147	}
148
149	if (!s->ops.pending) {
150		/* if there're no pending operations, we're done */
151		return;
152	}
153
154	t = time(NULL);
155	unix_to_nt_time(&now, t);
156
157	op = s->ops.pending;
158	s->ops.current = op;
159	DLIST_REMOVE(s->ops.pending, op);
160
161	op->source_dsa->repsFrom1->last_attempt = now;
162
163	op->creq = dreplsrv_op_pull_source_send(op);
164	if (!op->creq) {
165		dreplsrv_pending_op_callback(op);
166		return;
167	}
168
169	op->creq->async.fn		= dreplsrv_pending_op_callback_creq;
170	op->creq->async.private_data	= op;
171}
172