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:
parent
5304f34132
commit
8311b9e9e7
@ -353,11 +353,134 @@ struct winsdb_addr **winsdb_addr_list_make(TALLOC_CTX *mem_ctx)
|
|||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winsdb_addr **winsdb_addr_list_add(struct winsdb_addr **addresses, const char *address,
|
static int winsdb_addr_sort_list (struct winsdb_addr **p1, struct winsdb_addr **p2, void *opaque)
|
||||||
const char *wins_owner, time_t expire_time)
|
|
||||||
{
|
{
|
||||||
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);
|
addresses = talloc_realloc(addresses, addresses, struct winsdb_addr *, len + 2);
|
||||||
if (!addresses) return NULL;
|
if (!addresses) return NULL;
|
||||||
|
|
||||||
@ -383,6 +506,8 @@ struct winsdb_addr **winsdb_addr_list_add(struct winsdb_addr **addresses, const
|
|||||||
|
|
||||||
addresses[len+1] = NULL;
|
addresses[len+1] = NULL;
|
||||||
|
|
||||||
|
ldb_qsort(addresses, len+1 , sizeof(addresses[0]), h, (ldb_qsort_cmp_fn_t)winsdb_addr_sort_list);
|
||||||
|
|
||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +520,7 @@ void winsdb_addr_list_remove(struct winsdb_addr **addresses, const char *address
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!addresses[i]) return;
|
if (addresses[i]) talloc_free(addresses[i]);
|
||||||
|
|
||||||
for (; addresses[i]; i++) {
|
for (; addresses[i]; i++) {
|
||||||
addresses[i] = addresses[i+1];
|
addresses[i] = addresses[i+1];
|
||||||
|
@ -90,10 +90,12 @@ static uint8_t wins_register_new(struct nbt_name_socket *nbtsock,
|
|||||||
rec.addresses = winsdb_addr_list_make(packet);
|
rec.addresses = winsdb_addr_list_make(packet);
|
||||||
if (rec.addresses == NULL) return NBT_RCODE_SVR;
|
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,
|
address,
|
||||||
winssrv->wins_db->local_owner,
|
winssrv->wins_db->local_owner,
|
||||||
rec.expire_time);
|
rec.expire_time,
|
||||||
|
True);
|
||||||
if (rec.addresses == NULL) return NBT_RCODE_SVR;
|
if (rec.addresses == NULL) return NBT_RCODE_SVR;
|
||||||
|
|
||||||
DEBUG(4,("WINS: accepted registration of %s with address %s\n",
|
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;
|
rec->registered_by = src->addr;
|
||||||
|
|
||||||
if (winsdb_addr) {
|
if (winsdb_addr) {
|
||||||
winsdb_addr->wins_owner = winssrv->wins_db->local_owner;
|
rec->addresses = winsdb_addr_list_add(winssrv->wins_db,
|
||||||
winsdb_addr->expire_time = rec->expire_time;
|
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) {
|
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->expire_time = time(NULL) + ttl;
|
||||||
rec->registered_by = src->addr;
|
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,
|
address,
|
||||||
winssrv->wins_db->local_owner,
|
winssrv->wins_db->local_owner,
|
||||||
rec->expire_time);
|
rec->expire_time,
|
||||||
|
True);
|
||||||
if (rec->addresses == NULL) return NBT_RCODE_SVR;
|
if (rec->addresses == NULL) return NBT_RCODE_SVR;
|
||||||
|
|
||||||
DEBUG(5,("WINS: sgroup merge of %s at %s\n",
|
DEBUG(5,("WINS: sgroup merge of %s at %s\n",
|
||||||
@ -244,18 +253,25 @@ static void wins_wack_allow(struct wack_state *s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
rec->addresses[i]->wins_owner = s->winssrv->wins_db->local_owner;
|
rec->addresses = winsdb_addr_list_add(s->winssrv->wins_db,
|
||||||
rec->addresses[i]->expire_time = rec->expire_time;
|
rec, rec->addresses,
|
||||||
|
s->reg_address,
|
||||||
|
s->winssrv->wins_db->local_owner,
|
||||||
|
rec->expire_time,
|
||||||
|
True);
|
||||||
|
if (rec->addresses == NULL) goto failed;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
winsdb_addr_list_remove(rec->addresses, rec->addresses[i]->address);
|
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->reg_address,
|
||||||
s->winssrv->wins_db->local_owner,
|
s->winssrv->wins_db->local_owner,
|
||||||
rec->expire_time);
|
rec->expire_time,
|
||||||
|
True);
|
||||||
if (rec->addresses == NULL) goto failed;
|
if (rec->addresses == NULL) goto failed;
|
||||||
|
|
||||||
/* if we have more than one address, this becomes implicit a MHOMED record */
|
/* 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]) {
|
if (addresses_1b && addresses_1b[0]) {
|
||||||
const char **addresses_1c = addresses;
|
const char **addresses_1c = addresses;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
uint32_t num_addrs;
|
||||||
|
|
||||||
addresses = str_list_add(NULL, addresses_1b[0]);
|
addresses = str_list_add(NULL, addresses_1b[0]);
|
||||||
if (!addresses) {
|
if (!addresses) {
|
||||||
goto notfound;
|
goto notfound;
|
||||||
}
|
}
|
||||||
talloc_steal(packet, addresses);
|
talloc_steal(packet, addresses);
|
||||||
|
num_addrs = 1;
|
||||||
|
|
||||||
for (i=0; addresses_1c[i]; i++) {
|
for (i=0; addresses_1c[i]; i++) {
|
||||||
if (strcmp(addresses_1b[0], addresses_1c[i]) == 0) continue;
|
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]);
|
addresses = str_list_add(addresses, addresses_1c[i]);
|
||||||
if (!addresses) {
|
if (!addresses) {
|
||||||
goto notfound;
|
goto notfound;
|
||||||
@ -643,7 +667,7 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
|
|||||||
if (rec->type == WREPL_TYPE_SGROUP) {
|
if (rec->type == WREPL_TYPE_SGROUP) {
|
||||||
nb_flags |= NBT_NM_GROUP;
|
nb_flags |= NBT_NM_GROUP;
|
||||||
} else {
|
} else {
|
||||||
nb_flags |= (rec->node <<13);
|
nb_flags |= (rec->node <<13);
|
||||||
}
|
}
|
||||||
|
|
||||||
found:
|
found:
|
||||||
@ -705,7 +729,7 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
|
|||||||
if (!winsdb_addr_list_check(rec->addresses, src->addr)) {
|
if (!winsdb_addr_list_check(rec->addresses, src->addr)) {
|
||||||
int i;
|
int i;
|
||||||
DEBUG(4,("WINS: silently ignoring attempted name release on %s from %s\n", nbt_name_string(rec, rec->name), src->addr));
|
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++) {
|
for (i=0; rec->addresses && rec->addresses[i]; i++) {
|
||||||
DEBUGADD(4, ("%s\n", rec->addresses[i]->address));
|
DEBUGADD(4, ("%s\n", rec->addresses[i]->address));
|
||||||
}
|
}
|
||||||
|
@ -686,10 +686,12 @@ static NTSTATUS r_do_add(struct wreplsrv_partner *partner,
|
|||||||
|
|
||||||
for (i=0; i < replica->num_addresses; i++) {
|
for (i=0; i < replica->num_addresses; i++) {
|
||||||
/* TODO: find out if rec->expire_time is correct here */
|
/* 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].address,
|
||||||
replica->addresses[i].owner,
|
replica->addresses[i].owner,
|
||||||
rec->expire_time);
|
rec->expire_time,
|
||||||
|
False);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(rec->addresses);
|
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++) {
|
for (i=0; i < replica->num_addresses; i++) {
|
||||||
/* TODO: find out if rec->expire_time is correct here */
|
/* 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].address,
|
||||||
replica->addresses[i].owner,
|
replica->addresses[i].owner,
|
||||||
rec->expire_time);
|
rec->expire_time,
|
||||||
|
False);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(rec->addresses);
|
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;
|
merge->registered_by = NULL;
|
||||||
|
|
||||||
for (i=0; i < replica->num_addresses; i++) {
|
for (i=0; i < replica->num_addresses; i++) {
|
||||||
/* TODO: find out if rec->expire_time is correct here */
|
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
|
||||||
merge->addresses = winsdb_addr_list_add(merge->addresses,
|
merge, merge->addresses,
|
||||||
replica->addresses[i].address,
|
replica->addresses[i].address,
|
||||||
replica->addresses[i].owner,
|
replica->addresses[i].owner,
|
||||||
merge->expire_time);
|
merge->expire_time,
|
||||||
|
False);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,11 +854,12 @@ static NTSTATUS r_do_mhomed_merge(struct wreplsrv_partner *partner,
|
|||||||
}
|
}
|
||||||
if (found) continue;
|
if (found) continue;
|
||||||
|
|
||||||
/* TODO: find out if rec->expire_time is correct here */
|
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
|
||||||
merge->addresses = winsdb_addr_list_add(merge->addresses,
|
merge, merge->addresses,
|
||||||
rec->addresses[i]->address,
|
rec->addresses[i]->address,
|
||||||
rec->addresses[i]->wins_owner,
|
rec->addresses[i]->wins_owner,
|
||||||
merge->expire_time);
|
rec->addresses[i]->expire_time,
|
||||||
|
False);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,34 +1204,36 @@ static NTSTATUS r_do_sgroup_merge(struct wreplsrv_partner *partner,
|
|||||||
break;
|
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,
|
* if the address isn't in the replica and is owned by replicas owner,
|
||||||
* it won't be added to the merged record
|
* 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;
|
changed_old_addrs = True;
|
||||||
continue;
|
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]->address,
|
||||||
rec->addresses[i]->wins_owner,
|
rec->addresses[i]->wins_owner,
|
||||||
rec->addresses[i]->expire_time);
|
rec->addresses[i]->expire_time,
|
||||||
|
False);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i < replica->num_addresses; i++) {
|
for (i=0; i < replica->num_addresses; i++) {
|
||||||
/* TODO: find out if rec->expire_time is correct here */
|
merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
|
||||||
merge->addresses = winsdb_addr_list_add(merge->addresses,
|
merge, merge->addresses,
|
||||||
replica->addresses[i].address,
|
replica->addresses[i].address,
|
||||||
replica->addresses[i].owner,
|
replica->addresses[i].owner,
|
||||||
merge->expire_time);
|
merge->expire_time,
|
||||||
|
False);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
NT_STATUS_HAVE_NO_MEMORY(merge->addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user