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;

	addresses[len] = talloc(addresses, struct winsdb_addr);
	if (!addresses[len]) {
		talloc_free(addresses);
		return NULL;
	}

	addresses[len]->address = talloc_strdup(addresses[len], address);
	if (!addresses[len]->address) {
		talloc_free(addresses);
		return NULL;
	}

	addresses[len]->wins_owner = talloc_strdup(addresses[len], wins_owner);
	if (!addresses[len]->wins_owner) {
		talloc_free(addresses);
		return NULL;
	}

	addresses[len]->expire_time = expire_time;

	addresses[len+1] = NULL;

	LDB_TYPESAFE_QSORT(addresses, len+1, h, winsdb_addr_sort_list);

	return addresses;
}
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;

	 
	for (i=0; addresses[i]; i++) {
		if (old_addr) continue;
		if (strcmp(addresses[i]->address, address) == 0) {
			old_addr = addresses[i];
		}
	}
	len = i;

	 
	if (old_addr) {
		goto remove_old_addr;
	}

	 
	if (len < 25) {
		goto add_new_addr;
	}

	 
	if (!is_name_registration) {
		return addresses;
	}

	 
	for (i=0; addresses[i]; i++) {
		bool cur_is_replica = false;
		 
		if (strcmp(addresses[i]->wins_owner, h->local_owner) != 0) {
			cur_is_replica = true;
		}

		 
		if (found_old_replica && !cur_is_replica) continue;

		 
		if (!found_old_replica && cur_is_replica) {
			found_old_replica = true;
			old_addr = addresses[i];
			continue;
		}

		 
		if (!old_addr) {
			old_addr = addresses[i];
			continue;
		}

		 
		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;

	addresses[len] = talloc(addresses, struct winsdb_addr);
	if (!addresses[len]) {
		talloc_free(addresses);
		return NULL;
	}

	addresses[len]->address = talloc_strdup(addresses[len], address);
	if (!addresses[len]->address) {
		talloc_free(addresses);
		return NULL;
	}

	addresses[len]->wins_owner = talloc_strdup(addresses[len], wins_owner);
	if (!addresses[len]->wins_owner) {
		talloc_free(addresses);
		return NULL;
	}

	addresses[len]->expire_time = expire_time;

	addresses[len+1] = NULL;

	LDB_TYPESAFE_QSORT(addresses, len+1, h, winsdb_addr_sort_list);

	return addresses;
}