1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r13116: make sure we don't add more than 25 addresses to a record,

and don't return more than 25 in a name query reply

we now also order the addresses from the newest owned address
to the oldest replica address

metze
(This used to be commit 602ec0f1c6)
This commit is contained in:
Stefan Metzmacher 2006-01-24 19:14:08 +00:00 committed by Gerald (Jerry) Carter
parent 5304f34132
commit 8311b9e9e7
3 changed files with 193 additions and 36 deletions

View File

@ -353,11 +353,134 @@ struct winsdb_addr **winsdb_addr_list_make(TALLOC_CTX *mem_ctx)
return addresses;
}
struct winsdb_addr **winsdb_addr_list_add(struct winsdb_addr **addresses, const char *address,
const char *wins_owner, time_t expire_time)
static int winsdb_addr_sort_list (struct winsdb_addr **p1, struct winsdb_addr **p2, void *opaque)
{
size_t len = winsdb_addr_list_length(addresses);
struct winsdb_addr *a1 = talloc_get_type(*p1, struct winsdb_addr);
struct winsdb_addr *a2 = talloc_get_type(*p2, struct winsdb_addr);
struct winsdb_handle *h= talloc_get_type(opaque, struct winsdb_handle);
BOOL a1_owned = False;
BOOL a2_owned = False;
/*
* first the owned addresses with the newest to the oldest address
* then the replica addresses with the newest to the oldest address
*/
if (a2->expire_time != a1->expire_time) {
return a2->expire_time - a1->expire_time;
}
if (strcmp(a2->wins_owner, h->local_owner) == 0) {
a2_owned = True;
}
if (strcmp(a1->wins_owner, h->local_owner) == 0) {
a1_owned = True;
}
return a2_owned - a1_owned;
}
struct winsdb_addr **winsdb_addr_list_add(struct winsdb_handle *h, const struct winsdb_record *rec,
struct winsdb_addr **addresses, const char *address,
const char *wins_owner, time_t expire_time,
BOOL is_name_registration)
{
struct winsdb_addr *old_addr = NULL;
size_t len = 0;
size_t i;
BOOL found_old_replica = False;
/*
* count the addresses and maybe
* find an old entry for the new address
*/
for (i=0; addresses[i]; i++) {
if (old_addr) continue;
if (strcmp(addresses[i]->address, address) == 0) {
old_addr = addresses[i];
}
}
len = i;
/*
* the address is already there
* and we can replace it
*/
if (old_addr) {
goto remove_old_addr;
}
/*
* if we don't have 25 addresses already,
* we can just add the new address
*/
if (len < 25) {
goto add_new_addr;
}
/*
* if we haven't found the address,
* and we have already have 25 addresses
* if so then we need to do the following:
* - if it isn't a name registration, then just ignore the new address
* - if it is a name registration, then first search for
* the oldest replica and if there's no replica address
* search the oldest owned address
*/
if (!is_name_registration) {
return addresses;
}
/*
* find the oldest replica address, if there's no replica
* record at all, find the oldest owned address
*/
for (i=0; addresses[i]; i++) {
BOOL cur_is_replica = False;
/* find out if the current address is a replica */
if (strcmp(addresses[i]->wins_owner, h->local_owner) != 0) {
cur_is_replica = True;
}
/*
* if we already found a replica address and the current address
* is not a replica, then skip it
*/
if (found_old_replica && !cur_is_replica) continue;
/*
* if we found the first replica address, reset the address
* that would be replaced
*/
if (!found_old_replica && cur_is_replica) {
found_old_replica = True;
old_addr = addresses[i];
continue;
}
/*
* if the first address isn't a replica, just start with
* the first one
*/
if (!old_addr) {
old_addr = addresses[i];
continue;
}
/*
* see if we find an older address
*/
if (addresses[i]->expire_time < old_addr->expire_time) {
old_addr = addresses[i];
continue;
}
}
remove_old_addr:
winsdb_addr_list_remove(addresses, old_addr->address);
len --;
add_new_addr:
addresses = talloc_realloc(addresses, addresses, struct winsdb_addr *, len + 2);
if (!addresses) return NULL;
@ -383,6 +506,8 @@ struct winsdb_addr **winsdb_addr_list_add(struct winsdb_addr **addresses, const
addresses[len+1] = NULL;
ldb_qsort(addresses, len+1 , sizeof(addresses[0]), h, (ldb_qsort_cmp_fn_t)winsdb_addr_sort_list);
return addresses;
}
@ -395,7 +520,7 @@ void winsdb_addr_list_remove(struct winsdb_addr **addresses, const char *address
break;
}
}
if (!addresses[i]) return;
if (addresses[i]) talloc_free(addresses[i]);
for (; addresses[i]; i++) {
addresses[i] = addresses[i+1];

View File

@ -90,10 +90,12 @@ static uint8_t wins_register_new(struct nbt_name_socket *nbtsock,
rec.addresses = winsdb_addr_list_make(packet);
if (rec.addresses == NULL) return NBT_RCODE_SVR;
rec.addresses = winsdb_addr_list_add(rec.addresses,
rec.addresses = winsdb_addr_list_add(winssrv->wins_db,
&rec, rec.addresses,
address,
winssrv->wins_db->local_owner,
rec.expire_time);
rec.expire_time,
True);
if (rec.addresses == NULL) return NBT_RCODE_SVR;
DEBUG(4,("WINS: accepted registration of %s with address %s\n",
@ -123,8 +125,13 @@ static uint8_t wins_update_ttl(struct nbt_name_socket *nbtsock,
rec->registered_by = src->addr;
if (winsdb_addr) {
winsdb_addr->wins_owner = winssrv->wins_db->local_owner;
winsdb_addr->expire_time = rec->expire_time;
rec->addresses = winsdb_addr_list_add(winssrv->wins_db,
rec, rec->addresses,
winsdb_addr->address,
winssrv->wins_db->local_owner,
rec->expire_time,
True);
if (rec->addresses == NULL) return NBT_RCODE_SVR;
}
if (strcmp(winssrv->wins_db->local_owner, rec->wins_owner) != 0) {
@ -154,10 +161,12 @@ static uint8_t wins_sgroup_merge(struct nbt_name_socket *nbtsock,
rec->expire_time = time(NULL) + ttl;
rec->registered_by = src->addr;
rec->addresses = winsdb_addr_list_add(rec->addresses,
rec->addresses = winsdb_addr_list_add(winssrv->wins_db,
rec, rec->addresses,
address,
winssrv->wins_db->local_owner,
rec->expire_time);
rec->expire_time,
True);
if (rec->addresses == NULL) return NBT_RCODE_SVR;
DEBUG(5,("WINS: sgroup merge of %s at %s\n",
@ -244,18 +253,25 @@ static void wins_wack_allow(struct wack_state *s)
break;
}
if (found) {
rec->addresses[i]->wins_owner = s->winssrv->wins_db->local_owner;
rec->addresses[i]->expire_time = rec->expire_time;
rec->addresses = winsdb_addr_list_add(s->winssrv->wins_db,
rec, rec->addresses,
s->reg_address,
s->winssrv->wins_db->local_owner,
rec->expire_time,
True);
if (rec->addresses == NULL) goto failed;
continue;
}
winsdb_addr_list_remove(rec->addresses, rec->addresses[i]->address);
}
rec->addresses = winsdb_addr_list_add(rec->addresses,
rec->addresses = winsdb_addr_list_add(s->winssrv->wins_db,
rec, rec->addresses,
s->reg_address,
s->winssrv->wins_db->local_owner,
rec->expire_time);
rec->expire_time,
True);
if (rec->addresses == NULL) goto failed;
/* if we have more than one address, this becomes implicit a MHOMED record */
@ -623,16 +639,24 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
if (addresses_1b && addresses_1b[0]) {
const char **addresses_1c = addresses;
uint32_t i;
uint32_t num_addrs;
addresses = str_list_add(NULL, addresses_1b[0]);
if (!addresses) {
goto notfound;
}
talloc_steal(packet, addresses);
num_addrs = 1;
for (i=0; addresses_1c[i]; i++) {
if (strcmp(addresses_1b[0], addresses_1c[i]) == 0) continue;
/*
* stop when we already have 25 addresses
*/
if (num_addrs >= 25) break;
num_addrs++;
addresses = str_list_add(addresses, addresses_1c[i]);
if (!addresses) {
goto notfound;
@ -643,7 +667,7 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
if (rec->type == WREPL_TYPE_SGROUP) {
nb_flags |= NBT_NM_GROUP;
} else {
nb_flags |= (rec->node <<13);
nb_flags |= (rec->node <<13);
}
found:
@ -705,7 +729,7 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
if (!winsdb_addr_list_check(rec->addresses, src->addr)) {
int i;
DEBUG(4,("WINS: silently ignoring attempted name release on %s from %s\n", nbt_name_string(rec, rec->name), src->addr));
DEBUGADD(4, ("Registered Addressss: \n"));
DEBUGADD(4, ("Registered Addresses: \n"));
for (i=0; rec->addresses && rec->addresses[i]; i++) {
DEBUGADD(4, ("%s\n", rec->addresses[i]->address));
}

View File

@ -686,10 +686,12 @@ static NTSTATUS r_do_add(struct wreplsrv_partner *partner,
for (i=0; i < replica->num_addresses; i++) {
/* TODO: find out if rec->expire_time is correct here */
rec->addresses = winsdb_addr_list_add(rec->addresses,
rec->addresses = winsdb_addr_list_add(partner->service->wins_db,
rec, rec->addresses,
replica->addresses[i].address,
replica->addresses[i].owner,
rec->expire_time);
rec->expire_time,
False);
NT_STATUS_HAVE_NO_MEMORY(rec->addresses);
}
@ -729,10 +731,12 @@ static NTSTATUS r_do_replace(struct wreplsrv_partner *partner,
for (i=0; i < replica->num_addresses; i++) {
/* TODO: find out if rec->expire_time is correct here */
rec->addresses = winsdb_addr_list_add(rec->addresses,
rec->addresses = winsdb_addr_list_add(partner->service->wins_db,
rec, rec->addresses,
replica->addresses[i].address,
replica->addresses[i].owner,
rec->expire_time);
rec->expire_time,
False);
NT_STATUS_HAVE_NO_MEMORY(rec->addresses);
}
@ -829,11 +833,12 @@ static NTSTATUS r_do_mhomed_merge(struct wreplsrv_partner *partner,
merge->registered_by = NULL;
for (i=0; i < replica->num_addresses; i++) {
/* TODO: find out if rec->expire_time is correct here */
merge->addresses = winsdb_addr_list_add(merge->addresses,
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
merge, merge->addresses,
replica->addresses[i].address,
replica->addresses[i].owner,
merge->expire_time);
merge->expire_time,
False);
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
}
@ -849,11 +854,12 @@ static NTSTATUS r_do_mhomed_merge(struct wreplsrv_partner *partner,
}
if (found) continue;
/* TODO: find out if rec->expire_time is correct here */
merge->addresses = winsdb_addr_list_add(merge->addresses,
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
merge, merge->addresses,
rec->addresses[i]->address,
rec->addresses[i]->wins_owner,
merge->expire_time);
rec->addresses[i]->expire_time,
False);
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
}
@ -1198,34 +1204,36 @@ static NTSTATUS r_do_sgroup_merge(struct wreplsrv_partner *partner,
break;
}
/* if it's also in the replica, it'll added later */
if (found) continue;
/*
* if the address isn't in the replica and is owned by replicas owner,
* it won't be added to the merged record
*/
if (strcmp(rec->addresses[i]->wins_owner, owner->address) == 0) {
if (!found && strcmp(rec->addresses[i]->wins_owner, owner->address) == 0) {
changed_old_addrs = True;
continue;
}
/*
* add the address to the merge result, with the old owner and expire_time
* add the address to the merge result, with the old owner and expire_time,
* the owner and expire_time will be overwritten later if the address is
* in the replica too
*/
merge->addresses = winsdb_addr_list_add(merge->addresses,
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
merge, merge->addresses,
rec->addresses[i]->address,
rec->addresses[i]->wins_owner,
rec->addresses[i]->expire_time);
rec->addresses[i]->expire_time,
False);
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
}
for (i=0; i < replica->num_addresses; i++) {
/* TODO: find out if rec->expire_time is correct here */
merge->addresses = winsdb_addr_list_add(merge->addresses,
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
merge, merge->addresses,
replica->addresses[i].address,
replica->addresses[i].owner,
merge->expire_time);
merge->expire_time,
False);
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
}