diff options
-rw-r--r-- | source4/nbt_server/wins/winsdb.c | 55 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsserver.c | 3 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_in_call.c | 29 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_scavenging.c | 18 |
4 files changed, 77 insertions, 28 deletions
diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c index 3e73d89fdd..e3c02e05f0 100644 --- a/source4/nbt_server/wins/winsdb.c +++ b/source4/nbt_server/wins/winsdb.c @@ -446,6 +446,7 @@ NTSTATUS winsdb_lookup(struct winsdb_handle *h, struct winsdb_record *rec; struct ldb_context *wins_db = h->ldb; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + time_t now = time(NULL); /* find the record in the WINS database */ ret = ldb_search(wins_db, winsdb_dn(tmp_ctx, name), LDB_SCOPE_BASE, @@ -461,17 +462,9 @@ NTSTATUS winsdb_lookup(struct winsdb_handle *h, talloc_steal(tmp_ctx, res); - status = winsdb_record(h, res->msgs[0], tmp_ctx, &rec); + status = winsdb_record(h, res->msgs[0], tmp_ctx, now, &rec); if (!NT_STATUS_IS_OK(status)) goto failed; - /* see if it has already expired */ - if (rec->state == WREPL_STATE_ACTIVE && - rec->expire_time <= time(NULL)) { - DEBUG(5,("WINS: expiring name %s (expired at %s)\n", - nbt_name_string(tmp_ctx, rec->name), timestring(tmp_ctx, rec->expire_time))); - rec->state = WREPL_STATE_RELEASED; - } - talloc_steal(mem_ctx, rec); talloc_free(tmp_ctx); *_rec = rec; @@ -482,13 +475,13 @@ failed: return status; } -NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_CTX *mem_ctx, struct winsdb_record **_rec) +NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_CTX *mem_ctx, time_t now, struct winsdb_record **_rec) { NTSTATUS status; struct winsdb_record *rec; struct ldb_message_element *el; struct nbt_name *name; - uint32_t i, num_values; + uint32_t i, j, num_values; rec = talloc(mem_ctx, struct winsdb_record); if (rec == NULL) { @@ -549,17 +542,43 @@ NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_ goto failed; } + /* see if it has already expired */ + if (!rec->is_static && + rec->expire_time <= now && + rec->state == WREPL_STATE_ACTIVE) { + DEBUG(5,("WINS: expiring name %s (expired at %s)\n", + nbt_name_string(mem_ctx, rec->name), timestring(mem_ctx, rec->expire_time))); + rec->state = WREPL_STATE_RELEASED; + } + rec->addresses = talloc_array(rec, struct winsdb_addr *, num_values+1); if (rec->addresses == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; } - for (i=0;i<num_values;i++) { - status = winsdb_addr_decode(h, rec, &el->values[i], rec->addresses, &rec->addresses[i]); + for (i=0,j=0;i<num_values;i++) { + status = winsdb_addr_decode(h, rec, &el->values[i], rec->addresses, &rec->addresses[j]); if (!NT_STATUS_IS_OK(status)) goto failed; + + /* + * the record isn't static and is active + * then don't add the address if it's expired + */ + if (!rec->is_static && + rec->addresses[j]->expire_time <= now && + rec->state == WREPL_STATE_ACTIVE) { + DEBUG(5,("WINS: expiring name addr %s of %s (expired at %s)\n", + rec->addresses[j]->address, nbt_name_string(rec->addresses[j], rec->name), + timestring(rec->addresses[j], rec->addresses[j]->expire_time))); + talloc_free(rec->addresses[j]); + rec->addresses[j] = NULL; + continue; + } + j++; } - rec->addresses[i] = NULL; + rec->addresses[j] = NULL; + num_values = j; if (rec->is_static && rec->state == WREPL_STATE_ACTIVE) { rec->expire_time = get_time_t_max(); @@ -568,6 +587,14 @@ NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_ } } + if (rec->state == WREPL_STATE_ACTIVE) { + if (num_values < 1) { + DEBUG(5,("WINS: expiring name %s (because it has no active addresses)\n", + nbt_name_string(mem_ctx, rec->name))); + rec->state = WREPL_STATE_RELEASED; + } + } + *_rec = rec; return NT_STATUS_OK; failed: diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c index 7d3ab8294b..5cc3a51a00 100644 --- a/source4/nbt_server/wins/winsserver.c +++ b/source4/nbt_server/wins/winsserver.c @@ -492,7 +492,6 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, /* * if the registration is for an address that is currently active, then * just update the expiry time of the record and the address - * TODO: is this correct? */ winsdb_addr = winsdb_addr_list_check(rec->addresses, address); if (winsdb_addr) { @@ -525,9 +524,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, /* * if the registration is for an address that is currently active, then - * just update the expiry time * just update the expiry time of the record and the address - * TODO: is this correct? */ winsdb_addr = winsdb_addr_list_check(rec->addresses, address); if (winsdb_addr) { diff --git a/source4/wrepl_server/wrepl_in_call.c b/source4/wrepl_server/wrepl_in_call.c index 3365a1f146..8ce88db6a9 100644 --- a/source4/wrepl_server/wrepl_in_call.c +++ b/source4/wrepl_server/wrepl_in_call.c @@ -30,6 +30,7 @@ #include "nbt_server/wins/winsdb.h" #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" +#include "system/time.h" static NTSTATUS wreplsrv_in_start_association(struct wreplsrv_in_call *call) { @@ -178,7 +179,8 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) struct wrepl_wins_name *names; struct winsdb_record *rec; NTSTATUS status; - uint32_t i; + uint32_t i, j; + time_t now = time(NULL); owner = wreplsrv_find_owner(service, service->table, owner_in->address); @@ -258,26 +260,37 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) names = talloc_array(call, struct wrepl_wins_name, res->count); NT_STATUS_HAVE_NO_MEMORY(names); - for (i = 0; i < res->count; i++) { - status = winsdb_record(service->wins_db, res->msgs[i], call, &rec); + for (i=0, j=0; i < res->count; i++) { + status = winsdb_record(service->wins_db, res->msgs[i], call, now, &rec); NT_STATUS_NOT_OK_RETURN(status); - status = wreplsrv_record2wins_name(names, &names[i], rec); - NT_STATUS_NOT_OK_RETURN(status); + /* + * it's possible that winsdb_record() made the record RELEASED + * because it's expired, but in the database it's still stored + * as ACTIVE... + * + * make sure we really only replicate ACTIVE and TOMBSTONE records + */ + if (rec->state == WREPL_STATE_ACTIVE || rec->state == WREPL_STATE_TOMBSTONE) { + status = wreplsrv_record2wins_name(names, &names[j], rec); + NT_STATUS_NOT_OK_RETURN(status); + j++; + } + talloc_free(rec); talloc_free(res->msgs[i]); } /* sort the names before we send them */ - qsort(names, res->count, sizeof(struct wrepl_wins_name), (comparison_fn_t)wreplsrv_in_sort_wins_name); + qsort(names, j, sizeof(struct wrepl_wins_name), (comparison_fn_t)wreplsrv_in_sort_wins_name); DEBUG(2,("WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s]\n", - res->count, owner_in->address, + j, owner_in->address, (long long)owner_in->min_version, (long long)owner_in->max_version, call->wreplconn->partner->address)); - reply_out->num_names = res->count; + reply_out->num_names = j; reply_out->names = names; return NT_STATUS_OK; diff --git a/source4/wrepl_server/wrepl_scavenging.c b/source4/wrepl_server/wrepl_scavenging.c index 8f7c7b8e04..a11dae7a06 100644 --- a/source4/wrepl_server/wrepl_scavenging.c +++ b/source4/wrepl_server/wrepl_scavenging.c @@ -84,7 +84,11 @@ static NTSTATUS wreplsrv_scavenging_owned_records(struct wreplsrv_service *servi delete_tombstones = timeval_expired(&tombstone_extra_time); for (i=0; i < res->count; i++) { - status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, &rec); + /* + * we pass '0' as 'now' here, + * because we want to get the raw timestamps which are in the DB + */ + status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, 0, &rec); NT_STATUS_NOT_OK_RETURN(status); talloc_free(res->msgs[i]); @@ -198,7 +202,11 @@ static NTSTATUS wreplsrv_scavenging_replica_non_active_records(struct wreplsrv_s delete_tombstones = timeval_expired(&tombstone_extra_time); for (i=0; i < res->count; i++) { - status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, &rec); + /* + * we pass '0' as 'now' here, + * because we want to get the raw timestamps which are in the DB + */ + status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, 0, &rec); NT_STATUS_NOT_OK_RETURN(status); talloc_free(res->msgs[i]); @@ -390,7 +398,11 @@ static NTSTATUS wreplsrv_scavenging_replica_active_records(struct wreplsrv_servi DEBUG(10,("WINS scavenging: filter '%s' count %d\n", filter, res->count)); for (i=0; i < res->count; i++) { - status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, &rec); + /* + * we pass '0' as 'now' here, + * because we want to get the raw timestamps which are in the DB + */ + status = winsdb_record(service->wins_db, res->msgs[i], tmp_mem, 0, &rec); NT_STATUS_NOT_OK_RETURN(status); talloc_free(res->msgs[i]); |