preview of winsdb stuff

Stefan (metze) Metzmacher metze at metzemix.de
Mon Nov 18 11:24:06 GMT 2002


I fixed a seg fault
and some compiler warnings...

At 08:08 18.11.2002 +0100, Stefan (metze) Metzmacher wrote:
>Hi all,
>
>here's the preview of my winsdb stuff...
>
>it's working for me but must be tested a lot!
>
>Can some please test this?
>
>NOTE: this patch uses not the wins.tdb it uses wins_test.tdb, so if you 
>want to test the conversion from the old wins.tdb format to the new you 
>need to copy wins.tdb to wins_test.tdb first!
>
>The clean up of the winsserver code and the wrepld code follows in a 
>seperate patch witch requires this one.


metze
-----------------------------------------------------------------------------
Stefan "metze" Metzmacher <metze at metzemix.de>
-------------- next part --------------
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/Makefile.in HEAD-nmbd/source/Makefile.in
--- HEAD/source/Makefile.in	Fri Nov 15 18:42:55 2002
+++ HEAD-nmbd/source/Makefile.in	Fri Nov 15 18:42:41 2002
@@ -297,7 +297,11 @@ MSDFS_OBJ = msdfs/msdfs.o 
 
 SMBD_OBJ = $(SMBD_OBJ_MAIN) $(SMBD_OBJ_BASE)
 
-NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
+WINSDB_OBJ = nmbd/winsdb_interface.o nmbd/winsdb_tdb.o
+
+NMBD_OBJ_MAIN = nmbd/nmbd.o
+
+NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd_globals.o nmbd/nmbd_become_dmb.o \
             nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
             nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \
             nmbd/nmbd_incomingdgrams.o nmbd/nmbd_incomingrequests.o \
@@ -310,14 +314,14 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o 
             nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \
             nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
 
-NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
-           $(PROFILE_OBJ) $(LIB_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
+NMBD_OBJ =  $(NMBD_OBJ_MAIN) $(NMBD_OBJ1) $(WINSDB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) \
+	    $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
 
 WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \
              wrepld/partners.o
 
-WREPL_OBJ = $(WREPL_OBJ1)  $(PARAM_OBJ) $(UBIQX_OBJ) \
-	    $(PROFILE_OBJ) $(LIB_OBJ)
+WREPL_OBJ = $(WREPL_OBJ1) $(NMBD_OBJ1) $(WINSDB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) \
+	    $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
 
 SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
            web/swat.o web/neg_lang.o 
@@ -475,7 +479,8 @@ SMBFILTER_OBJ = utils/smbfilter.o $(LIBS
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
 PROTO_OBJ = $(SMBD_OBJ_MAIN) \
-	    $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
+	    $(SMBD_OBJ_SRV) $(NMBD_OBJ_MAIN) $(NMBD_OBJ1) $(WINSDB_OBJ) \
+	    $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
 	    $(SMBW_OBJ1) $(SMBWRAPPER_OBJ1) $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
 	    $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) \
 	    $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) \
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/include/includes.h HEAD-nmbd/source/include/includes.h
--- HEAD/source/include/includes.h	Thu Oct 31 07:21:34 2002
+++ HEAD-nmbd/source/include/includes.h	Thu Nov 14 14:04:04 2002
@@ -730,6 +730,7 @@ extern int errno;
 #include "smb.h"
 #include "smbw.h"
 #include "nameserv.h"
+#include "winsdb.h"
 
 #include "secrets.h"
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/include/nameserv.h HEAD-nmbd/source/include/nameserv.h
--- HEAD/source/include/nameserv.h	Sat Aug 17 19:21:11 2002
+++ HEAD-nmbd/source/include/nameserv.h	Thu Nov 14 15:36:35 2002
@@ -2,8 +2,9 @@
 #define _NAMESERV_H_
 /* 
    Unix SMB/CIFS implementation.
-   NBT netbios header - version 2
-   Copyright (C) Andrew Tridgell 1994-1998
+   NBT netbios header - version 3
+   Copyright (C) Andrew Tridgell 		1994-1998
+   Copyright (C) Stefan (metze) Metzmacher	2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,12 +22,6 @@
    
 */
 
-#define INFO_VERSION	"INFO/version"
-#define INFO_COUNT	"INFO/num_entries"
-#define INFO_ID_HIGH	"INFO/id_high"
-#define INFO_ID_LOW	"INFO/id_low"
-#define ENTRY_PREFIX 	"ENTRY/"
-
 #define PERMANENT_TTL 0
 
 /* NTAS uses 2, NT uses 1, WfWg uses 0 */
@@ -176,57 +171,54 @@ enum name_source {LMHOSTS_NAME, REGISTER
 enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
 enum packet_type {NMB_PACKET, DGRAM_PACKET};
 
-enum master_state
-{
-  MST_NONE,
-  MST_POTENTIAL,
-  MST_BACKUP,
-  MST_MSB,
-  MST_BROWSER,
-  MST_UNBECOMING_MASTER
-};
-
-enum domain_state
-{
-  DOMAIN_NONE,
-  DOMAIN_WAIT,
-  DOMAIN_MST
-};
-
-enum logon_state
-{
-  LOGON_NONE,
-  LOGON_WAIT,
-  LOGON_SRV
+enum master_state {
+	MST_NONE,
+	MST_POTENTIAL,
+	MST_BACKUP,
+	MST_MSB,
+	MST_BROWSER,
+	MST_UNBECOMING_MASTER
+};
+
+enum domain_state {
+	DOMAIN_NONE,
+	DOMAIN_WAIT,
+	DOMAIN_MST
+};
+
+enum logon_state {
+	LOGON_NONE,
+	LOGON_WAIT,
+	LOGON_SRV
 };
 
 struct subnet_record;
 
-struct nmb_data
-{
-  uint16 nb_flags;         /* Netbios flags. */
-  int num_ips;             /* Number of ip entries. */
-  struct in_addr *ip;      /* The ip list for this name. */
-
-  enum name_source source; /* Where the name came from. */
-
-  time_t death_time; /* The time the record must be removed (do not remove if 0). */
-  time_t refresh_time; /* The time the record should be refreshed. */
-  
-  SMB_BIG_UINT id;		/* unique id */
-  struct in_addr wins_ip;	/* the adress of the wins server this record comes from */
+struct nmb_addr {
+	struct in_addr ip;	/* address of the record */
+	time_t ttl; /* The time the record should be refreshed. */
+	struct in_addr owner;	/* the adress of the wins server this record comes from */
+};
 
-  int wins_flags;		/* similar to the netbios flags but different ! */
+struct nmb_data {
+	uint16 nb_flags;         /* Netbios flags. */
+	int wins_flags;		/* similar to the netbios flags but different ! */
+	struct in_addr owner;	/* the adress of the wins server this record comes from */
+	SMB_BIG_UINT id;		/* unique id */
+	time_t ttl; 	/* The time the record must be removed (do not remove if 0). */
+	time_t refresh_time; 	/* The time the record should be refreshed. */
+	int num_addrs;             /* Number of ip_records entries. */
+	struct nmb_addr *addrs;      /* The ip_record list for this name. */
 };
 
 /* This structure represents an entry in a local netbios name list. */
-struct name_record
-  {
-  ubi_trNode            node[1];
-  struct subnet_record *subnet;
-  struct nmb_name       name;    /* The netbios name. */
-  struct nmb_data       data;    /* The netbios data. */
-  };
+struct name_record {
+	ubi_trNode            node[1];
+	struct subnet_record *subnet;
+	enum name_source source; /* Where the name came from. */
+	struct nmb_name	name;    /* The netbios name. */
+	struct nmb_data	data; 	/* address,... of the netbios name */
+};
 
 /* Browser cache for synchronising browse lists. */
 struct browse_cache_record
@@ -622,15 +614,17 @@ extern struct subnet_record *remote_broa
 #define NEXT_SUBNET_INCLUDING_UNICAST(x) (get_next_subnet_maybe_unicast((x)))
 
 /* wins replication record used between nmbd and wrepld */
+#define MAX_WINS_GROUP_IPS 25
 typedef struct _WINS_RECORD {
 	char name[17];
 	char type;
 	int nb_flags;
 	int wins_flags;
+	struct in_addr owner;
 	SMB_BIG_UINT id;
+	time_t time;
 	int num_ips;
-	struct in_addr ip[25];
-	struct in_addr wins_ip;
+	struct in_addr ips[MAX_WINS_GROUP_IPS];
 } WINS_RECORD;
 
 /* To be removed. */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/include/winsdb.h HEAD-nmbd/source/include/winsdb.h
--- HEAD/source/include/winsdb.h	Thu Jan  1 01:00:00 1970
+++ HEAD-nmbd/source/include/winsdb.h	Mon Nov 18 12:05:55 2002
@@ -0,0 +1,61 @@
+/* 
+   Unix SMB/CIFS implementation.
+   WINSDB structures
+ 
+   Copyright (C) Stefan (metze) Metzmacher 2002
+
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _WINSDB_H
+#define _WINSDB_H
+
+
+/* let it be 0 until we have a stable interface --metze */
+#define WINSDB_INTERFACE_VERSION 1
+
+/* Backend to use by default when no backend was specified */
+#define WINSDB_DEFAULT_BACKEND "tdb"
+
+typedef struct winsdb_context 
+{
+	TALLOC_CTX 		*mem_ctx;
+	const char		*backendname;
+	void			*private_data;
+
+	NTSTATUS (*open) (struct winsdb_context *, BOOL write_db);
+	NTSTATUS (*close) (struct winsdb_context *);
+		
+	NTSTATUS (*get_global_id) (struct winsdb_context *, SMB_BIG_UINT *current_id);
+	NTSTATUS (*store_global_id) (struct winsdb_context *, SMB_BIG_UINT current_id);
+			
+	NTSTATUS (*get_next_record) (struct winsdb_context *, struct name_record **namerec);
+	NTSTATUS (*store_record) (struct winsdb_context *,const struct name_record *namerec);
+		
+	void (*free_private_data)(struct winsdb_context **);
+} WINSDB_CONTEXT;
+
+typedef NTSTATUS (*winsdb_init_function)(WINSDB_CONTEXT *, const char *);
+
+struct winsdb_init_function_entry {
+	char *module_name;
+	/* Function to create a winsdb_context */
+	winsdb_init_function init;
+	struct winsdb_init_function_entry *prev;
+	struct winsdb_init_function_entry *next;
+};
+
+#endif /* _WINSDB_H */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/asyncdns.c HEAD-nmbd/source/nmbd/asyncdns.c
--- HEAD/source/nmbd/asyncdns.c	Mon Jul 29 06:34:56 2002
+++ HEAD-nmbd/source/nmbd/asyncdns.c	Fri Nov  8 08:58:13 2002
@@ -24,13 +24,17 @@
   Add a DNS result to the name cache.
 ****************************************************************************/
 
-static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr)
+static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr ip)
 {
   int name_type = question->name_type;
   char *qname = question->name;
+  struct nmb_addr addr;
+  addr.ip = ip;
+  addr.owner = wins_fake_ip();
+  addr.ttl = 60*60;
   
   
-  if (!addr.s_addr) {
+  if (!ip.s_addr) {
     /* add the fail to WINS cache of names. give it 1 hour in the cache */
     DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
     (void)add_name_to_subnet( wins_server_subnet, qname, name_type,
@@ -39,8 +43,8 @@ static struct name_record *add_dns_resul
   }
 
   /* add it to our WINS cache of names. give it 2 hours in the cache */
-  DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
-
+  DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(ip)));
+  addr.ttl = 2*60*60;
   return( add_name_to_subnet( wins_server_subnet, qname, name_type,
                               NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) );
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd.c HEAD-nmbd/source/nmbd/nmbd.c
--- HEAD/source/nmbd/nmbd.c	Wed Nov 13 19:52:36 2002
+++ HEAD-nmbd/source/nmbd/nmbd.c	Thu Nov 14 18:39:06 2002
@@ -23,9 +23,9 @@
 
 #include "includes.h"
 
-int ClientNMB       = -1;
-int ClientDGRAM     = -1;
-int global_nmb_port = -1;
+extern int ClientNMB;
+extern int ClientDGRAM;
+extern int global_nmb_port;
 
 extern BOOL global_in_nmbd;
 
@@ -33,11 +33,11 @@ extern BOOL global_in_nmbd;
 static BOOL is_daemon = False;
 
 /* have we found LanMan clients yet? */
-BOOL found_lm_clients = False;
+extern BOOL found_lm_clients;
 
 /* what server type are we currently */
 
-time_t StartupTime = 0;
+extern time_t StartupTime;
 
 /**************************************************************************** **
  Handle a SIGTERM in band.
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_become_lmb.c HEAD-nmbd/source/nmbd/nmbd_become_lmb.c
--- HEAD/source/nmbd/nmbd_become_lmb.c	Wed Nov 13 19:52:36 2002
+++ HEAD-nmbd/source/nmbd/nmbd_become_lmb.c	Wed Nov 13 20:22:59 2002
@@ -38,15 +38,25 @@ void insert_permanent_name_into_unicast(
   if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
   {
     /* The name needs to be created on the unicast subnet. */
+    struct nmb_addr addr;
+    addr.ip = subrec->myip;
+    addr.owner = wins_fake_ip();
+    addr.ttl = PERMANENT_TTL;
+    
     (void)add_name_to_subnet( unicast_subnet, nmbname->name,
                               nmbname->name_type, nb_type,
-                              PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
+                              PERMANENT_TTL, PERMANENT_NAME, 1, &addr);
   }
   else
   {
     /* The name already exists on the unicast subnet. Add our local
        IP for the given broadcast subnet to the name. */
-    add_ip_to_name_record( namerec, subrec->myip);
+    struct nmb_addr addr;
+    addr.ip = subrec->myip;
+    addr.owner = wins_fake_ip();
+    addr.ttl = PERMANENT_TTL;
+    
+    add_ip_to_name_record( namerec, addr);
   }
 }
 
@@ -63,7 +73,7 @@ static void remove_permanent_name_from_u
   {
     /* Remove this broadcast subnet IP address from the name. */
     remove_ip_from_name_record( namerec, subrec->myip);
-    if(namerec->data.num_ips == 0)
+    if(namerec->data.num_addrs == 0)
       remove_name_from_namelist( unicast_subnet, namerec);
   }
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_elections.c HEAD-nmbd/source/nmbd/nmbd_elections.c
--- HEAD/source/nmbd/nmbd_elections.c	Wed Nov 13 19:52:37 2002
+++ HEAD-nmbd/source/nmbd/nmbd_elections.c	Thu Nov 14 18:31:10 2002
@@ -24,7 +24,7 @@
 #include "includes.h"
 
 /* Election parameters. */
-extern time_t StartupTime;
+time_t StartupTime;
 
 /****************************************************************************
   Send an election datagram packet.
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_globals.c HEAD-nmbd/source/nmbd/nmbd_globals.c
--- HEAD/source/nmbd/nmbd_globals.c	Thu Jan  1 01:00:00 1970
+++ HEAD-nmbd/source/nmbd/nmbd_globals.c	Fri Nov 15 08:08:38 2002
@@ -0,0 +1,35 @@
+/*
+   Unix SMB/CIFS implementation.
+   NBT netbios routines and daemon - version 2
+   Copyright (C) Andrew Tridgell 1994-1998
+   Copyright (C) Jeremy Allison 1997-2002
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   
+*/
+
+#include "includes.h"
+
+int ClientNMB       = -1;
+int ClientDGRAM     = -1;
+int global_nmb_port = -1;
+
+/* have we found LanMan clients yet? */
+BOOL found_lm_clients = False;
+
+/* what server type are we currently */
+
+time_t StartupTime = 0;
+
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_incomingrequests.c HEAD-nmbd/source/nmbd/nmbd_incomingrequests.c
--- HEAD/source/nmbd/nmbd_incomingrequests.c	Wed Nov 13 19:52:38 2002
+++ HEAD-nmbd/source/nmbd/nmbd_incomingrequests.c	Wed Nov 13 20:23:00 2002
@@ -111,8 +111,8 @@ group release name %s from IP %s on subn
 
   /* We only care about someone trying to release one of our names. */
   if( namerec
-   && ( (namerec->data.source == SELF_NAME)
-     || (namerec->data.source == PERMANENT_NAME) ) )
+   && ( (namerec->source == SELF_NAME)
+     || (namerec->source == PERMANENT_NAME) ) )
   {
     rcode = ACT_ERR;
     DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
@@ -235,7 +235,7 @@ IP %s on subnet %s\n", nmb_namestr(quest
    * later to queries.
    */
 
-  if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
+  if((namerec != NULL) && (namerec->source == WINS_PROXY_NAME))
   {
     remove_name_from_namelist( subrec, namerec );
     namerec = NULL;
@@ -246,8 +246,8 @@ IP %s on subnet %s\n", nmb_namestr(quest
     /* Unique name. */
 
     if( (namerec != NULL)
-     && ( (namerec->data.source == SELF_NAME)
-       || (namerec->data.source == PERMANENT_NAME)
+     && ( (namerec->source == SELF_NAME)
+       || (namerec->source == PERMANENT_NAME)
        || NAME_GROUP(namerec) ) )
     {
       /* No-one can register one of Samba's names, nor can they
@@ -259,7 +259,7 @@ IP %s on subnet %s\n", nmb_namestr(quest
     else if(namerec != NULL)
     {
       /* Update the namelist record with the new information. */
-      namerec->data.ip[0] = from_ip;
+      namerec->data.addrs[0].ip = from_ip;
       update_name_ttl(namerec, ttl);
 
       DEBUG(3,("process_name_registration_request: Updated name record %s \
@@ -273,8 +273,8 @@ with IP %s on subnet %s\n",nmb_namestr(&
 
     if( (namerec != NULL)
      && !NAME_GROUP(namerec)
-     && ( (namerec->data.source == SELF_NAME)
-       || (namerec->data.source == PERMANENT_NAME) ) )
+     && ( (namerec->source == SELF_NAME)
+       || (namerec->source == PERMANENT_NAME) ) )
     {
       /* Disallow group names when we have a unique name. */
       send_name_registration_response(ACT_ERR, 0, p);  
@@ -350,8 +350,8 @@ subnet %s - name not found.\n", nmb_name
 
   while (buf < bufend) 
   {
-    if( (namerec->data.source == SELF_NAME)
-     || (namerec->data.source == PERMANENT_NAME) )
+    if( (namerec->source == SELF_NAME)
+     || (namerec->source == PERMANENT_NAME) )
     {
       int name_type = namerec->name.name_type;
       
@@ -473,8 +473,8 @@ void process_name_query_request(struct s
 
 	/* Check if it is a name that expired */
 	if (namerec && 
-	    ((namerec->data.death_time != PERMANENT_TTL) && 
-	     (namerec->data.death_time < p->timestamp))) {
+	    ((namerec->data.ttl != PERMANENT_TTL) && 
+	     (namerec->data.ttl < p->timestamp))) {
 		DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
 		namerec = NULL;
 	}
@@ -490,9 +490,9 @@ void process_name_query_request(struct s
 		
 		if (!bcast || 
 		    (bcast && ((name_type == 0x1b) ||
-			       (namerec->data.source == SELF_NAME) ||
-			       (namerec->data.source == PERMANENT_NAME) ||
-			       ((namerec->data.source == WINS_PROXY_NAME) &&
+			       (namerec->source == SELF_NAME) ||
+			       (namerec->source == PERMANENT_NAME) ||
+			       ((namerec->source == WINS_PROXY_NAME) &&
 				((name_type == 0) || (name_type == 0x20)))))) {
 			/* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY, 
 			   or it's a Domain Master type. */
@@ -505,9 +505,9 @@ void process_name_query_request(struct s
 			 * replies to a broadcast query.
 			 */
 			
-			if (namerec->data.source == WINS_PROXY_NAME) {
-				for( i = 0; i < namerec->data.num_ips; i++) {
-					if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
+			if (namerec->source == WINS_PROXY_NAME) {
+				for( i = 0; i < namerec->data.num_addrs; i++) {
+					if (same_net(namerec->data.addrs[i].ip, subrec->myip, subrec->mask_ip)) {
 						DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n", 
 							 nmb_namestr(&namerec->name), subrec->subnet_name ));
 						return;
@@ -515,30 +515,30 @@ void process_name_query_request(struct s
 				}
 			}
 
-			ttl = (namerec->data.death_time != PERMANENT_TTL) ?
-				namerec->data.death_time - p->timestamp : lp_max_ttl();
+			ttl = (namerec->data.ttl != PERMANENT_TTL) ?
+				namerec->data.ttl - p->timestamp : lp_max_ttl();
 
 			/* Copy all known ip addresses into the return data. */
 			/* Optimise for the common case of one IP address so 
 			   we don't need a malloc. */
 
-			if (namerec->data.num_ips == 1) {
+			if (namerec->data.num_addrs == 1) {
 				prdata = rdata;
 			} else {
-				if ((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
+				if ((prdata = (char *)malloc( namerec->data.num_addrs * 6 )) == NULL) {
 					DEBUG(0,("process_name_query_request: malloc fail !\n"));
 					return;
 				}
 			}
 
-			for (i = 0; i < namerec->data.num_ips; i++) {
+			for (i = 0; i < namerec->data.num_addrs; i++) {
 				set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
-				putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
+				putip((char *)&prdata[2+(i*6)], &namerec->data.addrs[i].ip);
 			}
 
 			sort_query_replies(prdata, i, p->ip);
 			
-			reply_data_len = namerec->data.num_ips * 6;
+			reply_data_len = namerec->data.num_addrs * 6;
 			success = True;
 		}
 	}
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_lmhosts.c HEAD-nmbd/source/nmbd/nmbd_lmhosts.c
--- HEAD/source/nmbd/nmbd_lmhosts.c	Wed Jan 30 07:08:22 2002
+++ HEAD-nmbd/source/nmbd/nmbd_lmhosts.c	Fri Nov  8 09:02:07 2002
@@ -60,14 +60,22 @@ void load_lmhosts_file(char *fname)
 
     if(name_type == -1)
     {
+      struct nmb_addr addr;
+      addr.ip = ipaddr;
+      addr.owner = wins_fake_ip();
+      addr.ttl = PERMANENT_TTL;
       /* Add the (0) and (0x20) names directly into the namelist for this subnet. */
-      (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
-      (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
+      (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&addr);
+      (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&addr);
     }
     else
     {
+      struct nmb_addr addr;
+      addr.ip = ipaddr;
+      addr.owner = wins_fake_ip();
+      addr.ttl = PERMANENT_TTL;
       /* Add the given name type to the subnet namelist. */
-      (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
+      (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&addr);
     }
   }
    
@@ -90,7 +98,7 @@ BOOL find_name_in_lmhosts(struct nmb_nam
                                  FIND_ANY_NAME))==NULL)
     return False;
 
-  if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME))
+  if(!NAME_IS_ACTIVE(namerec) || (namerec->source != LMHOSTS_NAME))
     return False;
 
   *namerecp = namerec;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_mynames.c HEAD-nmbd/source/nmbd/nmbd_mynames.c
--- HEAD/source/nmbd/nmbd_mynames.c	Wed Nov 13 19:52:38 2002
+++ HEAD-nmbd/source/nmbd/nmbd_mynames.c	Wed Nov 13 20:23:00 2002
@@ -94,15 +94,25 @@ static void insert_refresh_name_into_uni
   if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
   {
     /* The name needs to be created on the unicast subnet. */
+    struct nmb_addr addr;
+    addr.ip = subrec->myip;
+    addr.owner = wins_fake_ip();
+    addr.ttl = PERMANENT_TTL;
+    
     (void)add_name_to_subnet( unicast_subnet, nmbname->name,
                               nmbname->name_type, nb_type,
-                              MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip);
+                              MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &addr);
   }
   else
   {
     /* The name already exists on the unicast subnet. Add our local
        IP for the given broadcast subnet to the name. */
-    add_ip_to_name_record( namerec, subrec->myip);
+    struct nmb_addr addr;
+    addr.ip = subrec->myip;
+    addr.owner = wins_fake_ip();
+    addr.ttl = PERMANENT_TTL;
+    
+    add_ip_to_name_record( namerec, addr);
   }
 }
 
@@ -190,7 +200,7 @@ void release_wins_names(void)
 	     namerec;
 	     namerec = nextnamerec) {
 		nextnamerec = (struct name_record *)ubi_trNext( namerec );
-		if( (namerec->data.source == SELF_NAME)
+		if( (namerec->source == SELF_NAME)
 		    && !NAME_IS_DEREGISTERING(namerec) )
 			release_name( subrec, namerec, standard_success_release,
 				      NULL, NULL);
@@ -210,9 +220,9 @@ void refresh_my_names(time_t t)
 	     namerec;
 	     namerec = (struct name_record *)ubi_trNext(namerec)) {
 		/* Each SELF name has an individual time to be refreshed. */
-		if ((namerec->data.source == SELF_NAME) &&
+		if ((namerec->source == SELF_NAME) &&
 		    (namerec->data.refresh_time < t) &&
-		    (namerec->data.death_time != PERMANENT_TTL)) {
+		    (namerec->data.ttl != PERMANENT_TTL)) {
 			/* We cheat here and pretend the refresh is going to be
 			   successful & update the refresh times. This stops
 			   multiple refresh calls being done. We actually
@@ -221,7 +231,7 @@ void refresh_my_names(time_t t)
 			if (!is_refresh_already_queued(unicast_subnet, namerec)) {
 				wins_refresh_name(namerec);
 			}
-			namerec->data.death_time = t + lp_max_ttl();
+			namerec->data.ttl = t + lp_max_ttl();
 			namerec->data.refresh_time = t + MIN(lp_max_ttl()/2, MAX_REFRESH_TIME);
 		}
 	}
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_namelistdb.c HEAD-nmbd/source/nmbd/nmbd_namelistdb.c
--- HEAD/source/nmbd/nmbd_namelistdb.c	Wed Nov 13 19:52:38 2002
+++ HEAD-nmbd/source/nmbd/nmbd_namelistdb.c	Fri Nov 15 12:23:11 2002
@@ -42,7 +42,7 @@ void set_samba_nb_type(void)
  * Convert a NetBIOS name to upper case.
  * ************************************************************************** **
  */
-static void upcase_name( struct nmb_name *target, struct nmb_name *source )
+void upcase_name( struct nmb_name *target, struct nmb_name *source )
   {
   int i;
 
@@ -73,11 +73,15 @@ static void update_name_in_namelist( str
   (void)ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec );
   if( oldrec )
     {
-    SAFE_FREE( oldrec->data.ip );
+    SAFE_FREE( oldrec->data.addrs );
     SAFE_FREE( oldrec );
     }
   } /* update_name_in_namelist */
 
+void add_record_to_subnet(struct subnet_record *subrec, struct name_record *namerec)
+{
+	update_name_in_namelist(subrec, namerec);	
+}
 /* ************************************************************************** **
  * Remove a name from the namelist.
  * ************************************************************************** **
@@ -87,7 +91,7 @@ void remove_name_from_namelist( struct s
   {
   (void)ubi_trRemove( subrec->namelist, namerec );
 
-  SAFE_FREE(namerec->data.ip);
+  SAFE_FREE(namerec->data.addrs);
 
   ZERO_STRUCTP(namerec);
   SAFE_FREE(namerec);
@@ -112,8 +116,8 @@ struct name_record *find_name_on_subnet(
     {
     /* Self names only - these include permanent names. */
     if( self_only
-     && (name_ret->data.source != SELF_NAME)
-     && (name_ret->data.source != PERMANENT_NAME) )
+     && (name_ret->source != SELF_NAME)
+     && (name_ret->source != PERMANENT_NAME) )
       {
       DEBUG( 9, 
              ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
@@ -121,7 +125,7 @@ struct name_record *find_name_on_subnet(
       return( NULL );
       }
     DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
-               subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) );
+               subrec->subnet_name, nmb_namestr(nmbname), name_ret->source) );
     return( name_ret );
     }
   DEBUG( 9, 
@@ -159,10 +163,16 @@ struct name_record *find_name_for_remote
 void update_name_ttl( struct name_record *namerec, int ttl )
 {
   time_t time_now = time(NULL);
+  int i;
 
-  if( namerec->data.death_time != PERMANENT_TTL )
-    namerec->data.death_time = time_now + ttl;
+  if( namerec->data.ttl != PERMANENT_TTL )
+    namerec->data.ttl = time_now + ttl;
 
+  for (i=0;i<namerec->data.num_addrs;i++) {
+  	if (ip_equal(namerec->data.addrs[i].owner,wins_fake_ip())) {
+		namerec->data.addrs[i].ttl = time_now + ttl;
+  	}	
+  }
   namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
 
   namerec->subnet->namelist_changed = True;
@@ -178,12 +188,12 @@ struct name_record *add_name_to_subnet( 
                                         uint16                nb_flags,
                                         int                   ttl,
                                         enum name_source      source,
-                                        int                   num_ips,
-                                        struct in_addr       *iplist)
+                                        int                   num_addrs,
+                                        struct nmb_addr       *addr_list)
 {
   struct name_record *namerec;
   time_t time_now = time(NULL);
-
+  
   namerec = (struct name_record *)malloc( sizeof(*namerec) );
   if( NULL == namerec )
   {
@@ -192,9 +202,9 @@ struct name_record *add_name_to_subnet( 
   }
 
   memset( (char *)namerec, '\0', sizeof(*namerec) );
-  namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) 
-                                               * num_ips );
-  if( NULL == namerec->data.ip )
+  namerec->data.addrs = (struct nmb_addr *)malloc( sizeof(struct nmb_addr) 
+                                               * num_addrs );
+  if( NULL == namerec->data.addrs )
   {
      DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
 
@@ -216,20 +226,19 @@ struct name_record *add_name_to_subnet( 
   if( strequal( my_netbios_names(0), name ) )
     namerec->data.nb_flags |= NB_PERM;
 
-  /* Copy the IPs. */
-  namerec->data.num_ips = num_ips;
-  memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) );
-
-  /* Data source. */
-  namerec->data.source = source;
-
   /* Setup the death_time and refresh_time. */
   if( ttl == PERMANENT_TTL )
-    namerec->data.death_time = PERMANENT_TTL;
+    namerec->data.ttl = PERMANENT_TTL;
   else
-    namerec->data.death_time = time_now + ttl;
+    namerec->data.ttl = time_now + ttl;
 
   namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
+  
+  /* Copy the IPs. */
+  namerec->data.num_addrs = num_addrs;
+  memcpy(namerec->data.addrs,addr_list,num_addrs * sizeof(struct nmb_addr));
+
+  namerec->source = source;
 
   /* Now add the record to the name list. */    
   update_name_in_namelist( subrec, namerec );
@@ -237,7 +246,7 @@ struct name_record *add_name_to_subnet( 
   DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
 ttl=%d nb_flags=%2x to subnet %s\n",
 	    nmb_namestr( &namerec->name ),
-            inet_ntoa( *iplist ),
+            inet_ntoa( addr_list[0].ip ),
             ttl,
             (unsigned int)nb_flags,
             subrec->subnet_name ) );
@@ -261,9 +270,14 @@ void standard_success_register(struct su
   struct name_record *namerec;
 
   namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
-  if( NULL == namerec )
+  if( NULL == namerec ){
+    struct nmb_addr addr;
+    addr.ip = registered_ip;
+    addr.owner = wins_fake_ip();
+    addr.ttl = ttl;
     (void)add_name_to_subnet( subrec, nmbname->name, nmbname->name_type,
-                              nb_flags, ttl, SELF_NAME, 1, &registered_ip );
+                              nb_flags, ttl, SELF_NAME, 1, &addr );
+  }
   else
     update_name_ttl( namerec, ttl );
 }
@@ -298,12 +312,12 @@ on subnet %s\n",
 
 static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
 {
-  if( ind != namerec->data.num_ips )
-    memmove( (char *)(&namerec->data.ip[ind]),
-             (char *)(&namerec->data.ip[ind+1]), 
-             ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) );
+  if((ind > -1) && (ind < namerec->data.num_addrs))
+    memmove( (char *)(&namerec->data.addrs[ind]),
+             (char *)(&namerec->data.addrs[ind+1]), 
+             ( namerec->data.num_addrs - ind - 1) * sizeof(struct nmb_addr) );
 
-  namerec->data.num_ips--;
+  namerec->data.num_addrs--;
   namerec->subnet->namelist_changed = True;
 }
 
@@ -315,8 +329,8 @@ BOOL find_ip_in_name_record( struct name
 {
   int i;
 
-  for(i = 0; i < namerec->data.num_ips; i++)
-    if(ip_equal( namerec->data.ip[i], ip))
+  for(i = 0; i < namerec->data.num_addrs; i++)
+    if(ip_equal( namerec->data.addrs[i].ip, ip))
       return True;
 
   return False;
@@ -326,16 +340,16 @@ BOOL find_ip_in_name_record( struct name
  Utility function to add an IP address to a name record.
  ******************************************************************/
 
-void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
+void add_ip_to_name_record( struct name_record *namerec, struct nmb_addr new_addr )
 {
-  struct in_addr *new_list;
+  struct nmb_addr *new_list;
 
   /* Don't add one we already have. */
-  if( find_ip_in_name_record( namerec, new_ip ) )
+  if( find_ip_in_name_record( namerec, new_addr.ip ) )
     return;
   
-  new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1)
-                                       * sizeof(struct in_addr) );
+  new_list = (struct nmb_addr *)malloc( (namerec->data.num_addrs + 1)
+                                       * sizeof(struct nmb_addr) );
   if( NULL == new_list )
   {
     DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
@@ -343,13 +357,13 @@ void add_ip_to_name_record( struct name_
   }
 
   memcpy( (char *)new_list,
-          (char *)namerec->data.ip,
-          namerec->data.num_ips * sizeof(struct in_addr) );
-  new_list[namerec->data.num_ips] = new_ip;
-
-  SAFE_FREE(namerec->data.ip);
-  namerec->data.ip = new_list;
-  namerec->data.num_ips += 1;
+          (char *)namerec->data.addrs,
+          namerec->data.num_addrs * sizeof(struct nmb_addr) );
+  new_list[namerec->data.num_addrs] = new_addr;
+
+  SAFE_FREE(namerec->data.addrs);
+  namerec->data.addrs = new_list;
+  namerec->data.num_addrs++;
 
   namerec->subnet->namelist_changed = True;
 }
@@ -363,10 +377,10 @@ void remove_ip_from_name_record( struct 
 {
   /* Try and find the requested ip address - remove it. */
   int i;
-  int orig_num = namerec->data.num_ips;
+  int orig_num = namerec->data.num_addrs;
 
   for(i = 0; i < orig_num; i++)
-    if( ip_equal( remove_ip, namerec->data.ip[i]) )
+    if( ip_equal( remove_ip, namerec->data.addrs[i].ip) )
     {
       remove_nth_ip_in_record( namerec, i);
       break;
@@ -399,11 +413,11 @@ on subnet %s. Name was not found on subn
   }
   else
   {
-    int orig_num = namerec->data.num_ips;
+    int orig_num = namerec->data.num_addrs;
 
     remove_ip_from_name_record( namerec, released_ip );
 
-    if( namerec->data.num_ips == orig_num )
+    if( namerec->data.num_addrs == orig_num )
       DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
 on subnet %s. This ip is not known for this name.\n",
                 nmb_namestr(nmbname),
@@ -411,7 +425,7 @@ on subnet %s. This ip is not known for t
                 subrec->subnet_name ) );
   }
 
-  if( namerec->data.num_ips == 0 )
+  if( namerec->data.num_addrs == 0 )
     remove_name_from_namelist( subrec, namerec );
 }
 
@@ -429,15 +443,15 @@ void expire_names_on_subnet(struct subne
        namerec = next_namerec )
   {
     next_namerec = (struct name_record *)ubi_trNext( namerec );
-    if( (namerec->data.death_time != PERMANENT_TTL)
-     && (namerec->data.death_time < t) )
+    if( (namerec->data.ttl != PERMANENT_TTL)
+     && (namerec->data.ttl < t) )
     {
-      if( namerec->data.source == SELF_NAME )
+      if( namerec->source == SELF_NAME )
       {
         DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
 name %s\n", 
                     subrec->subnet_name, nmb_namestr(&namerec->name) ) );
-        namerec->data.death_time += 300;
+        namerec->data.ttl += 300;
         namerec->subnet->namelist_changed = True;
         continue;
       }
@@ -475,9 +489,15 @@ void expire_names(time_t t)
 
 void add_samba_names_to_subnet( struct subnet_record *subrec )
 {
-  struct in_addr *iplist = &subrec->myip;
-  int num_ips = 1;
-
+  struct nmb_addr addr;
+  struct nmb_addr *addr_list = NULL;
+  int num_addrs = 1;
+
+  addr.ip = subrec->myip;
+  addr.owner = wins_fake_ip();
+  addr.ttl = PERMANENT_TTL;
+  
+  addr_list = &addr;
   /* These names are added permanently (ttl of zero) and will NOT be
      refreshed.  */
 
@@ -489,9 +509,9 @@ void add_samba_names_to_subnet( struct s
     int i;
     /* Create an IP list containing all our known subnets. */
 
-    num_ips = iface_count();
-    iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) );
-    if( NULL == iplist )
+    num_addrs = iface_count();
+    addr_list = (struct nmb_addr *)malloc( num_addrs * sizeof(struct nmb_addr) );
+    if( NULL == addr_list )
     {
       DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
       return;
@@ -499,22 +519,24 @@ void add_samba_names_to_subnet( struct s
 
     for( bcast_subrecs = FIRST_SUBNET, i = 0;
          bcast_subrecs; 
-         bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ )
-      iplist[i] = bcast_subrecs->myip;
-
+         bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) {
+         	addr_list[i].ip = bcast_subrecs->myip;
+		addr_list[i].owner = wins_fake_ip();
+		addr_list[i].ttl = PERMANENT_TTL;
+    }		
   }
 
   (void)add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
-                           PERMANENT_NAME, num_ips, iplist);
+                           PERMANENT_NAME, num_addrs, addr_list);
   (void)add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
-                           PERMANENT_NAME, num_ips, iplist);
+                           PERMANENT_NAME, num_addrs, addr_list);
   (void)add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
-                           PERMANENT_NAME, num_ips, iplist);
+                           PERMANENT_NAME, num_addrs, addr_list);
   (void)add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
-                           PERMANENT_NAME, num_ips, iplist);
+                           PERMANENT_NAME, num_addrs, addr_list);
 
-  if(iplist != &subrec->myip)
-    SAFE_FREE(iplist);
+  if(addr_list != &addr)
+    SAFE_FREE(addr_list);
 }
 
 /****************************************************************************
@@ -535,7 +557,7 @@ static void dump_subnet_namelist( struct
        namerec = (struct name_record *)ubi_trNext( namerec ) )
   {
     x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
-    switch(namerec->data.source)
+    switch(namerec->source)
     {
       case LMHOSTS_NAME:
         src_type = "LMHOSTS_NAME";
@@ -564,13 +586,13 @@ static void dump_subnet_namelist( struct
     }
     x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
 
-    if(namerec->data.death_time != PERMANENT_TTL)
+    if(namerec->data.ttl != PERMANENT_TTL)
     {
-      tm = LocalTime(&namerec->data.death_time);
-      x_fprintf(fp, "death_time = %s\t", asctime(tm));
+      tm = LocalTime(&namerec->data.ttl);
+      x_fprintf(fp, "ttl = %s\t", asctime(tm));
     }
     else
-      x_fprintf(fp, "death_time = PERMANENT\t");
+      x_fprintf(fp, "ttl = PERMANENT\t");
 
     if(namerec->data.refresh_time != PERMANENT_TTL)
     {
@@ -580,9 +602,9 @@ static void dump_subnet_namelist( struct
     else
       x_fprintf(fp, "refresh_time = PERMANENT\n");
 
-    x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
-    for(i = 0; i < namerec->data.num_ips; i++)
-      x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
+    x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_addrs);
+    for(i = 0; i < namerec->data.num_addrs; i++)
+      x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.addrs[i].ip));
 
     x_fprintf(fp, "\n\n");
   }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_namequery.c HEAD-nmbd/source/nmbd/nmbd_namequery.c
--- HEAD/source/nmbd/nmbd_namequery.c	Tue May 28 16:49:00 2002
+++ HEAD-nmbd/source/nmbd/nmbd_namequery.c	Thu Nov  7 12:50:15 2002
@@ -179,8 +179,8 @@ static BOOL query_local_namelists(struct
     return False;
 
   if( NAME_IS_ACTIVE(namerec)
-   && ( (namerec->data.source == SELF_NAME)
-     || (namerec->data.source == LMHOSTS_NAME) ) )
+   && ( (namerec->source == SELF_NAME)
+     || (namerec->source == LMHOSTS_NAME) ) )
   {
     *namerecp = namerec;
     return True;
@@ -220,27 +220,27 @@ BOOL query_name(struct subnet_record *su
     rrec.rr_type = RR_TYPE_NB;
     rrec.rr_class = RR_CLASS_IN;
     rrec.ttl = PERMANENT_TTL;
-    rrec.rdlength = namerec->data.num_ips * 6;
+    rrec.rdlength = namerec->data.num_addrs * 6;
     if(rrec.rdlength > MAX_DGRAM_SIZE)
     {
       if( DEBUGLVL( 0 ) )
         {
         dbgtext( "query_name: nmbd internal error - " );
-        dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
+        dbgtext( "there are %d ip addresses ", namerec->data.num_addrs );
         dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
         }
       return False;
     }
 
-    for( i = 0; i < namerec->data.num_ips; i++)
+    for( i = 0; i < namerec->data.num_addrs; i++)
     {
       set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
-      putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
+      putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.addrs[i].ip);
     }
 
     /* Call the success function directly. */
     if(success_fn)
-      (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
+      (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.addrs[0].ip, &rrec);
     return False;
   }
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_nameregister.c HEAD-nmbd/source/nmbd/nmbd_nameregister.c
--- HEAD/source/nmbd/nmbd_nameregister.c	Wed Nov 13 19:52:38 2002
+++ HEAD-nmbd/source/nmbd/nmbd_nameregister.c	Wed Nov 13 20:23:00 2002
@@ -411,16 +411,16 @@ static void multihomed_register_name(str
 	  only we will get away with this (only the WINS server
 	  will ever query names from us on this subnet).
 	*/
-	int num_ips=0;
+	int num_addrs=0;
 	int i, t;
 	struct subnet_record *subrec;
 	char **wins_tags;
-	struct in_addr *ip_list;
+	struct nmb_addr *addr_list;
 
 	for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
-		num_ips++;
+		num_addrs++;
 	
-	if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL) {
+	if((addr_list = (struct nmb_addr *)malloc(num_addrs * sizeof(struct nmb_addr)))==NULL) {
 		DEBUG(0,("multihomed_register_name: malloc fail !\n"));
 		return;
 	}
@@ -428,12 +428,14 @@ static void multihomed_register_name(str
 	for (subrec = FIRST_SUBNET, i = 0; 
 	     subrec;
 	     subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
-		ip_list[i] = subrec->myip;
+		addr_list[i].ip = subrec->myip;
+		addr_list[i].owner = wins_fake_ip();
+		addr_list[i].ttl = lp_max_ttl();		
 	}
-
-	add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
+		
+        add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
 			   nb_flags, lp_max_ttl(), SELF_NAME,
-			   num_ips, ip_list);
+			   num_addrs, addr_list);
 
 	/* get the list of wins tags - we try to register for each of them */
 	wins_tags = wins_srv_tags();
@@ -447,13 +449,13 @@ static void multihomed_register_name(str
 	for (t=0; wins_tags && wins_tags[t]; t++) {
 		multihomed_register_one(nmbname, nb_flags,
 					success_fn, fail_fn,
-					ip_list[0],
+					addr_list[0].ip,
 					wins_tags[t]);
 	}
 
 	wins_srv_tags_free(wins_tags);
 	
-	SAFE_FREE(ip_list);
+	SAFE_FREE(addr_list);
 }
 
 
@@ -515,7 +517,7 @@ void wins_refresh_name(struct name_recor
 				   register_name_response,
 				   register_name_timeout_response,
 				   namerec->data.nb_flags,
-				   namerec->data.ip[0], wins_tags[t]);
+				   namerec->data.addrs[0].ip, wins_tags[t]);
 	}
 
 	wins_srv_tags_free(wins_tags);
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_namerelease.c HEAD-nmbd/source/nmbd/nmbd_namerelease.c
--- HEAD/source/nmbd/nmbd_namerelease.c	Thu Jun 27 16:37:17 2002
+++ HEAD-nmbd/source/nmbd/nmbd_namerelease.c	Thu Nov  7 13:10:44 2002
@@ -148,22 +148,22 @@ static void wins_release_name(struct nam
 	wins_tags = wins_srv_tags();
 
 	for (t=0;wins_tags && wins_tags[t]; t++) {
-		for (i = 0; i < namerec->data.num_ips; i++) {
-			struct in_addr wins_ip = wins_srv_ip_tag(wins_tags[t], namerec->data.ip[i]);
+		for (i = 0; i < namerec->data.num_addrs; i++) {
+			struct in_addr wins_ip = wins_srv_ip_tag(wins_tags[t], namerec->data.addrs[i].ip);
 
-			BOOL last_one = ((i==namerec->data.num_ips - 1) && !wins_tags[t+1]);
+			BOOL last_one = ((i==namerec->data.num_addrs - 1) && !wins_tags[t+1]);
 			if (queue_release_name(unicast_subnet,
 					       release_name_response,
 					       release_name_timeout_response,
-					       last_one?success_fn : NULL,
+					       last_one? success_fn : NULL,
 					       last_one? fail_fn : NULL,
 					       last_one? userdata : NULL,
 					       &namerec->name,
 					       namerec->data.nb_flags,
-					       namerec->data.ip[i],
+					       namerec->data.addrs[i].ip,
 					       wins_ip) == NULL) {
 				DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
-					 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
+					 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.addrs[i].ip) ));
 			}
 		}
 	}
@@ -184,9 +184,9 @@ void release_name(struct subnet_record *
 	int i;
 
 	/* Ensure it's a SELF name, and in the ACTIVE state. */
-	if ((namerec->data.source != SELF_NAME) || !NAME_IS_ACTIVE(namerec)) {
+	if ((namerec->source != SELF_NAME) || !NAME_IS_ACTIVE(namerec)) {
 		DEBUG(0,("release_name: Cannot release name %s from subnet %s. Source was %d \n",
-			 nmb_namestr(&namerec->name), subrec->subnet_name, namerec->data.source)); 
+			 nmb_namestr(&namerec->name), subrec->subnet_name, namerec->source)); 
 		return;
 	}
 
@@ -204,19 +204,19 @@ void release_name(struct subnet_record *
 	 * Only call the success/fail function on the last one (it should
 	 * only be done once).
 	 */
-	for (i = 0; i < namerec->data.num_ips; i++) {
+	for (i = 0; i < namerec->data.num_addrs; i++) {
 		if (queue_release_name(subrec,
 				       release_name_response,
 				       release_name_timeout_response,
-				       (i == (namerec->data.num_ips - 1)) ? success_fn : NULL,
-				       (i == (namerec->data.num_ips - 1)) ? fail_fn : NULL,
-				       (i == (namerec->data.num_ips - 1)) ? userdata : NULL,
+				       (i == (namerec->data.num_addrs - 1)) ? success_fn : NULL,
+				       (i == (namerec->data.num_addrs - 1)) ? fail_fn : NULL,
+				       (i == (namerec->data.num_addrs - 1)) ? userdata : NULL,
 				       &namerec->name,
 				       namerec->data.nb_flags,
-				       namerec->data.ip[i],
+				       namerec->data.addrs[i].ip,
 				       subrec->bcast_ip) == NULL) {
 			DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
-				 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
+				 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.addrs[i].ip) ));
 		}
 	}
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_winsproxy.c HEAD-nmbd/source/nmbd/nmbd_winsproxy.c
--- HEAD/source/nmbd/nmbd_winsproxy.c	Wed Jan 30 07:08:22 2002
+++ HEAD-nmbd/source/nmbd/nmbd_winsproxy.c	Fri Nov  8 09:16:04 2002
@@ -34,10 +34,18 @@ static void wins_proxy_name_query_reques
   struct subnet_record *orig_broadcast_subnet;
   struct name_record *namerec;
   uint16 nb_flags;
-  int num_ips;
+  int num_addrs;
   int i;
   int ttl = 3600; /* By default one hour in the cache. */
-  struct in_addr *iplist;
+  struct nmb_addr addr;
+  struct nmb_addr *addr_list;
+
+  if(rrec->ttl == PERMANENT_TTL)
+    ttl = lp_max_ttl();
+    
+  addr.ip = ip;
+  addr.ttl = ttl;
+  addr.owner = wins_fake_ip();
 
   /* Extract the original packet and the original broadcast subnet from
      the userdata. */
@@ -48,39 +56,36 @@ static void wins_proxy_name_query_reques
 
   nb_flags = get_nb_flags( rrec->rdata );
 
-  num_ips = rrec->rdlength / 6;
-  if(num_ips == 0)
+  num_addrs = rrec->rdlength / 6;
+  if(num_addrs == 0)
   {
     DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
 returned for name %s.\n", nmb_namestr(nmbname) ));
     return;
   }
 
-  if(num_ips == 1)
-    iplist = &ip;
+  if(num_addrs == 1)
+    addr_list = &addr;
   else
   {
-    if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
+    if((addr_list = (struct nmb_addr *)malloc( num_addrs * sizeof(struct nmb_addr) )) == NULL)
     {
       DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n"));
       return;
     }
 
-    for(i = 0; i < num_ips; i++)
-      putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
+    for(i = 0; i < num_addrs; i++)
+      putip( (char *)&addr_list[i].ip, (char *)&rrec->rdata[ (i*6) + 2]);
   }
 
   /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
 
-  if(rrec == PERMANENT_TTL)
-    ttl = lp_max_ttl();
-
   namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name,
                                 nmbname->name_type, nb_flags, ttl,
-                                WINS_PROXY_NAME, num_ips, iplist );
+                                WINS_PROXY_NAME, num_addrs, addr_list );
 
-  if(iplist != &ip)
-    SAFE_FREE(iplist);
+  if(addr_list != &addr)
+    SAFE_FREE(addr_list);
 
   /*
    * Check that none of the IP addresses we are returning is on the
@@ -92,9 +97,9 @@ returned for name %s.\n", nmb_namestr(nm
 
   if(namerec && original_packet->packet.nmb.header.nm_flags.bcast)
   {
-    for( i = 0; i < namerec->data.num_ips; i++)
+    for( i = 0; i < namerec->data.num_addrs; i++)
     {
-      if( same_net( namerec->data.ip[i],
+      if( same_net( namerec->data.addrs[i].ip,
                     orig_broadcast_subnet->myip,
                     orig_broadcast_subnet->mask_ip ) )
       {
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/nmbd_winsserver.c HEAD-nmbd/source/nmbd/nmbd_winsserver.c
--- HEAD/source/nmbd/nmbd_winsserver.c	Mon Nov 18 06:44:22 2002
+++ HEAD-nmbd/source/nmbd/nmbd_winsserver.c	Mon Nov 18 06:56:19 2002
@@ -2,7 +2,8 @@
    Unix SMB/CIFS implementation.
    NBT netbios routines and daemon - version 2
 
-   Copyright (C) Jeremy Allison 1994-1998
+   Copyright (C) Jeremy Allison 		1994-1998
+   Copyright (C) Stefan (metze) Metzmacher	2002
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -22,9 +23,6 @@
 
 #include "includes.h"
 
-#define WINS_LIST "wins.tdb"
-#define WINS_VERSION 1
-
 /****************************************************************************
 change the wins owner address in the record.
 *****************************************************************************/
@@ -32,9 +30,57 @@ static void update_wins_owner(struct nam
 {
 	if (namerec==NULL)
 		return;
-	namerec->data.wins_ip=wins_ip;
+	namerec->data.owner=wins_ip;
+	
+	/*fix me: maybe change the addresses owner too here! --metze*/
+}
+
+struct in_addr wins_fake_ip(void)
+{
+	static struct in_addr wins_ip;
+	static BOOL init = False;
+	
+	if (!init) {
+		wins_ip = *interpret_addr2("0.0.0.0");
+		init = True;
+	}
+	return wins_ip;
 }
 
+void dump_nmb_record(struct name_record *namerec)
+{
+	int i;
+	
+	DEBUG(0,("Name: %-17s Owner: %15s ID: 0x%016X\n",
+			nmb_namestr(&namerec->name),inet_ntoa(namerec->data.owner),namerec->data.id));
+	DEBUGADD(0,("SOURCE: =0x%02X WINS_Flags: 0x%02X NB_FALGS: 0x%02X\n",
+			namerec->source,namerec->data.wins_flags,namerec->data.nb_flags));
+	{
+		char *ts, *nl;
+		struct tm *tm;
+		tm = LocalTime(&namerec->data.ttl);
+		ts = asctime(tm);
+		nl = strrchr_m( ts, '\n' );
+		if( NULL != nl )
+			*nl = '\0';
+		DEBUGADD(0,("TTL = %s\n", ts ));
+	}
+	for (i = 0; i < namerec->data.num_addrs; i++) {
+
+		DEBUGADD(0,("IP: %15s ",inet_ntoa(namerec->data.addrs[i].ip)));
+		DEBUGADD(0,("OWNER: %15s ",inet_ntoa(namerec->data.addrs[i].owner)));
+		{
+			char *ts, *nl;
+			struct tm *tm;
+			tm = LocalTime(&namerec->data.addrs[i].ttl);
+			ts = asctime(tm);
+			nl = strrchr_m( ts, '\n' );
+			if( NULL != nl )
+				*nl = '\0';
+				DEBUGADD(0,("TTL = %s\n", ts ));
+		}
+	}	
+}
 /****************************************************************************
 create the wins flags based on the nb flags and the input value.
 *****************************************************************************/
@@ -50,13 +96,13 @@ static void update_wins_flag(struct name
 		if (namerec->name.name_type==0x1C)
 			namerec->data.wins_flags|=WINS_SGROUP;
 		else
-			if (namerec->data.num_ips>1)
+			if (namerec->data.num_addrs>1)
 				namerec->data.wins_flags|=WINS_SGROUP;
 			else
 				namerec->data.wins_flags|=WINS_NGROUP;
 	} else {
 		/* can be unique or multi-homed */
-		if (namerec->data.num_ips>1)
+		if (namerec->data.num_addrs>1)
 			namerec->data.wins_flags|=WINS_MHOMED;
 		else
 			namerec->data.wins_flags|=WINS_UNIQUE;
@@ -66,14 +112,14 @@ static void update_wins_flag(struct name
 	namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
 
 	/* the static bit is elsewhere */
-	if (namerec->data.death_time == PERMANENT_TTL)
+	if (namerec->data.ttl == PERMANENT_TTL)
 		namerec->data.wins_flags|=WINS_STATIC;
 
 	/* and add the given bits */
 	namerec->data.wins_flags|=flags;
 
 	DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", 
-		 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
+		 namerec->data.nb_flags, (int)namerec->data.ttl, flags, namerec->data.wins_flags));
 
 }
 
@@ -87,8 +133,14 @@ static void get_global_id_and_update(SMB
 	 * with the value directly
 	 */
 
-	static SMB_BIG_UINT general_id = 1;
+	static SMB_BIG_UINT general_id = 0;
+	static BOOL init = False;
 
+	if (!init) {
+		if (NT_STATUS_IS_ERR(winsdb_get_global_id(NULL,&general_id)))
+			general_id =1;
+		init = True;
+	}
 	DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
 	
 	*current_id = general_id;
@@ -124,8 +176,8 @@ static void wins_hook(char *operation, s
 		      namerec->name.name_type,
 		      ttl);
 
-	for (i=0;i<namerec->data.num_ips;i++) {
-		p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
+	for (i=0;i<namerec->data.num_addrs;i++) {
+		p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.addrs[i].ip));
 	}
 
 	DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
@@ -222,10 +274,9 @@ Load or create the WINS database.
 BOOL initialise_wins(void)
 {
 	time_t time_now = time(NULL);
-	TDB_CONTEXT *tdb;
-	TDB_DATA kbuf, dbuf, newkey;
 	struct name_record *namerec = NULL;
-	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
+	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	SMB_BIG_UINT tmp_id;
 
 	DEBUG(2,("initialise_wins: started\n"));
 
@@ -234,100 +285,36 @@ BOOL initialise_wins(void)
 
 	add_samba_names_to_subnet(wins_server_subnet);
 
-	tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
-	if (!tdb) {
-		DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
-		return True;
-	}
-
-	if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) {
-		DEBUG(0,("Discarding invalid wins.dat file\n"));
-		tdb_close(tdb);
-		return True;
-	}
+	winsdb_open(NULL,False);
 
-	for (kbuf = tdb_firstkey(tdb); 
-	     kbuf.dptr; 
-	     newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
-
-		pstring name_type, name, ip_str;
-		char *p;
-		int type = 0;
-		int nb_flags;
-		int ttl;
-		unsigned int num_ips;
-		int high, low;
-		struct in_addr wins_ip;
-		struct in_addr *ip_list;
-		int wins_flags;
-		int len,i;
-
-		if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
-			continue;
-				
-		dbuf = tdb_fetch(tdb, kbuf);
-		if (!dbuf.dptr) continue;
-
-		fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
-
- 		pstrcpy(name, name_type);
-
-		if((p = strchr(name,'#')) != NULL) {
-			*p = 0;
-			sscanf(p+1,"%x",&type);
-		}
-
-		len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
-				&nb_flags, &high, &low,
-				ip_str, &ttl, &num_ips, &wins_flags);
-
-		wins_ip=*interpret_addr2(ip_str);
-
-		/* Don't reload replica records */
-		if (!ip_equal(wins_ip, our_fake_ip))
-			continue;
+	get_global_id_and_update(&tmp_id,False);
+	
+	while (NT_STATUS_IS_OK(nt_status = winsdb_get_next_record(NULL,&namerec))) {
 
-		/* Don't reload released or tombstoned records */
-		if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE)
+		if (!namerec) {
 			continue;
-
- 		/* Allocate the space for the ip_list. */
-		if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
-			DEBUG(0,("initialise_wins: Malloc fail !\n"));
-			return False;
 		}
-
-		for (i = 0; i < num_ips; i++) {
-			len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
-			ip_list[i] = *interpret_addr2(ip_str);
-		}
-
+	
 		/* add all entries that have 60 seconds or more to live */
-		if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
-			if(ttl != PERMANENT_TTL)
-				ttl -= time_now;
-    
-			DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
-			    	   name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
+		if ((namerec->data.ttl - 60) > time_now || namerec->data.ttl == PERMANENT_TTL) {
+			if(namerec->data.ttl != PERMANENT_TTL)
+				namerec->data.ttl -= time_now;
+    			/* todo: also for each address owned by us --metze*/
 
-			namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags, 
-					  	ttl, REGISTER_NAME, num_ips, ip_list);
-			if (namerec!=NULL) {
-				update_wins_owner(namerec, wins_ip);
-				update_wins_flag(namerec, wins_flags);
-				/* we don't reload the ID, on startup we restart at 1 */
-				get_global_id_and_update(&namerec->data.id, True);
-			}
+			add_record_to_subnet( wins_server_subnet, namerec);
+			dump_nmb_record(namerec);
 
 		} else {
 			DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
-				  name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
+				  namerec->name.name, 
+				  namerec->name.name_type, 
+				  namerec->data.ttl, 
+				  inet_ntoa(namerec->data.addrs[0].ip), 
+				  namerec->data.nb_flags));
 		}
-
-		SAFE_FREE(ip_list);
 	}
-    
-	tdb_close(tdb);
+
+	winsdb_close(NULL);
 	DEBUG(2,("initialise_wins: done\n"));
 	return True;
 }
@@ -399,7 +386,6 @@ void wins_process_name_refresh_request(s
   struct name_record *namerec = NULL;
   int ttl = get_ttl_from_packet(nmb);
   struct in_addr from_ip;
-  struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
 
   putip((char *)&from_ip,&nmb->additional->rdata[2]);
 
@@ -486,8 +472,9 @@ does not match group bit in WINS for thi
      * if the record is a replica:
      * we take ownership and update the version ID.
      */
-    if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
-    	update_wins_owner(namerec, our_fake_ip);
+     /* this need fixing --metze*/
+    if (!ip_equal(namerec->data.owner, wins_fake_ip())) {
+    	update_wins_owner(namerec, wins_fake_ip());
 	get_global_id_and_update(&namerec->data.id, True);
     }
 
@@ -589,8 +576,9 @@ static void wins_register_query_fail(str
   namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
 
   if( (namerec != NULL)
-   && (namerec->data.source == REGISTER_NAME)
-   && ip_equal(rrec->packet->ip, *namerec->data.ip) )
+   && (namerec->source == REGISTER_NAME)
+   && ip_equal(rrec->packet->ip, namerec->data.addrs[0].ip) )
+   /* shouldn't we check all addrs here??? --metze*/
   {
     remove_name_from_namelist( subrec, namerec);
     namerec = NULL;
@@ -674,7 +662,6 @@ void wins_process_name_registration_requ
   struct name_record *namerec = NULL;
   struct in_addr from_ip;
   BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
-  struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
 
   putip((char *)&from_ip,&nmb->additional->rdata[2]);
 
@@ -720,8 +707,8 @@ not active - removing it.\n", nmb_namest
    */
 
   if( (namerec != NULL)
-   && ( (namerec->data.source == DNS_NAME)
-     || (namerec->data.source == DNSFAIL_NAME) ) )
+   && ( (namerec->source == DNS_NAME)
+     || (namerec->source == DNSFAIL_NAME) ) )
   {
     DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
 a dns lookup - removing it.\n", nmb_namestr(question) ));
@@ -734,11 +721,11 @@ a dns lookup - removing it.\n", nmb_name
    * (ie. Don't allow any static names to be overwritten.
    */
 
-  if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
+  if((namerec != NULL) && (namerec->source != REGISTER_NAME))
   {
     DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
 to register name %s. Name already exists in WINS with source type %d.\n",
-                nmb_namestr(question), namerec->data.source ));
+                nmb_namestr(question), namerec->source ));
     send_wins_name_registration_response(RFS_ERR, 0, p);
     return;
   }
@@ -789,7 +776,12 @@ to register name %s from IP %s.\n", nmb_
        * Check the ip address is not already in the group.
        */
       if(!find_ip_in_name_record(namerec, from_ip)) {
-        add_ip_to_name_record(namerec, from_ip);
+      	struct nmb_addr addr;
+	addr.ip = from_ip;
+	addr.owner = wins_fake_ip();
+	addr.ttl = ttl;
+	
+        add_ip_to_name_record(namerec, addr);
 	/* we need to update the record for replication */
         get_global_id_and_update(&namerec->data.id, True);
 
@@ -801,7 +793,7 @@ to register name %s from IP %s.\n", nmb_
 	 * it will update its own record.
 	 */
 
-	update_wins_owner(namerec, our_fake_ip);
+	update_wins_owner(namerec, wins_fake_ip());
 
       }
       update_name_ttl(namerec, ttl);
@@ -867,9 +859,10 @@ is one of our (WINS server) names. Denyi
 
   if( !registering_group_name
    && (namerec != NULL)
-   && (namerec->data.num_ips == 1)
-   && ip_equal( namerec->data.ip[0], from_ip )
-   && ip_equal(namerec->data.wins_ip, our_fake_ip) )
+   && (namerec->data.num_addrs == 1)
+   && ip_equal( namerec->data.addrs[0].ip, from_ip )
+   && ip_equal(namerec->data.owner, wins_fake_ip()))
+   /* shouldn't we check each addr here??? --metze*/
   {
     update_name_ttl( namerec, ttl );
     send_wins_name_registration_response( 0, ttl, p );
@@ -916,7 +909,8 @@ is one of our (WINS server) names. Denyi
      * code. JRA.
      */
 
-    query_name_from_wins_server( *namerec->data.ip,
+    query_name_from_wins_server( namerec->data.addrs[0].ip,
+    		/* shouldn't we ... --metze */
                                   question->name,
                                   question->name_type, 
                                   wins_register_query_success,
@@ -928,12 +922,17 @@ is one of our (WINS server) names. Denyi
   /*
    * Name did not exist - add it.
    */
-
-  (void)add_name_to_subnet( subrec, question->name, question->name_type,
-                            nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
+  {
+	struct nmb_addr addr;
+	addr.ip = from_ip;
+	addr.owner = wins_fake_ip();
+	addr.ttl = ttl;
+	(void)add_name_to_subnet( subrec, question->name, question->name_type,
+                            nb_flags, ttl, REGISTER_NAME, 1, &addr);
+  }
   if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
 	get_global_id_and_update(&namerec->data.id, True);
-	update_wins_owner(namerec, our_fake_ip);
+	update_wins_owner(namerec, wins_fake_ip());
 	update_wins_flag(namerec, WINS_ACTIVE);
 	wins_hook("add", namerec, ttl);
   }
@@ -960,7 +959,6 @@ static void wins_multihomed_register_que
   struct name_record *namerec = NULL;
   struct in_addr from_ip;
   int ttl;
-  struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
 
   memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
 
@@ -980,7 +978,7 @@ static void wins_multihomed_register_que
 
   namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
 
-  if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
+  if( (namerec == NULL) || (namerec->source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
   {
     DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
 a subsequent IP address.\n", nmb_namestr(question_name) ));
@@ -992,11 +990,16 @@ a subsequent IP address.\n", nmb_namestr
     return;
   }
 
-  if(!find_ip_in_name_record(namerec, from_ip))
-    add_ip_to_name_record(namerec, from_ip);
-
+  if(!find_ip_in_name_record(namerec, from_ip)) {
+    struct nmb_addr addr;
+    addr.ip = from_ip;
+    addr.owner = wins_fake_ip();
+    addr.ttl = ttl;
+    
+    add_ip_to_name_record(namerec, addr);
+  }
   get_global_id_and_update(&namerec->data.id, True);
-  update_wins_owner(namerec, our_fake_ip);
+  update_wins_owner(namerec, wins_fake_ip());
   update_wins_flag(namerec, WINS_ACTIVE);
   update_name_ttl(namerec, ttl);
   send_wins_name_registration_response(0, ttl, orig_reg_packet);
@@ -1049,7 +1052,6 @@ void wins_process_multihomed_name_regist
   struct name_record *namerec = NULL;
   struct in_addr from_ip;
   BOOL group = (nb_flags & NB_GROUP) ? True : False;
-  struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
 
   putip((char *)&from_ip,&nmb->additional->rdata[2]);
 
@@ -1117,8 +1119,8 @@ to register name %s from IP %s.", nmb_na
    */
 
   if( (namerec != NULL)
-   && ( (namerec->data.source == DNS_NAME)
-     || (namerec->data.source == DNSFAIL_NAME) ) )
+   && ( (namerec->source == DNS_NAME)
+     || (namerec->source == DNSFAIL_NAME) ) )
   {
     DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
 - removing it.\n", nmb_namestr(question) ));
@@ -1131,11 +1133,11 @@ to register name %s from IP %s.", nmb_na
    * (ie. Don't allow any static names to be overwritten.
    */
 
-  if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
+  if( (namerec != NULL) && (namerec->source != REGISTER_NAME) )
   {
     DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
 to register name %s. Name already exists in WINS with source type %d.\n",
-    nmb_namestr(question), namerec->data.source ));
+    nmb_namestr(question), namerec->source ));
     send_wins_name_registration_response(RFS_ERR, 0, p);
     return;
   }
@@ -1179,11 +1181,16 @@ is one of our (WINS server) names. Denyi
        *  update the ttl. Update the version ID to force replication.
        */
 	    if(!find_ip_in_name_record(namerec, from_ip)) {
+	    	    struct nmb_addr addr;
+                    addr.ip = from_ip;
+                    addr.owner = wins_fake_ip();
+                    addr.ttl = ttl;
+                    
+		    add_ip_to_name_record(namerec, addr);
+		    
 		    get_global_id_and_update(&namerec->data.id, True);
-		    update_wins_owner(namerec, our_fake_ip);
+		    update_wins_owner(namerec, wins_fake_ip());
 		    update_wins_flag(namerec, WINS_ACTIVE);
-
-		    add_ip_to_name_record(namerec, from_ip);
 		    wins_hook("add", namerec, ttl);
 	    } else {
 		    wins_hook("refresh", namerec, ttl);
@@ -1207,9 +1214,10 @@ is one of our (WINS server) names. Denyi
      * If it's a replica, we need to become the wins owner
      * to force the replication
      */
-    if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
+    if (!ip_equal(namerec->data.owner, wins_fake_ip())) {
+    	/* shouldn't we check each addr here??? --metze*/
       get_global_id_and_update(&namerec->data.id, True);
-      update_wins_owner(namerec, our_fake_ip);
+      update_wins_owner(namerec, wins_fake_ip());
       update_wins_flag(namerec, WINS_ACTIVE);
     }
     
@@ -1260,7 +1268,8 @@ is one of our (WINS server) names. Denyi
      * not the person who sent the packet 
      */
 
-    query_name_from_wins_server( namerec->data.ip[0],
+    query_name_from_wins_server( namerec->data.addrs[0].ip, 
+    		/* shouldn't we check each addr here??? --metze */
                                  question->name,
                                  question->name_type, 
                                  wins_multihomed_register_query_success,
@@ -1273,13 +1282,19 @@ is one of our (WINS server) names. Denyi
   /*
    * Name did not exist - add it.
    */
-
-  (void)add_name_to_subnet( subrec, question->name, question->name_type,
-                            nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
+  {
+      struct nmb_addr addr;
+      addr.ip = from_ip;
+      addr.owner = wins_fake_ip();
+      addr.ttl = ttl;
+      DEBUG(0,("NAME: %-19s IP: %s\n",question->name,inet_ntoa(addr.ip)));
+     (void)add_name_to_subnet( subrec, question->name, question->name_type,
+                            nb_flags, ttl, REGISTER_NAME, 1, &addr);
+  }
 
   if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
 	  get_global_id_and_update(&namerec->data.id, True);
-	  update_wins_owner(namerec, our_fake_ip);
+	  update_wins_owner(namerec, wins_fake_ip());
 	  update_wins_flag(namerec, WINS_ACTIVE);
 	  wins_hook("add", namerec, ttl);
   }
@@ -1296,7 +1311,7 @@ static void process_wins_dmb_query_reque
 {  
   struct name_record *namerec = NULL;
   char *prdata;
-  int num_ips;
+  int num_addrs;
 
   /*
    * Go through all the ACTIVE names in the WINS db looking for those
@@ -1304,16 +1319,16 @@ static void process_wins_dmb_query_reque
    * addresses we need to return.
    */
 
-  num_ips = 0;
+  num_addrs = 0;
   for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
        namerec;
        namerec = (struct name_record *)ubi_trNext( namerec ) )
   {
     if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
-      num_ips += namerec->data.num_ips;
+      num_addrs += namerec->data.num_addrs;
   }
 
-  if(num_ips == 0)
+  if(num_addrs == 0)
   {
     /*
      * There are no 0x1b names registered. Return name query fail.
@@ -1322,7 +1337,7 @@ static void process_wins_dmb_query_reque
     return;
   }
 
-  if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
+  if((prdata = (char *)malloc( num_addrs * 6 )) == NULL)
   {
     DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
     return;
@@ -1334,7 +1349,7 @@ static void process_wins_dmb_query_reque
    * return.
    */ 
 
-  num_ips = 0;
+  num_addrs = 0;
   for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
        namerec;
        namerec = (struct name_record *)ubi_trNext( namerec ) )
@@ -1342,11 +1357,11 @@ static void process_wins_dmb_query_reque
     if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
     {
       int i;
-      for(i = 0; i < namerec->data.num_ips; i++)
+      for(i = 0; i < namerec->data.num_addrs; i++)
       {
-        set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
-        putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
-        num_ips++;
+        set_nb_flags(&prdata[num_addrs * 6],namerec->data.nb_flags);
+        putip((char *)&prdata[(num_addrs * 6) + 2], &namerec->data.addrs[i].ip);
+        num_addrs++;
       }
     }
   }
@@ -1361,7 +1376,7 @@ static void process_wins_dmb_query_reque
                        NMB_NAME_QUERY_OPCODE,         /* opcode. */
                        lp_min_wins_ttl(),             /* ttl. */
                        prdata,                        /* data to send. */
-                       num_ips*6);                    /* data length. */
+                       num_addrs*6);                    /* data length. */
 
   SAFE_FREE(prdata);
 }
@@ -1383,33 +1398,34 @@ void send_wins_name_query_response(int r
 
   if(rcode == 0)
   {
-    ttl = (namerec->data.death_time != PERMANENT_TTL) ?
-             namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
+    ttl = (namerec->data.ttl != PERMANENT_TTL) ?
+             namerec->data.ttl - p->timestamp : lp_max_wins_ttl();
 
     /* Copy all known ip addresses into the return data. */
     /* Optimise for the common case of one IP address so
        we don't need a malloc. */
 
-    if( namerec->data.num_ips == 1 )
+    if( namerec->data.num_addrs == 1 )
       prdata = rdata;
     else
     {
-      if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
+      if((prdata = (char *)malloc( namerec->data.num_addrs * 6 )) == NULL)
       {
         DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
         return;
       }
     }
 
-    for(i = 0; i < namerec->data.num_ips; i++)
+    for(i = 0; i < namerec->data.num_addrs; i++)
     {
+      /* fix me: send only active addresse --metze */
       set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
-      putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
+      putip((char *)&prdata[2+(i*6)], &namerec->data.addrs[i].ip);
     }
 
     sort_query_replies(prdata, i, p->ip);
 
-    reply_data_len = namerec->data.num_ips * 6;
+    reply_data_len = namerec->data.num_addrs * 6;
   }
 
   reply_netbios_packet(p,                             /* Packet to reply to. */
@@ -1470,7 +1486,7 @@ void wins_process_name_query_request(str
      * If it's a DNSFAIL_NAME then reply name not found.
      */
 
-    if( namerec->data.source == DNSFAIL_NAME )
+    if( namerec->source == DNSFAIL_NAME )
     {
       DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
              nmb_namestr(question) ));
@@ -1482,8 +1498,8 @@ void wins_process_name_query_request(str
      * If the name has expired then reply name not found.
      */
 
-    if( (namerec->data.death_time != PERMANENT_TTL)
-     && (namerec->data.death_time < p->timestamp) )
+    if( (namerec->data.ttl != PERMANENT_TTL)
+     && (namerec->data.ttl < p->timestamp) )
     {
       DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
                 nmb_namestr(question) ));
@@ -1492,7 +1508,7 @@ void wins_process_name_query_request(str
     }
 
     DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
-           nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
+           nmb_namestr(question), inet_ntoa(namerec->data.addrs[0].ip) ));
 
     send_wins_name_query_response(0, p, namerec);
     return;
@@ -1593,7 +1609,7 @@ to release name %s from IP %s.", nmb_nam
   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
 
   if( (namerec == NULL)
-   || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
+   || ((namerec != NULL) && (namerec->source != REGISTER_NAME)) )
   {
     send_wins_name_release_response(NAM_ERR, p);
     return;
@@ -1636,33 +1652,34 @@ release name %s as this record is not an
     send_wins_name_release_response(NAM_ERR, p);
     return;
   }    
-
-  /*
-   * Check if the record is a 0x1c group
-   * and has more then one ip
-   * remove only this address.
+  
+  /* check if the record is a 0x1c group 
+   * and has more then one ip's
+   * remove only this address
+   *
+   * fix me: handle the owner of the ip --metze
    */
-
-  if(releasing_group_name &&
-		(question->name_type == 0x1c) &&
-		(namerec->data.num_ips > 1)) {
-	remove_ip_from_name_record(namerec, from_ip);
-	DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
-			inet_ntoa(from_ip),nmb_namestr(question)));
-	send_wins_name_release_response(0, p);
-	return;
+  if(releasing_group_name && 
+  	(question->name_type == 0x1c) && 
+  	(namerec->data.num_addrs > 1))
+  {
+    remove_ip_from_name_record(namerec, from_ip);
+    DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
+           inet_ntoa(from_ip),nmb_namestr(question)));
+    send_wins_name_release_response(0, p);
+    return;
   }
-
+  
   /* 
-   * Send a release response.
-   * Flag the name as released and update the ttl
-   */
+  * Send a release response.
+  * Flag the name as released and update the ttl
+  */
 
   send_wins_name_release_response(0, p);
-  
+
   namerec->data.wins_flags |= WINS_RELEASED;
   update_name_ttl(namerec, EXTINCTION_INTERVAL);
-
+  
   wins_hook("delete", namerec, 0);
 }
 
@@ -1675,7 +1692,6 @@ void initiate_wins_processing(time_t t)
 	static time_t lasttime = 0;
 	struct name_record *namerec;
 	struct name_record *next_namerec;
-	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
 
 	if (!lasttime)
 		lasttime = t;
@@ -1692,30 +1708,31 @@ void initiate_wins_processing(time_t t)
 	     namerec = next_namerec ) {
 		next_namerec = (struct name_record *)ubi_trNext( namerec );
 
-		if( (namerec->data.death_time != PERMANENT_TTL)
-		     && (namerec->data.death_time < t) ) {
+		if( (namerec->data.ttl != PERMANENT_TTL)
+		     && (namerec->data.ttl < t) ) {
 
-			if( namerec->data.source == SELF_NAME ) {
+			if( namerec->source == SELF_NAME ) {
 				DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n", 
 				           wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
-				namerec->data.death_time += 300;
+				namerec->data.ttl += 300;
 				namerec->subnet->namelist_changed = True;
 				continue;
 			}
 
 			/* handle records, samba is the wins owner */
-			if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
+			if (ip_equal(namerec->data.owner, wins_fake_ip())) {
+				/* shouldn't we check each addr here??? --metze */
 				switch (namerec->data.wins_flags | WINS_STATE_MASK) {
 					case WINS_ACTIVE:
 						namerec->data.wins_flags&=~WINS_STATE_MASK;
 						namerec->data.wins_flags|=WINS_RELEASED;
-						namerec->data.death_time = t + EXTINCTION_INTERVAL;
+						namerec->data.ttl = t + EXTINCTION_INTERVAL;
 						DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
 						break;
 					case WINS_RELEASED:
 						namerec->data.wins_flags&=~WINS_STATE_MASK;
 						namerec->data.wins_flags|=WINS_TOMBSTONED;
-						namerec->data.death_time = t + EXTINCTION_TIMEOUT;
+						namerec->data.ttl = t + EXTINCTION_TIMEOUT;
 						get_global_id_and_update(&namerec->data.id, True);
 						DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
 						break;
@@ -1730,7 +1747,7 @@ void initiate_wins_processing(time_t t)
 						/* that's not as MS says it should be */
 						namerec->data.wins_flags&=~WINS_STATE_MASK;
 						namerec->data.wins_flags|=WINS_TOMBSTONED;
-						namerec->data.death_time = t + EXTINCTION_TIMEOUT;
+						namerec->data.ttl = t + EXTINCTION_TIMEOUT;
 						DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
 					case WINS_TOMBSTONED:
 						DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
@@ -1758,12 +1775,6 @@ we are not the wins owner !\n", nmb_name
 void wins_write_database(BOOL background)
 {
 	struct name_record *namerec;
-	pstring fname, fnamenew;
-	TDB_CONTEXT *tdb;
-	TDB_DATA kbuf, dbuf;
-	pstring key, buf;
-	int len;
-	int num_record=0;
 	SMB_BIG_UINT id;
 
 	if(!lp_we_are_a_wins_server())
@@ -1778,35 +1789,20 @@ void wins_write_database(BOOL background
 		}
 	}
 
-	slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
-	all_string_sub(fname,"//", "/", 0);
-	slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
-
-	tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
-	if (!tdb) {
-		DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
-		if (background)
-			_exit(0);
-		return;
-	}
-
-	DEBUG(3,("wins_write_database: Dump of WINS name list.\n"));
-
-	tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION);
+	winsdb_open(NULL,True);
 
 	for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
-	     namerec;
-	     namerec = (struct name_record *)ubi_trNext( namerec ) ) {
+		namerec;
+		namerec = (struct name_record *)ubi_trNext( namerec ) ) {
 
-		int i;
 		struct tm *tm;
 
-		DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) ));
-
-		if( namerec->data.death_time != PERMANENT_TTL ) {
+		DEBUG(3,("%-19s ", nmb_namestr(&namerec->name) ));
+		
+		if( namerec->data.ttl != PERMANENT_TTL ) {
 			char *ts, *nl;
 
-			tm = LocalTime(&namerec->data.death_time);
+			tm = LocalTime(&namerec->data.ttl);
 			ts = asctime(tm);
 			nl = strrchr_m( ts, '\n' );
 			if( NULL != nl )
@@ -1816,51 +1812,17 @@ void wins_write_database(BOOL background
 		} else
 			DEBUGADD(3,("TTL = PERMANENT                 "));
 
-		for (i = 0; i < namerec->data.num_ips; i++)
-			DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
-
-		DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip)));
-
-		if( namerec->data.source == REGISTER_NAME ) {
-		
-			/* store the type in the key to make the name unique */
-			slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
-
-			len = tdb_pack(buf, sizeof(buf), "dddfddd",
-					(int)namerec->data.nb_flags,
-					(int)(namerec->data.id>>32),
-					(int)(namerec->data.id&0xffffffff),
-					inet_ntoa(namerec->data.wins_ip),
-					(int)namerec->data.death_time, 
-					namerec->data.num_ips,
-					namerec->data.wins_flags);
-
-			for (i = 0; i < namerec->data.num_ips; i++)
-				len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i]));
-			
-			kbuf.dsize = strlen(key)+1;
-			kbuf.dptr = key;
-			dbuf.dsize = len;
-			dbuf.dptr = buf;
-			if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return;
-
-			num_record++;
+		if( namerec->source == REGISTER_NAME ) {
+			if (NT_STATUS_IS_ERR(winsdb_store_record(NULL,namerec))) 
+				return;
 		}
 	}
 
-	/* store the number of records */
-	tdb_store_int32(tdb, INFO_COUNT, num_record);
-
 	/* get and store the last used ID */
 	get_global_id_and_update(&id, False);
-	tdb_store_int32(tdb, INFO_ID_HIGH, id>>32);
-	tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff);
-
-	tdb_close(tdb);
+	winsdb_store_global_id(NULL,id);
 
-	chmod(fnamenew,0644);
-	unlink(fname);
-	rename(fnamenew,fname);
+	winsdb_close(NULL);
 
 	if (background)
 		_exit(0);
@@ -1876,7 +1838,6 @@ void nmbd_wins_new_entry(int msg_type, p
 	struct name_record *new_namerec = NULL;
 	struct nmb_name question;
 	BOOL overwrite=False;
-	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
 	int i;
 
 	if (buf==NULL)
@@ -1892,13 +1853,31 @@ void nmbd_wins_new_entry(int msg_type, p
 
 	/* record doesn't exist, add it */
 	if (namerec == NULL) {
+		struct nmb_addr *addr_list = NULL;
+		
+
+		addr_list = (struct nmb_addr *)malloc(record->num_ips * sizeof(struct nmb_addr));
+		
+		if (addr_list == NULL) {
+			DEBUG(0,("nmbd_wins_new_entry: malloc failed!\n"));
+			return;
+		}
+		for(i=0;i<record->num_ips;i++) {
+			addr_list[i].ip = record->ips[i];
+			addr_list[i].owner = record->owner;
+			addr_list[i].ttl = EXTINCTION_INTERVAL;
+		}
+
 		DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", 
-			  record->name, record->type, inet_ntoa(record->wins_ip)));
+			  record->name, record->type, inet_ntoa(record->owner)));
 
 		new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 
-						EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
+						EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, addr_list);
+
+		SAFE_FREE(addr_list);
+
 		if (new_namerec!=NULL) {
-				update_wins_owner(new_namerec, record->wins_ip);
+				update_wins_owner(new_namerec, record->owner);
 				update_wins_flag(new_namerec, record->wins_flags);
 				new_namerec->data.id=record->id;
 
@@ -1912,16 +1891,16 @@ void nmbd_wins_new_entry(int msg_type, p
 		if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
 
 			/* the database record is a replica */
-			if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
+			if (!ip_equal(namerec->data.owner, wins_fake_ip())) {
 				if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
-					if (ip_equal(namerec->data.wins_ip, record->wins_ip))
+					if (ip_equal(namerec->data.owner, record->owner))
 						overwrite=True;
 				} else
 					overwrite=True;
 			} else {
 			/* we are the wins owner of the database record */
 				/* the 2 records have the same IP address */
-				if (ip_equal(namerec->data.ip[0], record->ip[0])) {
+				if (ip_equal(namerec->data.addrs[0].ip, record->ips[0])) {
 					if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
 						get_global_id_and_update(&namerec->data.id, True);
 					else
@@ -1956,8 +1935,13 @@ void nmbd_wins_new_entry(int msg_type, p
 		if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
 			if (namerec->data.wins_flags&WINS_ACTIVE) {
 				for (i=0; i<record->num_ips; i++)
-					if(!find_ip_in_name_record(namerec, record->ip[i]))
-						add_ip_to_name_record(namerec, record->ip[i]);
+					if(!find_ip_in_name_record(namerec, record->ips[i])){
+						struct nmb_addr addr;
+                    				addr.ip = record->ips[i];
+                    				addr.owner = record->owner;
+                    				addr.ttl = EXTINCTION_INTERVAL;
+						add_ip_to_name_record(namerec, addr);
+						}
 			}
 			else
 				overwrite=True;
@@ -1973,10 +1957,10 @@ void nmbd_wins_new_entry(int msg_type, p
 					overwrite=True;
 			}
 			else {
-				if (ip_equal(record->wins_ip, namerec->data.wins_ip))
+				if (ip_equal(record->owner, namerec->data.owner))
 					overwrite=True;
 				
-				if (ip_equal(namerec->data.wins_ip, our_fake_ip))
+				if (ip_equal(namerec->data.owner, wins_fake_ip()))
 					if (namerec->data.wins_flags&WINS_UNIQUE)
 						get_global_id_and_update(&namerec->data.id, True);
 				
@@ -1985,24 +1969,43 @@ void nmbd_wins_new_entry(int msg_type, p
 			if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
 				if (namerec->data.wins_flags&WINS_UNIQUE ||
 				    namerec->data.wins_flags&WINS_MHOMED)
-					if (ip_equal(record->wins_ip, namerec->data.wins_ip))
+					if (ip_equal(record->owner, namerec->data.owner))
 						overwrite=True;
 				
 		}
 
 		if (overwrite == False)
 			DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", 
-				  record->name, record->type, inet_ntoa(record->wins_ip)));
+				  record->name, record->type, inet_ntoa(record->owner)));
 		else {
+			struct nmb_addr *addr_list = NULL;
+			
 			DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", 
-				  record->name, record->type, inet_ntoa(record->wins_ip)));
+				  record->name, record->type, inet_ntoa(record->owner)));
 
 			/* remove the old record and add a new one */
-			remove_name_from_namelist( wins_server_subnet, namerec );
+			remove_name_from_namelist( wins_server_subnet, namerec );		
+
+			addr_list = (struct nmb_addr *)malloc(record->num_ips * sizeof(struct nmb_addr));
+		
+			if (addr_list == NULL) {
+				DEBUG(0,("nmbd_wins_new_entry: malloc failed!\n"));
+				return;
+			}
+			for(i=0;i<record->num_ips;i++) {
+				addr_list[i].ip = record->ips[i];
+				addr_list[i].owner = record->owner;
+				addr_list[i].ttl = EXTINCTION_INTERVAL;
+			}
+
 			new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 
-						EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
+						EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, addr_list);
+
+			SAFE_FREE(addr_list);
+
 			if (new_namerec!=NULL) {
-				update_wins_owner(new_namerec, record->wins_ip);
+				dump_nmb_record(new_namerec);
+				update_wins_owner(new_namerec, record->owner);
 				update_wins_flag(new_namerec, record->wins_flags);
 				new_namerec->data.id=record->id;
 
@@ -2014,11 +2017,4 @@ void nmbd_wins_new_entry(int msg_type, p
 
 	}
 }
-
-
-
-
-
-
-
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/winsdb_interface.c HEAD-nmbd/source/nmbd/winsdb_interface.c
--- HEAD/source/nmbd/winsdb_interface.c	Thu Jan  1 01:00:00 1970
+++ HEAD-nmbd/source/nmbd/winsdb_interface.c	Mon Nov 18 07:08:01 2002
@@ -0,0 +1,294 @@
+/* 
+   Unix SMB/CIFS implementation.
+   WINSDB functions
+
+   Copyright (C) Stefan (metze) Metzmacher	2002
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   
+*/
+
+#include "includes.h"
+
+/** List of various built-in winsdb modules */
+
+const struct {
+	char *module_name;
+	/* Function to create a winsdb_context */
+	winsdb_init_function init;
+} builtin_winsdb_init_functions[] = {
+	{ "tdb", winsdb_init_tdb },
+	{ NULL, NULL}
+};
+
+static struct winsdb_init_function_entry *backends;
+
+static void lazy_initialize_winsdb()
+{
+	int i;
+	static BOOL initialised = False;
+	
+	if(!initialised) {
+		initialised = True;
+
+		for(i = 0; builtin_winsdb_init_functions[i].module_name; i++) {
+			smb_register_winsdb(builtin_winsdb_init_functions[i].module_name, builtin_winsdb_init_functions[i].init, WINSDB_INTERFACE_VERSION);
+		}
+	}
+}
+
+BOOL smb_register_winsdb(char *name, winsdb_init_function init, int version) 
+{
+	struct winsdb_init_function_entry *entry = backends;
+
+	if(version != WINSDB_INTERFACE_VERSION)
+		return False;
+
+	DEBUG(5,("Attempting to register winsdb backend %s\n", name));
+
+	/* Check for duplicates */
+	while(entry) { 
+		if(strcasecmp(name, entry->module_name) == 0) { 
+			DEBUG(0,("There already is a winsdb backend registered with the name %s!\n", name));
+			return False;
+		}
+		entry = entry->next;
+	}
+
+	entry = smb_xmalloc(sizeof(struct winsdb_init_function_entry));
+	entry->module_name = name;
+	entry->init = init;
+
+	DLIST_ADD(backends, entry);
+	DEBUG(5,("Successfully added winsdb backend '%s'\n", name));
+	return True;
+}
+
+/******************************************************************
+  Make a winsdb_context from scratch.
+ *******************************************************************/
+static NTSTATUS make_winsdb_context(WINSDB_CONTEXT **context) 
+{
+	TALLOC_CTX *mem_ctx;
+
+	if (!context)
+		return NT_STATUS_INVALID_PARAMETER;
+		
+	mem_ctx = talloc_init_named("winsdb_context internal allocation context");
+
+	if (!mem_ctx) {
+		DEBUG(0, ("make_winsdb_context: talloc init failed!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}		
+
+	*context = talloc(mem_ctx, sizeof(**context));
+	if (!*context) {
+		DEBUG(0, ("make_winsdb_context: talloc failed!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ZERO_STRUCTP(*context);
+
+	(*context)->mem_ctx = mem_ctx;
+
+	return NT_STATUS_OK;
+}
+
+/******************************************************************
+  Make a winsdb_context from scratch
+ *******************************************************************/
+NTSTATUS make_winsdb_context_by_name(WINSDB_CONTEXT **context, const char *backend_string)
+{
+	char *module_name = smb_xstrdup(backend_string);
+	char *module_location = NULL, *p;
+	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	struct winsdb_init_function_entry *entry;
+	int i;
+
+	lazy_initialize_winsdb();
+
+	entry = backends;
+
+	if (!NT_STATUS_IS_OK(nt_status = make_winsdb_context(context))) {
+		DEBUG(4,("make_winsdb_context failed\n"));
+		return nt_status;
+	}
+	
+	p = strchr(module_name, ':');
+
+	if (p) {
+		*p = 0;
+		module_location = p+1;
+		trim_string(module_location, " ", " ");
+	}
+
+	trim_string(module_name, " ", " ");
+
+	DEBUG(5,("Attempting to find an winsdb backend to match %s (%s)\n", backend_string, module_name));
+	while(entry) {
+		if (strequal(entry->module_name, module_name)) {
+			DEBUG(5,("Found winsdb backend %s\n", module_name));
+			nt_status = entry->init(*context, module_location);
+			if (NT_STATUS_IS_OK(nt_status)) {
+				DEBUG(5,("winsdb backend %s has a valid init\n", backend_string));
+			} else {
+				DEBUG(0,("winsdb backend %s did not correctly init (error was %s)\n", backend_string, nt_errstr(nt_status)));
+			}
+			SAFE_FREE(module_name);
+			return nt_status;
+			break; /* unreached */
+		}
+		entry = entry->next;
+	}
+
+	/* No such backend found */
+	SAFE_FREE(module_name);
+	return NT_STATUS_INVALID_PARAMETER;
+}
+
+/******************************************************************
+ Return an already initialised winsdb_context, to facilitate backward 
+ compatibility (see functions below).
+*******************************************************************/
+
+static struct winsdb_context *winsdb_get_static_context(BOOL reload) 
+{
+	static struct winsdb_context *winsdb_context = NULL;
+
+	if ((winsdb_context) && (reload)) {
+		winsdb_free_context(&winsdb_context);
+		if (NT_STATUS_IS_ERR(make_winsdb_context_by_name(&winsdb_context, lp_winsdb_backend()))) {
+			return NULL;
+		}
+	}
+
+	if (!winsdb_context) {
+		if (NT_STATUS_IS_ERR(make_winsdb_context_by_name(&winsdb_context, lp_winsdb_backend()))) {
+			return NULL;
+		}
+	}
+
+	return winsdb_context;
+}
+
+void winsdb_free_context(WINSDB_CONTEXT **context)
+{
+	if (context) {
+		if ((*context)->free_private_data) {
+			(*context)->free_private_data(context);
+		}			
+		talloc_destroy((*context)->mem_ctx);
+		*context = NULL; 
+	}
+}
+
+/****************************************************************************
+open the wins database for read or write 
+*****************************************************************************/
+NTSTATUS winsdb_open(WINSDB_CONTEXT *context, BOOL write_db)
+{
+	if (!context)
+		context = winsdb_get_static_context(False);
+
+	if (!context || !context->open) {
+		DEBUG(0,("winsdb_open: No context or no function found\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	return context->open(context, write_db);
+}
+
+/****************************************************************************
+return the general ID value
+*****************************************************************************/
+NTSTATUS winsdb_get_global_id(WINSDB_CONTEXT *context, SMB_BIG_UINT *current_id)
+{
+	if (!current_id)
+		return NT_STATUS_INVALID_PARAMETER;
+		
+	if (!context)
+		context = winsdb_get_static_context(False);
+
+	if (!context || !context->get_global_id) {
+		DEBUG(0,("winsdb_get_global_id: No context or no function found\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	return context->get_global_id(context, current_id);
+}
+
+/****************************************************************************
+return the general ID value and increase it if requested
+*****************************************************************************/
+NTSTATUS winsdb_store_global_id(WINSDB_CONTEXT *context, SMB_BIG_UINT current_id)
+{
+	if (!context)
+		context = winsdb_get_static_context(False);
+
+	if (!context || !context->get_global_id) {
+		DEBUG(0,("winsdb_store_global_id: No context or no function found\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	return context->store_global_id(context, current_id);
+}
+
+/****************************************************************************
+get the next sored record from the wins database 
+*****************************************************************************/
+NTSTATUS winsdb_get_next_record(WINSDB_CONTEXT *context, struct name_record **namerec)
+{
+	if (!namerec)
+		return NT_STATUS_INVALID_PARAMETER;
+		
+	if (!context)
+		context = winsdb_get_static_context(False);
+
+	if (!context || !context->get_next_record) {
+		DEBUG(0,("winsdb_get_next_record: No context or no function found\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	return context->get_next_record(context, namerec);
+}
+
+/****************************************************************************
+store a record in the wins database 
+*****************************************************************************/
+NTSTATUS winsdb_store_record(WINSDB_CONTEXT *context, const struct name_record *namerec)
+{
+	if (!namerec)
+		return NT_STATUS_INVALID_PARAMETER;
+		
+	if (!context)
+		context = winsdb_get_static_context(False);
+
+	if (!context || !context->store_record) {
+		DEBUG(0,("winsdb_store_record: No context or no function found\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	return context->store_record(context, namerec);
+}
+
+/****************************************************************************
+close the wins database 
+*****************************************************************************/
+NTSTATUS winsdb_close(WINSDB_CONTEXT *context)
+{
+	if (!context)
+		context = winsdb_get_static_context(False);
+
+	if (!context || !context->close) {
+		DEBUG(0,("winsdb_close: No context or no function found\n"));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	return context->close(context);
+}
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/nmbd/winsdb_tdb.c HEAD-nmbd/source/nmbd/winsdb_tdb.c
--- HEAD/source/nmbd/winsdb_tdb.c	Thu Jan  1 01:00:00 1970
+++ HEAD-nmbd/source/nmbd/winsdb_tdb.c	Mon Nov 18 12:06:27 2002
@@ -0,0 +1,571 @@
+/* 
+   Unix SMB/CIFS implementation.
+   WINSDB functions
+
+   Copyright (C) Stefan (metze) Metzmacher	2002
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   
+*/
+
+#include "includes.h"
+
+static int winsdb_tdb_debug_level = DBGC_ALL;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS winsdb_tdb_debug_level
+
+#if 0 /* only for testing --metze */
+#define WINSDB_TDB_FILE	"wins.tdb"
+#else
+#define WINSDB_TDB_FILE	"wins_test.tdb"
+#endif
+
+#define WINSDB_TDB_VERSION_1	1
+#define WINSDB_TDB_VERSION_2	2
+#define WINSDB_TDB_VERSION	WINSDB_TDB_VERSION_2
+
+#define WINSDB_TDB_INFO_VERSION	"INFO/version"
+#define WINSDB_TDB_INFO_COUNT	"INFO/num_entries"
+#define WINSDB_TDB_INFO_ID_HIGH	"INFO/id_high"
+#define WINSDB_TDB_INFO_ID_LOW	"INFO/id_low"
+#define WINSDB_TDB_ENTRY_PREFIX "ENTRY/"
+
+struct winsdb_tdb_privates {
+	char			*path;
+	TDB_CONTEXT 		*tdb;
+	BOOL			write_db;
+	int			num_records;
+	BOOL			not_first_key;
+	TDB_DATA 		current_kbuf;
+	struct name_record	*next;
+	struct name_record	**list;
+};
+
+static BOOL winsdb_tdb_convert_v1_to_v2(const char *path);
+
+/****************************************************************************
+close the wins database 
+*****************************************************************************/
+static NTSTATUS winsdb_tdb_close(WINSDB_CONTEXT *context)
+{
+	struct winsdb_tdb_privates	*privates = (struct winsdb_tdb_privates *)context->private_data;
+
+	DEBUG(5,("winsdb_tdb_close: started\n"));
+		
+	if (privates->tdb){
+		if (privates->write_db) {
+			tdb_store_int32(privates->tdb, 	WINSDB_TDB_INFO_COUNT, privates->num_records);
+		}
+		tdb_close(privates->tdb);
+		privates->tdb = NULL;
+		privates->not_first_key = False;
+	}
+	
+	DEBUG(5,("winsdb_tdb_close: done\n"));	
+	return NT_STATUS_OK;
+}
+
+/****************************************************************************
+open the wins database for read or write 
+*****************************************************************************/
+static NTSTATUS winsdb_tdb_open(WINSDB_CONTEXT *context, BOOL write_db)
+{
+	struct winsdb_tdb_privates	*privates = (struct winsdb_tdb_privates *)context->private_data;
+	int wins_version;
+	
+	DEBUG(5,("winsdb_tdb_open: started\n"));
+
+	privates->write_db = write_db;
+	if (privates->tdb) {
+		DEBUG(4,("winsdb_tdb_open: a file is already open: close it before open in the desired modus\n"));
+		winsdb_tdb_close(context);
+	}
+
+	if (write_db) {
+		privates->tdb = tdb_open_log(privates->path, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
+		if (!privates->tdb) {
+			DEBUG(0,("initialise_wins: Can't open wins database file %s for write. Error was %s\n", privates->path, strerror(errno) ));
+			return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+		}
+		tdb_store_int32(privates->tdb, WINSDB_TDB_INFO_VERSION, WINSDB_TDB_VERSION);
+		return NT_STATUS_OK;
+	}
+	
+	
+	privates->tdb = tdb_open_log(privates->path, 0, TDB_DEFAULT, O_RDONLY, 0600);
+	if (!privates->tdb) {
+		DEBUG(0,("initialise_wins: Can't open wins database file %s for read. Error was %s\n", privates->path, strerror(errno) ));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+
+	if ((wins_version=tdb_fetch_int32(privates->tdb, WINSDB_TDB_INFO_VERSION)) != WINSDB_TDB_VERSION) {
+		winsdb_tdb_close(context);
+		switch(wins_version) {
+			case WINSDB_TDB_VERSION_1:
+				DEBUG(5,("Try to convert %s from WINDB_TDB_VERION_1 to WINDB_TDB_VERION_2!\n",
+						privates->path));
+				if (winsdb_tdb_convert_v1_to_v2(privates->path)) {
+					return winsdb_tdb_open(context,False);
+				} else {
+					DEBUG(0,("Can't convert %s from WINDB_TDB_VERION_1 to WINDB_TDB_VERION_2!\n",
+						privates->path));
+					return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+				}
+				break;
+		}
+		DEBUG(0,("Discarding invalid wins.tdb file: %s\n",privates->path));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+	
+	DEBUG(5,("winsdb_tdb_open: done\n"));
+	return NT_STATUS_OK;
+}
+
+/****************************************************************************
+return the general ID value
+*****************************************************************************/
+static NTSTATUS winsdb_tdb_get_global_id(WINSDB_CONTEXT *context, SMB_BIG_UINT *current_id)
+{
+	struct winsdb_tdb_privates	*privates = (struct winsdb_tdb_privates *)context->private_data;
+	int32 high=0,low=0;
+	
+	DEBUG(5,("winsdb_tdb_get_global_id: started\n"));
+	
+	if (!privates->tdb) {
+		DEBUG(0,("fail: tdb file is not open!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+
+	if (privates->write_db) {
+		DEBUG(0,("fail: tdb file is opened for write!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+	
+	high = tdb_fetch_int32(privates->tdb, WINSDB_TDB_INFO_ID_HIGH);
+	low = tdb_fetch_int32(privates->tdb, WINSDB_TDB_INFO_ID_LOW);
+
+
+	*current_id = high;
+	*current_id = *current_id>>32;
+	*current_id |= low & 0xffffffff;
+
+	DEBUG(5,("winsdb_tdb_get_global_id: done\n"));	
+	return NT_STATUS_OK;
+}
+
+/****************************************************************************
+return the general ID value
+*****************************************************************************/
+static NTSTATUS winsdb_tdb_store_global_id(WINSDB_CONTEXT *context, SMB_BIG_UINT current_id)
+{
+	struct winsdb_tdb_privates	*privates = (struct winsdb_tdb_privates *)context->private_data;
+
+	DEBUG(5,("winsdb_tdb_store_global_id: started\n"));
+	
+	if (!privates->tdb) {
+		DEBUG(0,("fail: tdb file is not open!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+
+	if (!privates->write_db) {
+		DEBUG(0,("fail: tdb file is opened for read!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+	
+	tdb_store_int32(privates->tdb, WINSDB_TDB_INFO_ID_HIGH,current_id>>32);
+	tdb_store_int32(privates->tdb, WINSDB_TDB_INFO_ID_LOW,current_id&0xffffffff);
+
+	DEBUG(5,("winsdb_tdb_store_global_id: done\n"));
+	return NT_STATUS_OK;
+}
+
+/****************************************************************************
+get the next sored record from the wins database 
+*****************************************************************************/
+static NTSTATUS winsdb_tdb_get_next_record(WINSDB_CONTEXT *context, struct name_record **namerec)
+{
+	struct winsdb_tdb_privates	*privates = (struct winsdb_tdb_privates *)context->private_data;
+	TDB_DATA dbuf, new_kbuf;
+
+	DEBUG(5,("winsdb_tdb_get_next_record: started\n"));
+
+	if (!privates->tdb) {
+		DEBUG(0,("fail: tdb file is not open!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+
+	if (privates->write_db) {
+		DEBUG(0,("fail: tdb file is opened for write!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+	
+	if (!privates->not_first_key) {
+		privates->current_kbuf = tdb_firstkey(privates->tdb);
+		privates->not_first_key = True;
+	} else {
+		new_kbuf = tdb_nextkey(privates->tdb, privates->current_kbuf);
+		SAFE_FREE(privates->current_kbuf.dptr);
+		privates->current_kbuf = new_kbuf; 
+	}	
+     
+	if(privates->current_kbuf.dptr!=NULL) {
+		pstring name_type, name;
+		struct in_addr owner_ip, ip;
+		char *p;
+		int type = 0;
+		int temp_ttl;
+		int high, low;
+		struct nmb_addr *addr_list;
+		int len=0,i;
+
+		if (strncmp(privates->current_kbuf.dptr, WINSDB_TDB_ENTRY_PREFIX, strlen(WINSDB_TDB_ENTRY_PREFIX)) != 0) {
+			*namerec = NULL;
+			DEBUG(5,("winsdb_tdb_get_next_record: done (no entry prefix - skip)\n"));
+			return NT_STATUS_OK;
+		}
+
+		dbuf = tdb_fetch(privates->tdb, privates->current_kbuf);
+		if (!dbuf.dptr) {
+			*namerec = NULL;
+			DEBUG(0,("winsdb_tdb_get_next_record: done (no data)\n"));
+			return NT_STATUS_OK;
+		}
+
+		fstrcpy(name_type, privates->current_kbuf.dptr+strlen(WINSDB_TDB_ENTRY_PREFIX));
+
+ 		pstrcpy(name, name_type);
+
+		if((p = strchr(name,'#')) != NULL) {
+			*p = 0;
+			sscanf(p+1,"%x",&type);
+		}
+
+		*namerec = (struct name_record *)malloc(sizeof(struct name_record));
+		if (*namerec==NULL) {
+			DEBUG(0,("malloc for namerec failed\n"));
+			return NT_STATUS_NO_MEMORY;
+		}
+		
+		make_nmb_name(&(*namerec)->name, name, type);
+		upcase_name(&(*namerec)->name, NULL );
+			
+		len = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddddddd",
+				&(*namerec)->data.nb_flags, 
+				&(*namerec)->data.wins_flags, 
+				&(*namerec)->data.owner.s_addr,
+				&high, &low, 
+				&(*namerec)->data.ttl, 
+				&(*namerec)->data.num_addrs);
+
+		(*namerec)->data.id = high;
+		(*namerec)->data.id = (*namerec)->data.id<<32;
+		(*namerec)->data.id |= low;
+		(*namerec)->source = REGISTER_NAME;
+		(*namerec)->subnet = wins_server_subnet;
+		
+ 		/* Allocate the space for the ip_list. */
+		if((addr_list = (struct nmb_addr *)malloc( (*namerec)->data.num_addrs * sizeof(struct nmb_addr))) == NULL) {
+			DEBUG(0,("malloc for addr_list failed\n"));
+			return NT_STATUS_NO_MEMORY;
+		}
+		
+		for (i = 0; i < (*namerec)->data.num_addrs; i++) {
+			len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "ddd", &owner_ip.s_addr,&temp_ttl,&ip.s_addr);
+			addr_list[i].owner = owner_ip;
+			addr_list[i].ttl = temp_ttl;
+			addr_list[i].ip = ip;			
+		}
+
+		(*namerec)->data.addrs = addr_list;
+		DEBUG(2,("winsdb_tdb_get_next_record: done\n"));
+		return NT_STATUS_OK;
+	}
+
+	DEBUG(2,("winsdb_tdb_get_next_record: done (last)\n"));
+	return NT_STATUS_NO_MORE_ENTRIES;
+}
+
+/****************************************************************************
+store a record in the wins database 
+*****************************************************************************/
+static NTSTATUS winsdb_tdb_store_record(WINSDB_CONTEXT *context, const struct name_record *namerec)
+{
+	struct winsdb_tdb_privates	*privates = (struct winsdb_tdb_privates *)context->private_data;
+	TDB_DATA kbuf, dbuf;
+	pstring key, buf;
+	int len=0;
+	int i;
+
+	DEBUG(5,("winsdb_tdb_store_record: started\n"));
+
+	if (!privates->tdb) {
+		DEBUG(0,("fail: tdb file is not open!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+
+	if (!privates->write_db) {
+		DEBUG(0,("fail: tdb file is opened for read!\n"));
+		return NT_STATUS_UNSUCCESSFUL;/*maybe an other error here? --metze*/
+	}
+	
+	DEBUG(3,("store name %-19s\n", nmb_namestr(&namerec->name) ));
+		
+	/* store the type in the key to make the name unique */
+	slprintf(key, sizeof(key), "%s%s#%02x", WINSDB_TDB_ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
+	dump_nmb_record(namerec);
+	len = tdb_pack(buf, sizeof(buf), "ddddddd",
+		(int)namerec->data.nb_flags,
+		namerec->data.wins_flags,
+		(int)namerec->data.owner.s_addr,
+		(int)(namerec->data.id>>32),
+		(int)(namerec->data.id&0xffffffff),
+		(int)namerec->data.ttl, 
+		namerec->data.num_addrs);
+	for (i = 0; i < namerec->data.num_addrs; i++) {
+		len += tdb_pack(buf+len, sizeof(buf)-len, "ddd", 
+			(int)namerec->data.addrs[i].owner.s_addr,
+			(int)namerec->data.addrs[i].ttl,
+			(int)namerec->data.addrs[i].ip.s_addr);
+	}
+	
+	kbuf.dsize = strlen(key)+1;
+	kbuf.dptr = key;
+	dbuf.dsize = len;
+	dbuf.dptr = buf;
+	if (tdb_store(privates->tdb, kbuf, dbuf, TDB_INSERT) != 0) 
+		return NT_STATUS_UNSUCCESSFUL;
+
+	privates->num_records++;
+
+	DEBUG(5,("winsdb_tdb_store_record: done\n"));
+	return NT_STATUS_OK;
+}
+
+static void winsdb_tdb_free_private_data(WINSDB_CONTEXT **context)
+{
+	/* todo */
+}
+
+/*****************************************************
+Init the WINSDB TDB backend  
+******************************************************/
+NTSTATUS winsdb_init_tdb(WINSDB_CONTEXT *context, const char *module_params)
+{
+	struct winsdb_tdb_privates *winsdb_tdb_state;
+	
+	context->backendname = "winsdb_tdb";
+
+	context->open = winsdb_tdb_open;
+	context->close = winsdb_tdb_close;
+	context->get_global_id = winsdb_tdb_get_global_id;
+	context->store_global_id = winsdb_tdb_store_global_id;
+	context->get_next_record = winsdb_tdb_get_next_record;
+	context->store_record = winsdb_tdb_store_record;
+
+
+	context->free_private_data = winsdb_tdb_free_private_data;
+
+	winsdb_tdb_state = (struct winsdb_tdb_privates *)talloc_zero(context->mem_ctx, sizeof(struct winsdb_tdb_privates));
+	if (!winsdb_tdb_state) {
+		DEBUG(0, ("talloc() failed for winsdb tdb private_data!\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (module_params && *module_params) {
+		winsdb_tdb_state->path = talloc_strdup(context->mem_ctx, module_params);
+		if (!winsdb_tdb_state->path) {
+			DEBUG(0, ("talloc_strdup() failed.\n"));
+			return NT_STATUS_NO_MEMORY;
+		}
+	} else {
+		winsdb_tdb_state->path = talloc_strdup(context->mem_ctx, lock_path(WINSDB_TDB_FILE));
+	}
+	
+	winsdb_tdb_state->not_first_key = False;
+	context->private_data = (void *)winsdb_tdb_state;
+	
+	winsdb_tdb_debug_level = debug_add_class("winsdb_tdb");
+	if (winsdb_tdb_debug_level == -1) {
+		winsdb_tdb_debug_level = DBGC_ALL;
+		DEBUG(0, ("winsdb_tdb: Couldn't register custom debugging class!\n"));
+	} else DEBUG(2, ("winsdb_tdb: Debug class number of 'winsdb_tdb': %d\n", winsdb_tdb_debug_level));
+    
+	DEBUG(5, ("Initializing winsdb_tdb\n"));
+	if (module_params)
+		DEBUG(10, ("Module Parameters: %s\n", module_params));
+
+	return NT_STATUS_OK;
+}
+
+
+/****************************************************************************
+Load the WINS database Version 1 .
+only for backward compatibility.
+*****************************************************************************/
+static BOOL winsdb_tdb_convert_v1_to_v2(const char *path)
+{
+	TDB_CONTEXT *old_tdb, *new_tdb;
+	TDB_DATA old_kbuf, new_kbuf, old_dbuf, new_dbuf, nextkey;
+	pstring fnamenew;
+	int num_records = 0;
+
+	if (!path) {
+		DEBUG(0,("winsdb_tdb_convert_v1_to_v2: no path given!\n"));
+		return False;
+	}
+	DEBUG(2,("winsdb_tdb_convert_v1_to_v2: for %s started\n",path));
+
+	if(!lp_we_are_a_wins_server())
+		return False;
+
+	old_tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDONLY, 0600);
+	if (!old_tdb) {
+		DEBUG(2,("winsdb_tdb_convert_v1_to_v2: Can't open wins database file %s. Error was %s\n", path, strerror(errno) ));
+		return False;
+	}
+	
+	if (tdb_fetch_int32(old_tdb, WINSDB_TDB_INFO_VERSION) != WINSDB_TDB_VERSION_1) {
+		DEBUG(0,("Discarding invalid wins.tdb file not WINSDB_TDB_VERSION_1\n"));
+		tdb_close(old_tdb);
+		return False;
+	}
+		
+	slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", path, (unsigned int)sys_getpid());
+
+	new_tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
+	if (!new_tdb) {
+		DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
+		return False;
+	}
+
+	tdb_store_int32(new_tdb, WINSDB_TDB_INFO_VERSION, WINSDB_TDB_VERSION);
+	
+	for (old_kbuf = tdb_firstkey(old_tdb); 
+	     old_kbuf.dptr; 
+	     nextkey = tdb_nextkey(old_tdb, old_kbuf), safe_free(old_kbuf.dptr), old_kbuf=nextkey) {
+
+		pstring ip_str,owner_ip_str;
+		pstring new_buf;
+		pstring name;
+		int nb_flags;
+		int ttl;
+		unsigned int num_addrs;
+		int high, low;
+		struct in_addr owner_ip;
+		struct nmb_addr *addr_list;
+		int wins_flags;
+		int old_len,new_len,i;
+
+		if (strncmp(old_kbuf.dptr, WINSDB_TDB_ENTRY_PREFIX, strlen(WINSDB_TDB_ENTRY_PREFIX)) != 0)
+			continue;
+				
+		fstrcpy(name, old_kbuf.dptr+strlen(WINSDB_TDB_ENTRY_PREFIX));
+
+		old_dbuf = tdb_fetch(old_tdb, old_kbuf);
+		if (!old_dbuf.dptr) continue;
+
+		old_len = tdb_unpack(old_dbuf.dptr, old_dbuf.dsize, "dddfddd",
+				&nb_flags, &high, &low,
+				owner_ip_str, &ttl, &num_addrs, &wins_flags);
+
+		owner_ip=*interpret_addr2(owner_ip_str);
+
+ 		/* Allocate the space for the ip_list. */
+		if((addr_list = (struct nmb_addr *)malloc( num_addrs * sizeof(struct nmb_addr))) == NULL) {
+			DEBUG(0,("initialise_wins: Malloc fail !\n"));
+			return False;
+		}
+
+		for (i = 0; i < num_addrs; i++) {
+			old_len += tdb_unpack(old_dbuf.dptr+old_len, old_dbuf.dsize-old_len, "f", ip_str);
+			addr_list[i].ip = *interpret_addr2(ip_str);
+			addr_list[i].ttl = ttl;
+			addr_list[i].owner = owner_ip;
+		}
+
+		new_len = tdb_pack(new_buf, sizeof(new_buf), "ddddddd",
+				(int)nb_flags,
+				(int)wins_flags,
+				(int)owner_ip.s_addr,
+				(int)high,
+				(int)low,
+				(int)ttl, 
+				(int)num_addrs);
+
+		DEBUG(15,("Name: %-17s Owner: %15s\nWINS_Flags: 0x%02X NB_FALGS: 0x%02X ID: 0x%08X%08X\n",
+				name,inet_ntoa(owner_ip),wins_flags,nb_flags,high,low));
+		{
+			char *ts, *nl;
+			struct tm *tm;
+			tm = LocalTime((time_t)&ttl);
+			ts = asctime(tm);
+			nl = strrchr_m( ts, '\n' );
+			if( NULL != nl )
+				*nl = '\0';
+
+			DEBUGADD(15,("TTL = %s\n", ts ));
+		}
+		for (i = 0; i < num_addrs; i++) {
+			new_len += tdb_pack(new_buf+new_len, sizeof(new_buf)-new_len, "ddd", 
+				(int)addr_list[i].owner.s_addr,
+				(int)addr_list[i].ttl,
+				(int)addr_list[i].ip.s_addr);
+			DEBUGADD(15,("IP: %15s ",
+				inet_ntoa(addr_list[i].ip)));
+			DEBUGADD(15,("OWNER: %15s ",
+				inet_ntoa(addr_list[i].owner)));
+			{
+				char *ts, *nl;
+				struct tm *tm;
+				tm = LocalTime(&addr_list[i].ttl);
+				ts = asctime(tm);
+				nl = strrchr_m( ts, '\n' );
+				if( NULL != nl )
+					*nl = '\0';
+
+				DEBUGADD(15,("TTL = %s\n", ts ));
+			}
+		}
+
+		new_kbuf.dsize = old_dbuf.dsize;
+		new_kbuf.dptr = old_dbuf.dptr;
+		new_dbuf.dsize = new_len;
+		new_dbuf.dptr = new_buf;
+		
+		SAFE_FREE(addr_list);
+		
+		if (tdb_store(new_tdb, new_kbuf, new_dbuf, TDB_INSERT) != 0) { 
+			return False;
+		}
+		num_records++;
+	}
+    
+	/* store the number of records */
+	tdb_store_int32(new_tdb, WINSDB_TDB_INFO_COUNT, num_records);
+
+	tdb_store_int32(new_tdb, WINSDB_TDB_INFO_ID_HIGH, tdb_fetch_int32(old_tdb, WINSDB_TDB_INFO_ID_HIGH));
+	tdb_store_int32(new_tdb, WINSDB_TDB_INFO_ID_LOW, tdb_fetch_int32(old_tdb, WINSDB_TDB_INFO_ID_LOW));
+
+	tdb_close(old_tdb);
+	tdb_close(new_tdb);
+
+	chmod(fnamenew,0644);
+	unlink(path);
+	rename(fnamenew,path);
+	
+	DEBUG(2,("winsdb_tdb_convert_v1_to_v2: done\n"));
+	return True;
+}
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/param/loadparm.c HEAD-nmbd/source/param/loadparm.c
--- HEAD/source/param/loadparm.c	Wed Nov 13 19:52:39 2002
+++ HEAD-nmbd/source/param/loadparm.c	Mon Nov 18 07:08:56 2002
@@ -220,6 +220,7 @@ typedef struct
 	BOOL bMsAddPrinterWizard;
 	BOOL bDNSproxy;
 	BOOL bWINSsupport;
+	char *szWinsdbBackend;
 	BOOL bWINSproxy;
 	BOOL bLocalMaster;
 	BOOL bPreferredMaster;
@@ -975,6 +976,7 @@ static struct parm_struct parm_table[] =
 	
 	{"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
 	{"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+	{"winsdb backend", P_STRING, P_GLOBAL, &Globals.szWinsdbBackend, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
 	{"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 	{"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
 
@@ -1402,6 +1404,7 @@ static void init_globals(void)
 	Globals.bDomainLogons = False;
 	Globals.bBrowseList = True;
 	Globals.bWINSsupport = False;
+	string_set(&Globals.szWinsdbBackend, WINSDB_DEFAULT_BACKEND);
 	Globals.bWINSproxy = False;
 
 	Globals.bDNSproxy = True;
@@ -1613,6 +1616,7 @@ FN_GLOBAL_BOOL(lp_disable_netbios, &Glob
 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
+FN_GLOBAL_STRING(lp_winsdb_backend, &Globals.szWinsdbBackend)
 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/ubiqx/sys_include.h HEAD-nmbd/source/ubiqx/sys_include.h
--- HEAD/source/ubiqx/sys_include.h	Wed Jan 26 22:25:35 2000
+++ HEAD-nmbd/source/ubiqx/sys_include.h	Mon Nov 18 07:41:53 2002
@@ -40,6 +40,7 @@
  */
 #define _PROTO_H_
 #define _NAMESERV_H_
+#define _WINSDB_H
 #define _HASH_H_
 
 /* The main Samba system-adaptive header file.
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=.#* HEAD/source/wrepld/process.c HEAD-nmbd/source/wrepld/process.c
--- HEAD/source/wrepld/process.c	Mon Jul 29 06:34:59 2002
+++ HEAD-nmbd/source/wrepld/process.c	Fri Nov 15 08:32:31 2002
@@ -30,14 +30,6 @@ int partner_count;
 
 TALLOC_CTX *mem_ctx;
 
-#define WINS_LIST "wins.tdb"
-#define INFO_VERSION	"INFO/version"
-#define INFO_COUNT	"INFO/num_entries"
-#define INFO_ID_HIGH	"INFO/id_high"
-#define INFO_ID_LOW	"INFO/id_low"
-#define ENTRY_PREFIX 	"ENTRY/"
-
-
 /*******************************************************************
 fill the header of a reply.
 ********************************************************************/
@@ -195,18 +187,13 @@ read the last ID from the wins tdb file.
 ****************************************************************************/
 static void get_our_last_id(WINS_OWNER *wins_owner)
 {
-	TDB_CONTEXT *tdb;
-
-	tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
-	if (!tdb) {
-		DEBUG(2,("get_our_last_id: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
-		return;
-	}
+	SMB_BIG_UINT id;
 	
-	wins_owner->max_version=((SMB_BIG_UINT)tdb_fetch_int32(tdb, INFO_ID_HIGH))<<32 | 
-				 (SMB_BIG_UINT)tdb_fetch_int32(tdb, INFO_ID_LOW);
-
-	tdb_close(tdb);
+	winsdb_open(NULL,False);
+	winsdb_get_global_id(NULL,&id);
+	winsdb_close(NULL);
+	
+	wins_owner->max_version=id;
 }
 
 /****************************************************************************
@@ -351,7 +338,7 @@ static void receive_version_number_map_t
 	          q->rep.avmt_rep.partner_count ,inet_ntoa(q->rep.avmt_rep.initiating_wins_server)));
 	DEBUG(5,("real peer is: %s\n", peer));
 
-	for (i=0; global_wins_table[0][i].address.s_addr!=addr.s_addr && i<partner_count;i++)
+	for (i=0; !ip_equal(global_wins_table[0][i].address,addr) && i<partner_count;i++)
 		;
 
 	if (i==partner_count) {
@@ -401,7 +388,7 @@ static void receive_version_number_map_t
 /****************************************************************************
 add an entry to the wins list we'll send.
 ****************************************************************************/
-static BOOL add_record_to_winsname(WINS_NAME **wins_name, int *max_names, char *name, int type, int wins_flags, int id, struct in_addr *ip_list, int num_ips)
+static BOOL add_record_to_winsname(WINS_NAME **wins_name, int *max_names, struct name_record *namerec, struct in_addr owner_ip, time_t time_now)
 {
 	WINS_NAME *temp_list;
 	int i;
@@ -413,34 +400,41 @@ static BOOL add_record_to_winsname(WINS_
 
 	temp_list[current].name_len=0x11;
 	
-	safe_strcpy(temp_list[current].name, name, 15);
+	safe_strcpy(temp_list[current].name, namerec->name.name, 15);
 
-	temp_list[current].type=type;
+	temp_list[current].type=namerec->name.name_type;
 	temp_list[current].empty=0;
 
-	temp_list[current].name_flag=wins_flags;
+	temp_list[current].name_flag=namerec->data.wins_flags;
 
-	if ( (wins_flags&0x03) == 1 || (wins_flags&0x03)==2)
+	if ( (namerec->data.wins_flags&0x03) == 1 || (namerec->data.wins_flags&0x03)==2)
 		temp_list[current].group_flag=0x01000000;
 	else
 		temp_list[current].group_flag=0x00000000;
 	
-	temp_list[current].id=id;
-	
-	temp_list[current].owner.s_addr=ip_list[0].s_addr;
+	temp_list[current].id=namerec->data.id;
 
 	if (temp_list[current].name_flag & 2) {
-		temp_list[current].num_ip=num_ips;
-		temp_list[current].others=(struct in_addr *)talloc(mem_ctx, sizeof(struct in_addr)*num_ips);
+		int y;
+		temp_list[current].num_ip = 0;
+		temp_list[current].others=(struct in_addr *)talloc(mem_ctx, sizeof(struct in_addr)*namerec->data.num_addrs);
 		if (temp_list[current].others==NULL)
 			return False;
 	
-		for (i=0; i<num_ips; i++)
-			temp_list[current].others[i].s_addr=ip_list[i].s_addr;
-
-	} else 
+		for (i=0,y=0; i<namerec->data.num_addrs; i++) {
+			if (ip_equal(namerec->data.addrs[i].owner,owner_ip) && 
+				(((namerec->data.addrs[i].ttl - 60)> time_now)||
+				(namerec->data.addrs[i].ttl == PERMANENT_TTL))){
+				temp_list[current].others[y]=namerec->data.addrs[i].ip;
+				temp_list[current].num_ip++;
+				y++;
+			}
+		}
+	} else {
 		temp_list[current].num_ip=1;
-
+		temp_list[current].owner=namerec->data.addrs[0].ip;
+	}
+	
 	temp_list[current].foo=0xffffffff;
 
 	*wins_name=temp_list;
@@ -457,10 +451,9 @@ static void send_entry_request(GENERIC_P
 	int i;
 	time_t time_now = time(NULL);
 	WINS_OWNER *wins_owner;
-	TDB_CONTEXT *tdb;
-	TDB_DATA kbuf, dbuf, newkey;
 	int s_ctx=get_server_assoc(q->header.assoc_ctx);
 	int num_interfaces = iface_count();
+	struct name_record *namerec;
 
 	if (s_ctx==0) {
 		DEBUG(1, ("send_entry_request: request for a partner not in our table\n"));
@@ -484,97 +477,37 @@ static void send_entry_request(GENERIC_P
 
 	for (i=0; i<num_interfaces; i++)
 		if (ip_equal(wins_owner->address, *iface_n_ip(i))) {
-			wins_owner->address=*interpret_addr2("0.0.0.0");
+			wins_owner->address=wins_fake_ip();
 			break;
 		}
 
 
-	tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
-	if (!tdb) {
-		DEBUG(2,("send_entry_request: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
-		return;
-	}
+	winsdb_open(NULL,False);
 
-	for (kbuf = tdb_firstkey(tdb); 
-	     kbuf.dptr; 
-	     newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
-		pstring name_type, name, ip_str;
-		char *p;
-		int type = 0;
-		int nb_flags;
-		int ttl;
-		unsigned int num_ips;
-		int low, high;
-		SMB_BIG_UINT version;
-		struct in_addr wins_ip;
-		struct in_addr *ip_list;
-		int wins_flags;
-		int len;
+	while(NT_STATUS_IS_OK(winsdb_get_next_record(NULL,&namerec))) {
 
-		if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
+		if (!namerec)
 			continue;
-		
-		
-		dbuf = tdb_fetch(tdb, kbuf);
-		if (!dbuf.dptr)
-			continue;
-
-		fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
-		pstrcpy(name, name_type);
-
-		if((p = strchr(name,'#')) != NULL) {
-			*p = 0;
-			sscanf(p+1,"%x",&type);
-		}
-
-		len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
-				&nb_flags,
-				&high,
-				&low,
-				ip_str,
-				&ttl, 
-				&num_ips,
-				&wins_flags);
-
-		wins_ip=*interpret_addr2(ip_str);
-
- 		/* Allocate the space for the ip_list. */
-		if((ip_list = (struct in_addr *)talloc(mem_ctx,  num_ips * sizeof(struct in_addr))) == NULL) {
-			DEBUG(0,("initialise_wins: talloc fail !\n"));
-			return;
-		}
-
-		for (i = 0; i < num_ips; i++) {
-			len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
-			ip_list[i] = *interpret_addr2(ip_str);
-		}
-
-		/* add all entries that have 60 seconds or more to live */
-		if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
-			if(ttl != PERMANENT_TTL)
-				ttl -= time_now;
-    
-			DEBUG( 4, ("send_entry_request: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
-			    name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
-
-			/* add the record to the list to send */
-			version=((SMB_BIG_UINT)high)<<32 | low;
 			
-			if (wins_owner->min_version<=version && wins_owner->max_version>=version &&
-			    wins_owner->address.s_addr==wins_ip.s_addr) {
-				if(!add_record_to_winsname(&r->rep.se_rp.wins_name, &max_names, name, type, wins_flags, version, ip_list, num_ips))
+		/* add all entries that have 60 seconds or more to live */
+		if ((namerec->data.ttl - 60) > time_now || namerec->data.ttl == PERMANENT_TTL) {
+			if(namerec->data.ttl != PERMANENT_TTL)
+				namerec->data.ttl -= time_now;
+
+			if (wins_owner->min_version<=namerec->data.id && wins_owner->max_version>=namerec->data.id &&
+			    ip_equal(wins_owner->address,namerec->data.owner)) {
+				if(!add_record_to_winsname(&r->rep.se_rp.wins_name, &max_names, namerec, wins_owner->address, time_now))
 					return;
 				max_names++;
 			}
 
 		} else {
-			DEBUG(4, ("send_entry_request: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
-				  name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
+			
 		}
 	}
-    
-	tdb_close(tdb);
 
+	winsdb_close(NULL);
+	
 	DEBUG(4,("send_entry_request, sending %d records\n", max_names));
 	fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE);
 	r->rep.msg_type=MESSAGE_REP_SEND_ENTRIES_REPLY; /* reply */
@@ -607,7 +540,7 @@ static void update_notify_request(GENERI
 	get_our_last_id(&global_wins_table[0][0]);
 
 	for (i=0; i<partner_count; i++) {
-		if (global_wins_table[0][i].address.s_addr==u->initiating_wins_server.s_addr) {
+		if (ip_equal(global_wins_table[0][i].address,u->initiating_wins_server)) {
 			DEBUG(5,("update_notify_request: found initiator at index %d\n", i));
 			break;
 		}
@@ -721,13 +654,13 @@ static void send_entry_reply(GENERIC_PAC
 		record.wins_flags=q->rep.se_rp.wins_name[k].name_flag&0x00ff;
 		record.num_ips=q->rep.se_rp.wins_name[k].num_ip;
 
-		record.wins_ip.s_addr=server.s_addr;
+		record.owner = server;
 
 		if (record.num_ips==1)
-			record.ip[0]=q->rep.se_rp.wins_name[k].owner;
+			record.ips[0]=q->rep.se_rp.wins_name[k].owner;
 		else
-			for (i=0; i<record.num_ips; i++)
-				record.ip[i]=q->rep.se_rp.wins_name[k].others[i];
+			for (i=0; i<record.num_ips && i< MAX_WINS_GROUP_IPS; i++)
+				record.ips[i]=q->rep.se_rp.wins_name[k].others[i];
 
 		record.nb_flags=0;
 


More information about the samba-technical mailing list