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 | }
|
---|