Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : WINS Replication server
5 :
6 : Copyright (C) Stefan Metzmacher 2005
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "librpc/gen_ndr/ndr_winsrepl.h"
24 : #include "wrepl_server/wrepl_server.h"
25 : #include "nbt_server/wins/winsdb.h"
26 : #include <ldb.h>
27 : #include <ldb_errors.h>
28 : #include "system/time.h"
29 : #include "samba/service_task.h"
30 : #include "lib/messaging/irpc.h"
31 : #include "librpc/gen_ndr/ndr_irpc_c.h"
32 : #include "librpc/gen_ndr/ndr_nbt.h"
33 : #include "param/param.h"
34 :
35 780 : const char *wreplsrv_owner_filter(struct wreplsrv_service *service,
36 : TALLOC_CTX *mem_ctx,
37 : const char *wins_owner)
38 : {
39 780 : if (strcmp(wins_owner, service->wins_db->local_owner) == 0) {
40 9 : return talloc_asprintf(mem_ctx, "(|(winsOwner=%s)(winsOwner=0.0.0.0))",
41 : wins_owner);
42 : }
43 :
44 771 : return talloc_asprintf(mem_ctx, "(&(winsOwner=%s)(!(winsOwner=0.0.0.0)))",
45 : wins_owner);
46 : }
47 :
48 0 : static NTSTATUS wreplsrv_scavenging_owned_records(struct wreplsrv_service *service, TALLOC_CTX *tmp_mem)
49 : {
50 0 : NTSTATUS status;
51 0 : struct winsdb_record *rec = NULL;
52 0 : struct ldb_result *res = NULL;
53 0 : const char *owner_filter;
54 0 : const char *filter;
55 0 : unsigned int i;
56 0 : int ret;
57 0 : time_t now = time(NULL);
58 0 : const char *now_timestr;
59 0 : const char *action;
60 0 : const char *old_state=NULL;
61 0 : const char *new_state=NULL;
62 0 : uint32_t modify_flags;
63 0 : bool modify_record;
64 0 : bool delete_record;
65 0 : bool delete_tombstones;
66 0 : struct timeval tombstone_extra_time;
67 0 : const char *local_owner = service->wins_db->local_owner;
68 0 : bool propagate = lpcfg_parm_bool(service->task->lp_ctx, NULL, "wreplsrv", "propagate name releases", false);
69 :
70 0 : now_timestr = ldb_timestring(tmp_mem, now);
71 0 : NT_STATUS_HAVE_NO_MEMORY(now_timestr);
72 0 : owner_filter = wreplsrv_owner_filter(service, tmp_mem, local_owner);
73 0 : NT_STATUS_HAVE_NO_MEMORY(owner_filter);
74 0 : filter = talloc_asprintf(tmp_mem,
75 : "(&%s(objectClass=winsRecord)"
76 : "(expireTime<=%s))",
77 : owner_filter, now_timestr);
78 0 : NT_STATUS_HAVE_NO_MEMORY(filter);
79 0 : ret = ldb_search(service->wins_db->ldb, tmp_mem, &res, NULL, LDB_SCOPE_SUBTREE, NULL, "%s", filter);
80 0 : if (ret != LDB_SUCCESS) return NT_STATUS_INTERNAL_DB_CORRUPTION;
81 0 : DEBUG(10,("WINS scavenging: filter '%s' count %d\n", filter, res->count));
82 :
83 0 : tombstone_extra_time = timeval_add(&service->startup_time,
84 : service->config.tombstone_extra_timeout,
85 : 0);
86 0 : delete_tombstones = timeval_expired(&tombstone_extra_time);
87 :
88 0 : for (i=0; i < res->count; i++) {
89 0 : bool has_replicas = false;
90 :
91 : /*
92 : * we pass '0' as 'now' here,
93 : * because we want to get the raw timestamps which are in the DB
94 : */
95 0 : status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, 0, &rec);
96 0 : NT_STATUS_NOT_OK_RETURN(status);
97 0 : talloc_free(res->msgs[i]);
98 :
99 0 : modify_flags = 0;
100 0 : modify_record = false;
101 0 : delete_record = false;
102 :
103 0 : switch (rec->state) {
104 0 : case WREPL_STATE_ACTIVE:
105 0 : old_state = "active";
106 0 : if (rec->is_static) {
107 : /*
108 : *we store it again, so that it won't appear
109 : * in the scavenging the next time
110 : */
111 0 : old_state = "active(static)";
112 0 : new_state = "active(static)";
113 0 : modify_flags = 0;
114 0 : modify_record = true;
115 0 : break;
116 : }
117 0 : if (rec->type != WREPL_TYPE_SGROUP || !propagate) {
118 0 : new_state = "released";
119 0 : rec->state = WREPL_STATE_RELEASED;
120 0 : rec->expire_time= service->config.tombstone_interval + now;
121 0 : modify_flags = 0;
122 0 : modify_record = true;
123 0 : break;
124 : }
125 : /* check if there's any replica address */
126 0 : for (i=0;rec->addresses[i];i++) {
127 0 : if (strcmp(rec->addresses[i]->wins_owner, local_owner) != 0) {
128 0 : has_replicas = true;
129 0 : rec->addresses[i]->expire_time= service->config.renew_interval + now;
130 : }
131 : }
132 0 : if (has_replicas) {
133 : /* if it has replica addresses propagate them */
134 0 : new_state = "active(propagated)";
135 0 : rec->state = WREPL_STATE_ACTIVE;
136 0 : rec->expire_time= service->config.renew_interval + now;
137 0 : modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
138 0 : modify_record = true;
139 0 : break;
140 : }
141 : /*
142 : * if it doesn't have replica addresses, make it a tombstone,
143 : * so that the released owned addresses are propagated
144 : */
145 0 : new_state = "tombstone";
146 0 : rec->state = WREPL_STATE_TOMBSTONE;
147 0 : rec->expire_time= time(NULL) +
148 0 : service->config.tombstone_interval +
149 0 : service->config.tombstone_timeout;
150 0 : modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
151 0 : modify_record = true;
152 0 : break;
153 :
154 0 : case WREPL_STATE_RELEASED:
155 0 : old_state = "released";
156 0 : new_state = "tombstone";
157 0 : rec->state = WREPL_STATE_TOMBSTONE;
158 0 : rec->expire_time= service->config.tombstone_timeout + now;
159 0 : modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
160 0 : modify_record = true;
161 0 : break;
162 :
163 0 : case WREPL_STATE_TOMBSTONE:
164 0 : old_state = "tombstone";
165 0 : new_state = "tombstone";
166 0 : if (!delete_tombstones) break;
167 0 : new_state = "deleted";
168 0 : delete_record = true;
169 0 : break;
170 :
171 0 : case WREPL_STATE_RESERVED:
172 0 : DEBUG(0,("%s: corrupted record: %s\n",
173 : __location__, nbt_name_string(rec, rec->name)));
174 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
175 : }
176 :
177 0 : if (modify_record) {
178 0 : action = "modify";
179 0 : ret = winsdb_modify(service->wins_db, rec, modify_flags);
180 0 : } else if (delete_record) {
181 0 : action = "delete";
182 0 : ret = winsdb_delete(service->wins_db, rec);
183 : } else {
184 0 : action = "skip";
185 0 : ret = NBT_RCODE_OK;
186 : }
187 :
188 0 : if (ret != NBT_RCODE_OK) {
189 0 : DEBUG(2,("WINS scavenging: failed to %s name %s (owned:%s -> owned:%s): error:%u\n",
190 : action, nbt_name_string(rec, rec->name), old_state, new_state, ret));
191 : } else {
192 0 : DEBUG(4,("WINS scavenging: %s name: %s (owned:%s -> owned:%s)\n",
193 : action, nbt_name_string(rec, rec->name), old_state, new_state));
194 : }
195 :
196 0 : talloc_free(rec);
197 : }
198 :
199 0 : return NT_STATUS_OK;
200 : }
201 :
202 0 : static NTSTATUS wreplsrv_scavenging_replica_non_active_records(struct wreplsrv_service *service, TALLOC_CTX *tmp_mem)
203 : {
204 0 : NTSTATUS status;
205 0 : struct winsdb_record *rec = NULL;
206 0 : struct ldb_result *res = NULL;
207 0 : const char *owner_filter;
208 0 : const char *filter;
209 0 : unsigned int i;
210 0 : int ret;
211 0 : time_t now = time(NULL);
212 0 : const char *now_timestr;
213 0 : const char *action;
214 0 : const char *old_state=NULL;
215 0 : const char *new_state=NULL;
216 0 : uint32_t modify_flags;
217 0 : bool modify_record;
218 0 : bool delete_record;
219 0 : bool delete_tombstones;
220 0 : struct timeval tombstone_extra_time;
221 :
222 0 : now_timestr = ldb_timestring(tmp_mem, now);
223 0 : NT_STATUS_HAVE_NO_MEMORY(now_timestr);
224 0 : owner_filter = wreplsrv_owner_filter(service, tmp_mem,
225 0 : service->wins_db->local_owner);
226 0 : NT_STATUS_HAVE_NO_MEMORY(owner_filter);
227 0 : filter = talloc_asprintf(tmp_mem,
228 : "(&(!%s)(objectClass=winsRecord)"
229 : "(!(recordState=%u))(expireTime<=%s))",
230 : owner_filter, WREPL_STATE_ACTIVE, now_timestr);
231 0 : NT_STATUS_HAVE_NO_MEMORY(filter);
232 0 : ret = ldb_search(service->wins_db->ldb, tmp_mem, &res, NULL, LDB_SCOPE_SUBTREE, NULL, "%s", filter);
233 0 : if (ret != LDB_SUCCESS) return NT_STATUS_INTERNAL_DB_CORRUPTION;
234 0 : DEBUG(10,("WINS scavenging: filter '%s' count %d\n", filter, res->count));
235 :
236 0 : tombstone_extra_time = timeval_add(&service->startup_time,
237 : service->config.tombstone_extra_timeout,
238 : 0);
239 0 : delete_tombstones = timeval_expired(&tombstone_extra_time);
240 :
241 0 : for (i=0; i < res->count; i++) {
242 : /*
243 : * we pass '0' as 'now' here,
244 : * because we want to get the raw timestamps which are in the DB
245 : */
246 0 : status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, 0, &rec);
247 0 : NT_STATUS_NOT_OK_RETURN(status);
248 0 : talloc_free(res->msgs[i]);
249 :
250 0 : modify_flags = 0;
251 0 : modify_record = false;
252 0 : delete_record = false;
253 :
254 0 : switch (rec->state) {
255 0 : case WREPL_STATE_ACTIVE:
256 0 : DEBUG(0,("%s: corrupted record: %s\n",
257 : __location__, nbt_name_string(rec, rec->name)));
258 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
259 :
260 0 : case WREPL_STATE_RELEASED:
261 0 : old_state = "released";
262 0 : new_state = "tombstone";
263 0 : rec->state = WREPL_STATE_TOMBSTONE;
264 0 : rec->expire_time= service->config.tombstone_timeout + now;
265 0 : modify_flags = 0;
266 0 : modify_record = true;
267 0 : break;
268 :
269 0 : case WREPL_STATE_TOMBSTONE:
270 0 : old_state = "tombstone";
271 0 : new_state = "tombstone";
272 0 : if (!delete_tombstones) break;
273 0 : new_state = "deleted";
274 0 : delete_record = true;
275 0 : break;
276 :
277 0 : case WREPL_STATE_RESERVED:
278 0 : DEBUG(0,("%s: corrupted record: %s\n",
279 : __location__, nbt_name_string(rec, rec->name)));
280 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
281 : }
282 :
283 0 : if (modify_record) {
284 0 : action = "modify";
285 0 : ret = winsdb_modify(service->wins_db, rec, modify_flags);
286 0 : } else if (delete_record) {
287 0 : action = "delete";
288 0 : ret = winsdb_delete(service->wins_db, rec);
289 : } else {
290 0 : action = "skip";
291 0 : ret = NBT_RCODE_OK;
292 : }
293 :
294 0 : if (ret != NBT_RCODE_OK) {
295 0 : DEBUG(2,("WINS scavenging: failed to %s name %s (replica:%s -> replica:%s): error:%u\n",
296 : action, nbt_name_string(rec, rec->name), old_state, new_state, ret));
297 : } else {
298 0 : DEBUG(4,("WINS scavenging: %s name: %s (replica:%s -> replica:%s)\n",
299 : action, nbt_name_string(rec, rec->name), old_state, new_state));
300 : }
301 :
302 0 : talloc_free(rec);
303 : }
304 :
305 0 : return NT_STATUS_OK;
306 : }
307 :
308 : struct verify_state {
309 : struct imessaging_context *msg_ctx;
310 : struct wreplsrv_service *service;
311 : struct winsdb_record *rec;
312 : struct nbtd_proxy_wins_challenge r;
313 : };
314 :
315 0 : static void verify_handler(struct tevent_req *subreq)
316 : {
317 0 : struct verify_state *s =
318 0 : tevent_req_callback_data(subreq,
319 : struct verify_state);
320 0 : struct winsdb_record *rec = s->rec;
321 0 : const char *action;
322 0 : const char *old_state = "active";
323 0 : const char *new_state = "active";
324 0 : const char *new_owner = "replica";
325 0 : uint32_t modify_flags = 0;
326 0 : bool modify_record = false;
327 0 : bool delete_record = false;
328 0 : bool different = false;
329 0 : int ret;
330 0 : NTSTATUS status;
331 0 : uint32_t i, j;
332 :
333 : /*
334 : * - if the name isn't present anymore remove our record
335 : * - if the name is found and not a normal group check if the addresses match,
336 : * - if they don't match remove the record
337 : * - if they match do nothing
338 : * - if an error happens do nothing
339 : */
340 0 : status = dcerpc_nbtd_proxy_wins_challenge_r_recv(subreq, s);
341 0 : TALLOC_FREE(subreq);
342 0 : if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
343 0 : delete_record = true;
344 0 : new_state = "deleted";
345 0 : } else if (NT_STATUS_IS_OK(status) && rec->type != WREPL_TYPE_GROUP) {
346 0 : for (i=0; i < s->r.out.num_addrs; i++) {
347 0 : bool found = false;
348 0 : for (j=0; rec->addresses[j]; j++) {
349 0 : if (strcmp(s->r.out.addrs[i].addr, rec->addresses[j]->address) == 0) {
350 0 : found = true;
351 0 : break;
352 : }
353 : }
354 0 : if (!found) {
355 0 : different = true;
356 0 : break;
357 : }
358 : }
359 0 : } else if (NT_STATUS_IS_OK(status) && rec->type == WREPL_TYPE_GROUP) {
360 0 : if (s->r.out.num_addrs != 1 || strcmp(s->r.out.addrs[0].addr, "255.255.255.255") != 0) {
361 0 : different = true;
362 : }
363 : }
364 :
365 0 : if (different) {
366 : /*
367 : * if the reply from the owning wins server has different addresses
368 : * then take the ownership of the record and make it a tombstone
369 : * this will then hopefully replicated to the original owner of the record
370 : * which will then propagate it's own record, so that the current record will
371 : * be replicated to to us
372 : */
373 0 : DEBUG(2,("WINS scavenging: replica %s verify got different addresses from winsserver: %s: tombstoning record\n",
374 : nbt_name_string(rec, rec->name), rec->wins_owner));
375 :
376 0 : rec->state = WREPL_STATE_TOMBSTONE;
377 0 : rec->expire_time= time(NULL) + s->service->config.tombstone_timeout;
378 0 : for (i=0; rec->addresses[i]; i++) {
379 0 : rec->addresses[i]->expire_time = rec->expire_time;
380 : }
381 0 : modify_record = true;
382 0 : modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
383 0 : new_state = "tombstone";
384 0 : new_owner = "owned";
385 0 : } else if (NT_STATUS_IS_OK(status)) {
386 : /* if the addresses are the same, just update the timestamps */
387 0 : rec->expire_time = time(NULL) + s->service->config.verify_interval;
388 0 : for (i=0; rec->addresses[i]; i++) {
389 0 : rec->addresses[i]->expire_time = rec->expire_time;
390 : }
391 0 : modify_record = true;
392 0 : modify_flags = 0;
393 0 : new_state = "active";
394 : }
395 :
396 0 : if (modify_record) {
397 0 : action = "modify";
398 0 : ret = winsdb_modify(s->service->wins_db, rec, modify_flags);
399 0 : } else if (delete_record) {
400 0 : action = "delete";
401 0 : ret = winsdb_delete(s->service->wins_db, rec);
402 : } else {
403 0 : action = "skip";
404 0 : ret = NBT_RCODE_OK;
405 : }
406 :
407 0 : if (ret != NBT_RCODE_OK) {
408 0 : DEBUG(2,("WINS scavenging: failed to %s name %s (replica:%s -> %s:%s): error:%u\n",
409 : action, nbt_name_string(rec, rec->name), old_state, new_owner, new_state, ret));
410 : } else {
411 0 : DEBUG(4,("WINS scavenging: %s name: %s (replica:%s -> %s:%s): %s: %s\n",
412 : action, nbt_name_string(rec, rec->name), old_state, new_owner, new_state,
413 : rec->wins_owner, nt_errstr(status)));
414 : }
415 :
416 0 : talloc_free(s);
417 0 : }
418 :
419 0 : static NTSTATUS wreplsrv_scavenging_replica_active_records(struct wreplsrv_service *service, TALLOC_CTX *tmp_mem)
420 : {
421 0 : NTSTATUS status;
422 0 : struct winsdb_record *rec = NULL;
423 0 : struct ldb_result *res = NULL;
424 0 : const char *owner_filter;
425 0 : const char *filter;
426 0 : unsigned int i;
427 0 : int ret;
428 0 : time_t now = time(NULL);
429 0 : const char *now_timestr;
430 0 : struct tevent_req *subreq;
431 0 : struct verify_state *s;
432 0 : struct dcerpc_binding_handle *irpc_handle;
433 :
434 0 : now_timestr = ldb_timestring(tmp_mem, now);
435 0 : NT_STATUS_HAVE_NO_MEMORY(now_timestr);
436 0 : owner_filter = wreplsrv_owner_filter(service, tmp_mem,
437 0 : service->wins_db->local_owner);
438 0 : NT_STATUS_HAVE_NO_MEMORY(owner_filter);
439 0 : filter = talloc_asprintf(tmp_mem,
440 : "(&(!%s)(objectClass=winsRecord)"
441 : "(recordState=%u)(expireTime<=%s))",
442 : owner_filter, WREPL_STATE_ACTIVE, now_timestr);
443 0 : NT_STATUS_HAVE_NO_MEMORY(filter);
444 0 : ret = ldb_search(service->wins_db->ldb, tmp_mem, &res, NULL, LDB_SCOPE_SUBTREE, NULL, "%s", filter);
445 0 : if (ret != LDB_SUCCESS) return NT_STATUS_INTERNAL_DB_CORRUPTION;
446 0 : DEBUG(10,("WINS scavenging: filter '%s' count %d\n", filter, res->count));
447 :
448 0 : for (i=0; i < res->count; i++) {
449 : /*
450 : * we pass '0' as 'now' here,
451 : * because we want to get the raw timestamps which are in the DB
452 : */
453 0 : status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, 0, &rec);
454 0 : NT_STATUS_NOT_OK_RETURN(status);
455 0 : talloc_free(res->msgs[i]);
456 :
457 0 : if (rec->state != WREPL_STATE_ACTIVE) {
458 0 : DEBUG(0,("%s: corrupted record: %s\n",
459 : __location__, nbt_name_string(rec, rec->name)));
460 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
461 : }
462 :
463 : /*
464 : * ask the owning wins server if the record still exists,
465 : * if not delete the record
466 : *
467 : * TODO: NOTE: this is a simpliefied version, to verify that
468 : * a record still exist, I assume that w2k3 uses
469 : * DCERPC calls or some WINSREPL packets for this,
470 : * but we use a wins name query
471 : */
472 0 : DEBUG(2,("ask wins server '%s' if '%s' with version_id:%llu still exists\n",
473 : rec->wins_owner, nbt_name_string(rec, rec->name),
474 : (unsigned long long)rec->version));
475 :
476 0 : s = talloc_zero(tmp_mem, struct verify_state);
477 0 : NT_STATUS_HAVE_NO_MEMORY(s);
478 0 : s->msg_ctx = service->task->msg_ctx;
479 0 : s->service = service;
480 0 : s->rec = talloc_steal(s, rec);
481 :
482 0 : s->r.in.name = *rec->name;
483 0 : s->r.in.num_addrs = 1;
484 0 : s->r.in.addrs = talloc_array(s, struct nbtd_proxy_wins_addr, s->r.in.num_addrs);
485 0 : NT_STATUS_HAVE_NO_MEMORY(s->r.in.addrs);
486 : /* TODO: fix pidl to handle inline ipv4address arrays */
487 0 : s->r.in.addrs[0].addr = rec->wins_owner;
488 :
489 0 : irpc_handle = irpc_binding_handle_by_name(s,
490 0 : service->task->msg_ctx,
491 : "nbt_server",
492 : &ndr_table_irpc);
493 0 : if (irpc_handle == NULL) {
494 0 : return NT_STATUS_INTERNAL_ERROR;
495 : }
496 :
497 0 : subreq = dcerpc_nbtd_proxy_wins_challenge_r_send(s,
498 0 : service->task->event_ctx,
499 : irpc_handle,
500 : &s->r);
501 0 : NT_STATUS_HAVE_NO_MEMORY(subreq);
502 :
503 0 : tevent_req_set_callback(subreq, verify_handler, s);
504 :
505 0 : talloc_steal(service, s);
506 : }
507 :
508 0 : return NT_STATUS_OK;
509 : }
510 :
511 3626 : NTSTATUS wreplsrv_scavenging_run(struct wreplsrv_service *service)
512 : {
513 31 : NTSTATUS status;
514 31 : TALLOC_CTX *tmp_mem;
515 3626 : bool skip_first_run = false;
516 :
517 3626 : if (!timeval_expired(&service->scavenging.next_run)) {
518 3561 : return NT_STATUS_OK;
519 : }
520 :
521 65 : if (timeval_is_zero(&service->scavenging.next_run)) {
522 65 : skip_first_run = true;
523 : }
524 :
525 65 : service->scavenging.next_run = timeval_current_ofs(service->config.scavenging_interval, 0);
526 65 : status = wreplsrv_periodic_schedule(service, service->config.scavenging_interval);
527 65 : NT_STATUS_NOT_OK_RETURN(status);
528 :
529 : /*
530 : * if it's the first time this functions is called (startup)
531 : * the next_run is zero, in this case we should not do scavenging
532 : */
533 65 : if (skip_first_run) {
534 65 : return NT_STATUS_OK;
535 : }
536 :
537 0 : if (service->scavenging.processing) {
538 0 : return NT_STATUS_OK;
539 : }
540 :
541 0 : DEBUG(2,("wreplsrv_scavenging_run(): start\n"));
542 :
543 0 : tmp_mem = talloc_new(service);
544 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_mem);
545 0 : service->scavenging.processing = true;
546 0 : status = wreplsrv_scavenging_owned_records(service,tmp_mem);
547 0 : service->scavenging.processing = false;
548 0 : talloc_free(tmp_mem);
549 0 : NT_STATUS_NOT_OK_RETURN(status);
550 :
551 0 : tmp_mem = talloc_new(service);
552 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_mem);
553 0 : service->scavenging.processing = true;
554 0 : status = wreplsrv_scavenging_replica_non_active_records(service, tmp_mem);
555 0 : service->scavenging.processing = false;
556 0 : talloc_free(tmp_mem);
557 0 : NT_STATUS_NOT_OK_RETURN(status);
558 :
559 0 : tmp_mem = talloc_new(service);
560 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_mem);
561 0 : service->scavenging.processing = true;
562 0 : status = wreplsrv_scavenging_replica_active_records(service, tmp_mem);
563 0 : service->scavenging.processing = false;
564 0 : talloc_free(tmp_mem);
565 0 : NT_STATUS_NOT_OK_RETURN(status);
566 :
567 0 : DEBUG(2,("wreplsrv_scavenging_run(): end\n"));
568 :
569 0 : return NT_STATUS_OK;
570 : }
|