~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/wrepl_server/wrepl_scavenging.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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