summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2005-12-06 23:06:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:05:45 -0500
commita342681792724c1ae8561ba8d352c4ee6e2a5332 (patch)
treedb15ef035492900ca8723aa41894cf5d6ded3810
parent1fa8039397175331d9f5e8b5e3897e9bba14484a (diff)
downloadsamba-a342681792724c1ae8561ba8d352c4ee6e2a5332.tar.gz
samba-a342681792724c1ae8561ba8d352c4ee6e2a5332.tar.xz
samba-a342681792724c1ae8561ba8d352c4ee6e2a5332.zip
r12107: Move to a tdb-based wins database. At the moment we still
use it as though it were an in-memory db and dump out to a flat file every 2 mins, but that can now change. Jeremy.
-rw-r--r--source/Makefile.in9
-rw-r--r--source/include/includes.h6
-rw-r--r--source/include/nameserv.h6
-rw-r--r--source/include/smb.h7
-rw-r--r--source/libsmb/nmblib.c2
-rw-r--r--source/nmbd/asyncdns.c26
-rw-r--r--source/nmbd/nmbd.c5
-rw-r--r--source/nmbd/nmbd_browserdb.c22
-rw-r--r--source/nmbd/nmbd_browsesync.c6
-rw-r--r--source/nmbd/nmbd_incomingrequests.c6
-rw-r--r--source/nmbd/nmbd_mynames.c8
-rw-r--r--source/nmbd/nmbd_namelistdb.c327
-rw-r--r--source/nmbd/nmbd_subnetdb.c33
-rw-r--r--source/nmbd/nmbd_winsproxy.c22
-rw-r--r--source/nmbd/nmbd_winsserver.c801
15 files changed, 891 insertions, 395 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index a80b16df715..bb3f72847b1 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -219,9 +219,6 @@ READLINE_OBJ = lib/readline.o
# Be sure to include them into your application
POPT_LIB_OBJ = lib/popt_common.o
-UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
- ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o
-
PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o
KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o
@@ -441,13 +438,13 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.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) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \
+NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_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) \
+WREPL_OBJ = $(WREPL_OBJ1) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
$(LIBSAMBA_OBJ)
@@ -543,7 +540,7 @@ LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o
LIBBIGBALLOFMUD_MAJOR = 0
-LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \
+LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
$(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ)
diff --git a/source/include/includes.h b/source/include/includes.h
index cde199eed8b..80fc3feed98 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -863,8 +863,6 @@ extern int errno;
/* Lists, trees, caching, database... */
#include "xfile.h"
#include "intl.h"
-#include "ubi_sLinkList.h"
-#include "ubi_dLinkList.h"
#include "dlinklist.h"
#include "tdb/tdb.h"
#include "tdb/spinlock.h"
@@ -887,10 +885,6 @@ extern int errno;
#include "util_getent.h"
-#ifndef UBI_BINTREE_H
-#include "ubi_Cache.h"
-#endif /* UBI_BINTREE_H */
-
#include "debugparse.h"
#include "version.h"
diff --git a/source/include/nameserv.h b/source/include/nameserv.h
index ec3d56c06b7..9f6bf76a093 100644
--- a/source/include/nameserv.h
+++ b/source/include/nameserv.h
@@ -217,7 +217,7 @@ struct nmb_data {
/* This structure represents an entry in a local netbios name list. */
struct name_record {
- ubi_trNode node[1];
+ struct name_record *prev, *next;
struct subnet_record *subnet;
struct nmb_name name; /* The netbios name. */
struct nmb_data data; /* The netbios data. */
@@ -225,7 +225,7 @@ struct name_record {
/* Browser cache for synchronising browse lists. */
struct browse_cache_record {
- ubi_dlNode node[1];
+ struct browse_cache_record *prev, *next;
unstring lmb_name;
unstring work_group;
struct in_addr ip;
@@ -425,7 +425,7 @@ struct subnet_record {
enum subnet_type type; /* To catagorize the subnet. */
struct work_record *workgrouplist; /* List of workgroups. */
- ubi_trRoot namelist[1]; /* List of netbios names. */
+ struct name_record *namelist; /* List of netbios names. */
struct response_record *responselist; /* List of responses expected. */
BOOL namelist_changed;
diff --git a/source/include/smb.h b/source/include/smb.h
index b2d28b7d70e..a3dce53a4ca 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1530,17 +1530,14 @@ struct node_status_extra {
/* There really is more here ... */
};
-struct pwd_info
-{
+struct pwd_info {
BOOL null_pwd;
BOOL cleartext;
fstring password;
-
};
-typedef struct user_struct
-{
+typedef struct user_struct {
struct user_struct *next, *prev;
uint16 vuid; /* Tag for this entry. */
uid_t uid; /* uid of a validated user */
diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c
index 164f85be7bf..4d84d7bc499 100644
--- a/source/libsmb/nmblib.c
+++ b/source/libsmb/nmblib.c
@@ -331,7 +331,7 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
Useful for debugging messages.
******************************************************************/
-char *nmb_namestr(struct nmb_name *n)
+char *nmb_namestr(const struct nmb_name *n)
{
static int i=0;
static fstring ret[4];
diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c
index 4db54ea198c..c0626d11619 100644
--- a/source/nmbd/asyncdns.c
+++ b/source/nmbd/asyncdns.c
@@ -34,16 +34,18 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_a
if (!addr.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,
+ add_name_to_subnet( wins_server_subnet, qname, name_type,
NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );
- return( NULL );
+ return NULL;
}
/* 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)));
- return( add_name_to_subnet( wins_server_subnet, qname, name_type,
- NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) );
+ add_name_to_subnet( wins_server_subnet, qname, name_type,
+ NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr);
+
+ return find_name_on_subnet(wins_server_subnet, question, FIND_ANY_NAME);
}
#ifndef SYNC_DNS
@@ -283,8 +285,7 @@ void run_dns_queue(void)
queue a DNS query
****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
+BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
if (in_dns || fd_in == -1)
return False;
@@ -316,9 +317,9 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
we use this when we can't do async DNS lookups
****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
+BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
+ struct name_record *namerec = NULL;
struct in_addr dns_ip;
unstring qname;
@@ -334,11 +335,12 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
/* Re-block TERM signal. */
BlockSignals(True, SIGTERM);
- *n = add_dns_result(question, dns_ip);
- if(*n == NULL)
+ namerec = add_dns_result(question, dns_ip);
+ if(namerec == NULL) {
send_wins_name_query_response(NAM_ERR, p, NULL);
- else
- send_wins_name_query_response(0, p, *n);
+ } else {
+ send_wins_name_query_response(0, p, namerec);
+ }
return False;
}
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 01fdb8e74cf..78411d34176 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -58,7 +58,7 @@ static void terminate(void)
DEBUG(0,("Got SIGTERM: going down...\n"));
/* Write out wins.dat file if samba is a WINS server */
- wins_write_database(False);
+ wins_write_database(0,False);
/* Remove all SELF registered names from WINS */
release_wins_names();
@@ -773,7 +773,10 @@ static BOOL open_sockets(BOOL isdaemon, int port)
pidfile_create("nmbd");
message_init();
message_register(MSG_FORCE_ELECTION, nmbd_message_election);
+#if 0
+ /* Until winsrepl is done. */
message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
+#endif
message_register(MSG_SHUTDOWN, nmbd_terminate);
message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
message_register(MSG_SEND_PACKET, msg_nmbd_send_packet);
diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c
index e8797a99d51..e27e483702a 100644
--- a/source/nmbd/nmbd_browserdb.c
+++ b/source/nmbd/nmbd_browserdb.c
@@ -35,7 +35,7 @@
* lmb_browserlist - This is our local master browser list.
*/
-ubi_dlNewList( lmb_browserlist );
+struct browse_cache_record *lmb_browserlist;
/* -------------------------------------------------------------------------- **
* Functions...
@@ -52,7 +52,8 @@ ubi_dlNewList( lmb_browserlist );
*/
static void remove_lmb_browser_entry( struct browse_cache_record *browc )
{
- safe_free( ubi_dlRemThis( lmb_browserlist, browc ) );
+ DLIST_REMOVE(lmb_browserlist, browc);
+ SAFE_FREE(browc);
}
/* ************************************************************************** **
@@ -85,6 +86,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
struct in_addr ip )
{
struct browse_cache_record *browc;
+ struct browse_cache_record *tmp_browc;
time_t now = time( NULL );
browc = SMB_MALLOC_P(struct browse_cache_record);
@@ -113,7 +115,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
browc->ip = ip;
- (void)ubi_dlAddTail( lmb_browserlist, browc );
+ DLIST_ADD_END(lmb_browserlist, browc, tmp_browc);
if( DEBUGLVL( 3 ) ) {
Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" );
@@ -138,12 +140,13 @@ struct browse_cache_record *find_browser_in_lmb_cache( const char *browser_name
{
struct browse_cache_record *browc;
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc; browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
- if( strequal( browser_name, browc->lmb_name ) )
+ for( browc = lmb_browserlist; browc; browc = browc->next ) {
+ if( strequal( browser_name, browc->lmb_name ) ) {
break;
+ }
+ }
- return( browc );
+ return browc;
}
/* ************************************************************************** **
@@ -160,9 +163,8 @@ void expire_lmb_browsers( time_t t )
struct browse_cache_record *browc;
struct browse_cache_record *nextbrowc;
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc; browc = nextbrowc ) {
- nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc );
+ for( browc = lmb_browserlist; browc; browc = nextbrowc) {
+ nextbrowc = browc->next;
if( browc->death_time < t ) {
if( DEBUGLVL( 3 ) ) {
diff --git a/source/nmbd/nmbd_browsesync.c b/source/nmbd/nmbd_browsesync.c
index 03234bb98fa..9535a3115a6 100644
--- a/source/nmbd/nmbd_browsesync.c
+++ b/source/nmbd/nmbd_browsesync.c
@@ -24,7 +24,7 @@
#include "includes.h"
/* This is our local master browser list database. */
-extern ubi_dlList lmb_browserlist[];
+extern struct browse_cache_record *lmb_browserlist;
/****************************************************************************
As a domain master browser, do a sync with a local master browser.
@@ -87,9 +87,7 @@ void dmb_expire_and_sync_browser_lists(time_t t)
expire_lmb_browsers(t);
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc;
- browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) {
+ for( browc = lmb_browserlist; browc; browc = browc->next ) {
if (browc->sync_time < t)
sync_with_lmb(browc);
}
diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c
index 7fac8c25739..eaef7097b4a 100644
--- a/source/nmbd/nmbd_incomingrequests.c
+++ b/source/nmbd/nmbd_incomingrequests.c
@@ -339,7 +339,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
names_added = 0;
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
+ namerec = subrec->namelist;
while (buf < bufend) {
if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
@@ -389,7 +389,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
buf = buf0 + 18*names_added;
- namerec = (struct name_record *)ubi_trNext( namerec );
+ namerec = namerec->next;
if (!namerec) {
/* End of the subnet specific name list. Now
@@ -398,7 +398,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
if (uni_subrec != subrec) {
subrec = uni_subrec;
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
+ namerec = subrec->namelist;
}
}
if (!namerec)
diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c
index 07247d5495e..f34d98172c6 100644
--- a/source/nmbd/nmbd_mynames.c
+++ b/source/nmbd/nmbd_mynames.c
@@ -182,8 +182,8 @@ void release_wins_names(void)
struct subnet_record *subrec = unicast_subnet;
struct name_record *namerec, *nextnamerec;
- for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = nextnamerec) {
- nextnamerec = (struct name_record *)ubi_trNext( namerec );
+ for (namerec = subrec->namelist; namerec; namerec = nextnamerec) {
+ nextnamerec = namerec->next;
if( (namerec->data.source == SELF_NAME)
&& !NAME_IS_DEREGISTERING(namerec) )
release_name( subrec, namerec, standard_success_release,
@@ -202,9 +202,7 @@ void refresh_my_names(time_t t)
if (wins_srv_count() < 1)
return;
- for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist);
- namerec;
- namerec = (struct name_record *)ubi_trNext(namerec)) {
+ for (namerec = unicast_subnet->namelist; namerec; namerec = namerec->next) {
/* Each SELF name has an individual time to be refreshed. */
if ((namerec->data.source == SELF_NAME) &&
(namerec->data.refresh_time < t) &&
diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c
index 88d5ea52f58..894b8776134 100644
--- a/source/nmbd/nmbd_namelistdb.c
+++ b/source/nmbd/nmbd_namelistdb.c
@@ -32,24 +32,26 @@ uint16 samba_nb_type = 0; /* samba's NetBIOS name type */
void set_samba_nb_type(void)
{
- if( lp_wins_support() || wins_srv_count() )
+ if( lp_wins_support() || wins_srv_count() ) {
samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */
- else
+ } else {
samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */
+ }
}
/***************************************************************************
Convert a NetBIOS name to upper case.
***************************************************************************/
-static void upcase_name( struct nmb_name *target, struct nmb_name *source )
+static void upcase_name( struct nmb_name *target, const struct nmb_name *source )
{
int i;
unstring targ;
fstring scope;
- if( NULL != source )
+ if( NULL != source ) {
memcpy( target, source, sizeof( struct nmb_name ) );
+ }
pull_ascii_nstring(targ, sizeof(targ), target->name);
strupper_m( targ );
@@ -63,25 +65,11 @@ static void upcase_name( struct nmb_name *target, struct nmb_name *source )
* unused space doesn't have garbage in it.
*/
- for( i = strlen( target->name ); i < sizeof( target->name ); i++ )
+ for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) {
target->name[i] = '\0';
- for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ )
+ }
+ for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) {
target->scope[i] = '\0';
-}
-
-/**************************************************************************
- Add a new or overwrite an existing namelist entry.
-***************************************************************************/
-
-static void update_name_in_namelist( struct subnet_record *subrec,
- struct name_record *namerec )
-{
- struct name_record *oldrec = NULL;
-
- ubi_trInsert( subrec->namelist, namerec, &namerec->name, &oldrec );
- if( oldrec ) {
- SAFE_FREE( oldrec->data.ip );
- SAFE_FREE( oldrec );
}
}
@@ -89,64 +77,81 @@ static void update_name_in_namelist( struct subnet_record *subrec,
Remove a name from the namelist.
***************************************************************************/
-void remove_name_from_namelist( struct subnet_record *subrec,
- struct name_record *namerec )
+void remove_name_from_namelist(struct subnet_record *subrec,
+ struct name_record *namerec )
{
- ubi_trRemove( subrec->namelist, namerec );
+ if (subrec == wins_server_subnet) {
+ remove_name_from_wins_namelist(namerec);
+ } else {
+ subrec->namelist_changed = True;
+ }
+ DLIST_REMOVE(subrec->namelist, namerec);
SAFE_FREE(namerec->data.ip);
ZERO_STRUCTP(namerec);
SAFE_FREE(namerec);
- subrec->namelist_changed = True;
}
/**************************************************************************
Find a name in a subnet.
**************************************************************************/
-struct name_record *find_name_on_subnet( struct subnet_record *subrec,
- struct nmb_name *nmbname,
- BOOL self_only )
+struct name_record *find_name_on_subnet(struct subnet_record *subrec,
+ const struct nmb_name *nmbname,
+ BOOL self_only)
{
- struct nmb_name uc_name[1];
+ struct nmb_name uc_name;
struct name_record *name_ret;
- upcase_name( uc_name, nmbname );
- name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name );
+ upcase_name( &uc_name, nmbname );
+
+ if (subrec == wins_server_subnet) {
+ return find_name_on_wins_subnet(&uc_name, self_only);
+ }
+
+ for( name_ret = subrec->namelist; name_ret; name_ret = name_ret->next) {
+ if (memcmp(&uc_name, &name_ret->name, sizeof(struct nmb_name)) == 0) {
+ break;
+ }
+ }
+
if( name_ret ) {
/* Self names only - these include permanent names. */
if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) {
DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
subrec->subnet_name, nmb_namestr(nmbname) ) );
- return( NULL );
+ return False;
}
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) );
- return( name_ret );
+
+ return name_ret;
}
DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
subrec->subnet_name, nmb_namestr(nmbname) ) );
- return( NULL );
+
+ return NULL;
}
/**************************************************************************
Find a name over all known broadcast subnets.
************************************************************************/
-struct name_record *find_name_for_remote_broadcast_subnet(
- struct nmb_name *nmbname,
- BOOL self_only )
+struct name_record *find_name_for_remote_broadcast_subnet(struct nmb_name *nmbname,
+ BOOL self_only)
{
struct subnet_record *subrec;
- struct name_record *namerec = NULL;
+ struct name_record *namerec;
for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) {
- if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) )
- break;
+ namerec = find_name_on_subnet(subrec, nmbname, self_only);
+ if (namerec) {
+ return namerec;
+ }
}
- return( namerec );
+ return NULL;
}
/**************************************************************************
@@ -157,34 +162,40 @@ void update_name_ttl( struct name_record *namerec, int ttl )
{
time_t time_now = time(NULL);
- if( namerec->data.death_time != PERMANENT_TTL )
+ if( namerec->data.death_time != PERMANENT_TTL) {
namerec->data.death_time = time_now + ttl;
+ }
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
- namerec->subnet->namelist_changed = True;
+ if (namerec->subnet == wins_server_subnet) {
+ wins_store_changed_namerec(namerec);
+ } else {
+ namerec->subnet->namelist_changed = True;
+ }
}
/**************************************************************************
Add an entry to a subnet name list.
***********************************************************************/
-struct name_record *add_name_to_subnet( struct subnet_record *subrec,
- const char *name,
- int type,
- uint16 nb_flags,
- int ttl,
- enum name_source source,
- int num_ips,
- struct in_addr *iplist)
+BOOL add_name_to_subnet( struct subnet_record *subrec,
+ const char *name,
+ int type,
+ uint16 nb_flags,
+ int ttl,
+ enum name_source source,
+ int num_ips,
+ struct in_addr *iplist)
{
+ BOOL ret = False;
struct name_record *namerec;
time_t time_now = time(NULL);
namerec = SMB_MALLOC_P(struct name_record);
if( NULL == namerec ) {
DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
- return( NULL );
+ return False;
}
memset( (char *)namerec, '\0', sizeof(*namerec) );
@@ -193,7 +204,7 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
ZERO_STRUCTP(namerec);
SAFE_FREE(namerec);
- return NULL;
+ return False;
}
namerec->subnet = subrec;
@@ -206,8 +217,9 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
namerec->data.wins_flags = WINS_ACTIVE;
/* If it's our primary name, flag it as so. */
- if( strequal( my_netbios_names(0), name ) )
+ if (strequal( my_netbios_names(0), name )) {
namerec->data.nb_flags |= NB_PERM;
+ }
/* Copy the IPs. */
namerec->data.num_ips = num_ips;
@@ -217,16 +229,14 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
namerec->data.source = source;
/* Setup the death_time and refresh_time. */
- if( ttl == PERMANENT_TTL )
+ if (ttl == PERMANENT_TTL) {
namerec->data.death_time = PERMANENT_TTL;
- else
+ } else {
namerec->data.death_time = time_now + ttl;
+ }
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
- /* Now add the record to the name list. */
- update_name_in_namelist( subrec, namerec );
-
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 ),
@@ -235,9 +245,20 @@ ttl=%d nb_flags=%2x to subnet %s\n",
(unsigned int)nb_flags,
subrec->subnet_name ) );
- subrec->namelist_changed = True;
+ /* Now add the record to the name list. */
+
+ if (subrec == wins_server_subnet) {
+ ret = add_name_to_wins_subnet(namerec);
+ /* Free namerec - it's stored in the tdb. */
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+ } else {
+ DLIST_ADD(subrec->namelist, namerec);
+ subrec->namelist_changed = True;
+ ret = True;
+ }
- return(namerec);
+ return ret;
}
/*******************************************************************
@@ -253,8 +274,8 @@ void standard_success_register(struct subnet_record *subrec,
{
struct name_record *namerec;
- namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
- if( NULL == namerec ) {
+ namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME);
+ if (namerec == NULL) {
unstring name;
pull_ascii_nstring(name, sizeof(name), nmbname->name);
add_name_to_subnet( subrec, name, nmbname->name_type,
@@ -277,14 +298,15 @@ void standard_fail_register( struct subnet_record *subrec,
{
struct name_record *namerec;
- namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
+ namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME);
DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) );
/* Remove the name from the subnet. */
- if( namerec )
+ if( namerec ) {
remove_name_from_namelist(subrec, namerec);
+ }
}
/*******************************************************************
@@ -293,13 +315,18 @@ on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) );
static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
{
- if( ind != namerec->data.num_ips )
+ 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) );
+ }
namerec->data.num_ips--;
- namerec->subnet->namelist_changed = True;
+ if (namerec->subnet == wins_server_subnet) {
+ wins_store_changed_namerec(namerec);
+ } else {
+ namerec->subnet->namelist_changed = True;
+ }
}
/*******************************************************************
@@ -310,9 +337,11 @@ BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip )
{
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_ips; i++) {
+ if(ip_equal( namerec->data.ip[i], ip)) {
return True;
+ }
+ }
return False;
}
@@ -326,8 +355,9 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
struct in_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_ip )) {
return;
+ }
new_list = SMB_MALLOC_ARRAY( struct in_addr, namerec->data.num_ips + 1);
if( NULL == new_list ) {
@@ -342,7 +372,11 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
namerec->data.ip = new_list;
namerec->data.num_ips += 1;
- namerec->subnet->namelist_changed = True;
+ if (namerec->subnet == wins_server_subnet) {
+ wins_store_changed_namerec(namerec);
+ } else {
+ namerec->subnet->namelist_changed = True;
+ }
}
/*******************************************************************
@@ -388,26 +422,29 @@ on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(
remove_ip_from_name_record( namerec, released_ip );
- if( namerec->data.num_ips == orig_num )
+ if( namerec->data.num_ips == 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), inet_ntoa(released_ip), subrec->subnet_name ) );
+ }
}
- if( namerec->data.num_ips == 0 )
+ if( namerec->data.num_ips == 0 ) {
remove_name_from_namelist( subrec, namerec );
+ }
}
/*******************************************************************
- Expires old names in a subnet namelist.
+ Expires old names in a subnet namelist.
+ NB. Does not touch the wins_subnet - no wins specific processing here.
******************************************************************/
-void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
+static void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
{
struct name_record *namerec;
struct name_record *next_namerec;
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) {
- next_namerec = (struct name_record *)ubi_trNext( namerec );
+ for( namerec = subrec->namelist; namerec; namerec = next_namerec ) {
+ next_namerec = namerec->next;
if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
if( namerec->data.source == SELF_NAME ) {
DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
@@ -420,13 +457,14 @@ name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) );
DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
subrec->subnet_name, nmb_namestr(&namerec->name)));
- remove_name_from_namelist( subrec, namerec );
+ remove_name_from_namelist(subrec, namerec );
}
}
}
/*******************************************************************
- Expires old names in all subnet namelists.
+ Expires old names in all subnet namelists.
+ NB. Does not touch the wins_subnet.
******************************************************************/
void expire_names(time_t t)
@@ -479,75 +517,85 @@ void add_samba_names_to_subnet( struct subnet_record *subrec )
add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
PERMANENT_NAME, num_ips, iplist);
- if(iplist != &subrec->myip)
+ if(iplist != &subrec->myip) {
SAFE_FREE(iplist);
+ }
}
/****************************************************************************
- Dump the contents of the namelists on all the subnets (including unicast)
- into a file. Initiated by SIGHUP - used to debug the state of the namelists.
+ Dump a name_record struct.
**************************************************************************/
-static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
+void dump_name_record( struct name_record *namerec, XFILE *fp)
{
- struct name_record *namerec;
const char *src_type;
struct tm *tm;
int i;
- x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec;
- namerec = (struct name_record *)ubi_trNext( namerec ) ) {
-
- x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
- switch(namerec->data.source) {
- case LMHOSTS_NAME:
- src_type = "LMHOSTS_NAME";
- break;
- case WINS_PROXY_NAME:
- src_type = "WINS_PROXY_NAME";
- break;
- case REGISTER_NAME:
- src_type = "REGISTER_NAME";
- break;
- case SELF_NAME:
- src_type = "SELF_NAME";
- break;
- case DNS_NAME:
- src_type = "DNS_NAME";
- break;
- case DNSFAIL_NAME:
- src_type = "DNSFAIL_NAME";
- break;
- case PERMANENT_NAME:
- src_type = "PERMANENT_NAME";
- break;
- default:
- src_type = "unknown!";
- break;
- }
+ x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
+ switch(namerec->data.source) {
+ case LMHOSTS_NAME:
+ src_type = "LMHOSTS_NAME";
+ break;
+ case WINS_PROXY_NAME:
+ src_type = "WINS_PROXY_NAME";
+ break;
+ case REGISTER_NAME:
+ src_type = "REGISTER_NAME";
+ break;
+ case SELF_NAME:
+ src_type = "SELF_NAME";
+ break;
+ case DNS_NAME:
+ src_type = "DNS_NAME";
+ break;
+ case DNSFAIL_NAME:
+ src_type = "DNSFAIL_NAME";
+ break;
+ case PERMANENT_NAME:
+ src_type = "PERMANENT_NAME";
+ break;
+ default:
+ src_type = "unknown!";
+ break;
+ }
- x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
+ x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
- if(namerec->data.death_time != PERMANENT_TTL) {
- tm = localtime(&namerec->data.death_time);
- x_fprintf(fp, "death_time = %s\t", asctime(tm));
- } else {
- x_fprintf(fp, "death_time = PERMANENT\t");
- }
+ if(namerec->data.death_time != PERMANENT_TTL) {
+ tm = localtime(&namerec->data.death_time);
+ x_fprintf(fp, "death_time = %s\t", asctime(tm));
+ } else {
+ x_fprintf(fp, "death_time = PERMANENT\t");
+ }
- if(namerec->data.refresh_time != PERMANENT_TTL) {
- tm = localtime(&namerec->data.refresh_time);
- x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
- } else {
- x_fprintf(fp, "refresh_time = PERMANENT\n");
- }
+ if(namerec->data.refresh_time != PERMANENT_TTL) {
+ tm = localtime(&namerec->data.refresh_time);
+ x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
+ } 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_ips);
+ for(i = 0; i < namerec->data.num_ips; i++) {
+ x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
+ }
+
+ x_fprintf(fp, "\n\n");
+
+}
+
+/****************************************************************************
+ Dump the contents of the namelists on all the subnets (including unicast)
+ into a file. Initiated by SIGHUP - used to debug the state of the namelists.
+**************************************************************************/
- x_fprintf(fp, "\n\n");
+static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
+{
+ struct name_record *namerec;
+ x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
+ for( namerec = subrec->namelist; namerec; namerec = namerec->next) {
+ dump_name_record(namerec, fp);
}
}
@@ -569,16 +617,21 @@ void dump_all_namelists(void)
return;
}
- for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
+ for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
dump_subnet_namelist( subrec, fp );
+ }
- if( !we_are_a_wins_client() )
+ if (!we_are_a_wins_client()) {
dump_subnet_namelist( unicast_subnet, fp );
+ }
- if( remote_broadcast_subnet->namelist != NULL )
+ if (remote_broadcast_subnet->namelist != NULL) {
dump_subnet_namelist( remote_broadcast_subnet, fp );
+ }
+
+ if (wins_server_subnet != NULL) {
+ dump_wins_subnet_namelist(fp );
+ }
- if( wins_server_subnet != NULL )
- dump_subnet_namelist( wins_server_subnet, fp );
x_fclose( fp );
}
diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c
index b53a6d7328f..b2e1178bebc 100644
--- a/source/nmbd/nmbd_subnetdb.c
+++ b/source/nmbd/nmbd_subnetdb.c
@@ -51,34 +51,6 @@ static void add_subnet(struct subnet_record *subrec)
DLIST_ADD(subnetlist, subrec);
}
-/* ************************************************************************** **
- * Comparison routine for ordering the splay-tree based namelists assoicated
- * with each subnet record.
- *
- * Input: Item - Pointer to the comparison key.
- * Node - Pointer to a node the splay tree.
- *
- * Output: The return value will be <0 , ==0, or >0 depending upon the
- * ordinal relationship of the two keys.
- *
- * ************************************************************************** **
- */
-static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
-{
- struct name_record *NR = (struct name_record *)Node;
-
- if( DEBUGLVL( 10 ) ) {
- struct nmb_name *Iname = (struct nmb_name *)Item;
-
- Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
- Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
- memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
- nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
- }
-
- return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
-}
-
/****************************************************************************
stop listening on a subnet
we don't free the record as we don't have proper reference counting for it
@@ -156,10 +128,7 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
return(NULL);
}
- memset( (char *)subrec, '\0', sizeof(*subrec) );
- (void)ubi_trInitTree( subrec->namelist,
- namelist_entry_compare,
- ubi_trOVERWRITE );
+ ZERO_STRUCTP(subrec);
if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c
index 75319724616..d6dc6261c84 100644
--- a/source/nmbd/nmbd_winsproxy.c
+++ b/source/nmbd/nmbd_winsproxy.c
@@ -33,7 +33,7 @@ static void wins_proxy_name_query_request_success( struct subnet_record *subrec,
unstring name;
struct packet_struct *original_packet;
struct subnet_record *orig_broadcast_subnet;
- struct name_record *namerec;
+ struct name_record *namerec = NULL;
uint16 nb_flags;
int num_ips;
int i;
@@ -64,22 +64,34 @@ returned for name %s.\n", nmb_namestr(nmbname) ));
return;
}
- for(i = 0; i < num_ips; i++)
+ for(i = 0; i < num_ips; i++) {
putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
+ }
}
/* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
- if(rrec == PERMANENT_TTL)
+ if(rrec == PERMANENT_TTL) {
ttl = lp_max_ttl();
+ }
pull_ascii_nstring(name, sizeof(name), nmbname->name);
- namerec = add_name_to_subnet( orig_broadcast_subnet, name,
+ add_name_to_subnet( orig_broadcast_subnet, name,
nmbname->name_type, nb_flags, ttl,
WINS_PROXY_NAME, num_ips, iplist );
- if(iplist != &ip)
+ namerec = find_name_on_subnet(orig_broadcast_subnet, nmbname, FIND_ANY_NAME);
+ if (!namerec) {
+ DEBUG(0,("wins_proxy_name_query_request_success: failed to add "
+ "name %s to subnet %s !\n",
+ name,
+ orig_broadcast_subnet->subnet_name ));
+ return;
+ }
+
+ if(iplist != &ip) {
SAFE_FREE(iplist);
+ }
/*
* Check that none of the IP addresses we are returning is on the
diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c
index 8a1f82c8b17..5c234bf8dcc 100644
--- a/source/nmbd/nmbd_winsserver.c
+++ b/source/nmbd/nmbd_winsserver.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
NBT netbios routines and daemon - version 2
- Copyright (C) Jeremy Allison 1994-2003
+ Copyright (C) Jeremy Allison 1994-2005
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
@@ -18,12 +18,312 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ Converted to store WINS data in a tdb. Dec 2005. JRA.
*/
#include "includes.h"
#define WINS_LIST "wins.dat"
#define WINS_VERSION 1
+#define WINSDB_VERSION 1
+
+/****************************************************************************
+ We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
+ name (65 bytes with the last byte being the name type).
+*****************************************************************************/
+
+TDB_CONTEXT *wins_tdb;
+
+/****************************************************************************
+ Convert a wins.tdb record to a struct name_record. Add in our global_scope().
+*****************************************************************************/
+
+static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
+{
+ struct name_record *namerec = NULL;
+ uint16 nb_flags;
+ unsigned char nr_src;
+ uint32 death_time, refresh_time;
+ uint32 id_low, id_high;
+ uint32 saddr;
+ uint32 wins_flags;
+ uint32 num_ips;
+ size_t len;
+ int i;
+
+ if (data.dptr == NULL || data.dsize == 0) {
+ return NULL;
+ }
+
+ /* Min size is "wbddddddd" + 1 ip address (4). */
+ if (data.dsize < 2 + 1 + (7*4) + 4) {
+ return NULL;
+ }
+
+ len = tdb_unpack(data.dptr, data.dsize,
+ "wbddddddd",
+ &nb_flags,
+ &nr_src,
+ &death_time,
+ &refresh_time,
+ &id_low,
+ &id_high,
+ &saddr,
+ &wins_flags,
+ &num_ips );
+
+ namerec = SMB_MALLOC_P(struct name_record);
+ if (!namerec) {
+ return NULL;
+ }
+
+ namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
+ if (!namerec->data.ip) {
+ SAFE_FREE(namerec);
+ return NULL;
+ }
+
+ namerec->subnet = wins_server_subnet;
+ push_ascii_nstring(namerec->name.name, key.dptr);
+ namerec->name.name_type = key.dptr[sizeof(unstring)];
+ /* Add the scope. */
+ push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
+
+ /* We're using a byte-by-byte compare, so we must be sure that
+ * unused space doesn't have garbage in it.
+ */
+
+ for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
+ namerec->name.name[i] = '\0';
+ }
+ for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
+ namerec->name.scope[i] = '\0';
+ }
+
+ namerec->data.nb_flags = nb_flags;
+ namerec->data.source = (enum name_source)nr_src;
+ namerec->data.death_time = (time_t)death_time;
+ namerec->data.refresh_time = (time_t)refresh_time;
+ namerec->data.id = id_low;
+#if defined(HAVE_LONGLONG)
+ namerec->data.id |= ((SMB_BIG_UINT)id_high << 32);
+#endif
+ namerec->data.wins_ip.s_addr = saddr;
+ namerec->data.wins_flags = wins_flags,
+ namerec->data.num_ips = num_ips;
+
+ for (i = 0; i < num_ips; i++) {
+ namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
+ }
+
+ return namerec;
+}
+
+/****************************************************************************
+ Convert a struct name_record to a wins.tdb record. Ignore the scope.
+*****************************************************************************/
+
+static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
+{
+ TDB_DATA data;
+ size_t len = 0;
+ int i;
+ uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
+#if defined(HAVE_LONGLONG)
+ uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
+#else
+ uint32 id_high = 0;
+#endif
+
+ ZERO_STRUCT(data);
+
+ len = (2 + 1 + (7*4)); /* "wbddddddd" */
+ len += (namerec->data.num_ips * 4);
+
+ data.dptr = SMB_MALLOC(len);
+ if (!data.dptr) {
+ return data;
+ }
+ data.dsize = len;
+
+ len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
+ namerec->data.nb_flags,
+ (unsigned char)namerec->data.source,
+ (uint32)namerec->data.death_time,
+ (uint32)namerec->data.refresh_time,
+ id_low,
+ id_high,
+ (uint32)namerec->data.wins_ip.s_addr,
+ (uint32)namerec->data.wins_flags,
+ (uint32)namerec->data.num_ips );
+
+ for (i = 0; i < namerec->data.num_ips; i++) {
+ SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
+ }
+
+ return data;
+}
+
+/****************************************************************************
+ Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
+*****************************************************************************/
+
+static TDB_DATA name_to_key(const struct nmb_name *nmbname)
+{
+ static char keydata[sizeof(unstring) + 1];
+ TDB_DATA key;
+
+ memset(keydata, '\0', sizeof(keydata));
+
+ pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
+ strupper_m(keydata);
+ keydata[sizeof(unstring)] = nmbname->name_type;
+ key.dptr = keydata;
+ key.dsize = sizeof(keydata);
+
+ return key;
+}
+
+/****************************************************************************
+ Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
+ on the linked list. We will free this later in XXXX().
+*****************************************************************************/
+
+struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only)
+{
+ TDB_DATA data, key;
+ struct name_record *nr = NULL;
+ struct name_record *namerec = NULL;
+
+ if (!wins_tdb) {
+ return NULL;
+ }
+
+ key = name_to_key(nmbname);
+ data = tdb_fetch(wins_tdb, key);
+
+ if (data.dsize == 0) {
+ return NULL;
+ }
+
+ namerec = wins_record_to_name_record(key, data);
+ if (!namerec) {
+ return NULL;
+ }
+
+ /* Search for this name record on the list. Replace it if found. */
+
+ for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
+ if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
+ /* Delete it. */
+ DLIST_REMOVE(wins_server_subnet->namelist, nr);
+ SAFE_FREE(nr->data.ip);
+ SAFE_FREE(nr);
+ break;
+ }
+ }
+
+ DLIST_ADD(wins_server_subnet->namelist, namerec);
+ return namerec;
+}
+
+/****************************************************************************
+ Overwrite or add a given name in the wins.tdb.
+*****************************************************************************/
+
+static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
+{
+ TDB_DATA key, data;
+ int ret;
+
+ if (!wins_tdb) {
+ return False;
+ }
+
+ key = name_to_key(&namerec->name);
+ data = name_record_to_wins_record(namerec);
+
+ if (data.dptr == NULL) {
+ return False;
+ }
+
+ ret = tdb_store(wins_tdb, key, data, tdb_flag);
+
+ SAFE_FREE(data.dptr);
+ return (ret == 0) ? True : False;
+}
+
+/****************************************************************************
+ Overwrite a given name in the wins.tdb.
+*****************************************************************************/
+
+BOOL wins_store_changed_namerec(const struct name_record *namerec)
+{
+ return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
+}
+
+/****************************************************************************
+ Primary interface into creating and overwriting records in the wins.tdb.
+*****************************************************************************/
+
+BOOL add_name_to_wins_subnet(const struct name_record *namerec)
+{
+ return store_or_replace_wins_namerec(namerec, TDB_INSERT);
+}
+
+/****************************************************************************
+ Delete a given name in the tdb and remove the temporary malloc'ed data struct
+ on the linked list.
+*****************************************************************************/
+
+BOOL remove_name_from_wins_namelist(struct name_record *namerec)
+{
+ TDB_DATA key;
+ int ret;
+
+ if (!wins_tdb) {
+ return False;
+ }
+
+ key = name_to_key(&namerec->name);
+ ret = tdb_delete(wins_tdb, key);
+
+ DLIST_REMOVE(wins_server_subnet->namelist, namerec);
+ SAFE_FREE(namerec->data.ip);
+ ZERO_STRUCTP(namerec);
+ SAFE_FREE(namerec);
+ return (ret == 0) ? True : False;
+}
+
+/****************************************************************************
+ Dump out the complete namelist.
+*****************************************************************************/
+
+static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ struct name_record *namerec = NULL;
+ XFILE *fp = (XFILE *)state;
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ dump_name_record(namerec, fp);
+
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+ return 0;
+}
+
+void dump_wins_subnet_namelist(XFILE *fp)
+{
+ tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
+}
/****************************************************************************
Change the wins owner address in the record.
@@ -31,8 +331,6 @@
static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
{
- if (namerec==NULL)
- return;
namerec->data.wins_ip=wins_ip;
}
@@ -42,34 +340,35 @@ static void update_wins_owner(struct name_record *namerec, struct in_addr wins_i
static void update_wins_flag(struct name_record *namerec, int flags)
{
- if (namerec==NULL)
- return;
-
namerec->data.wins_flags=0x0;
/* if it's a group, it can be a normal or a special one */
if (namerec->data.nb_flags & NB_GROUP) {
- if (namerec->name.name_type==0x1C)
+ if (namerec->name.name_type==0x1C) {
namerec->data.wins_flags|=WINS_SGROUP;
- else
- if (namerec->data.num_ips>1)
+ } else {
+ if (namerec->data.num_ips>1) {
namerec->data.wins_flags|=WINS_SGROUP;
- else
+ } else {
namerec->data.wins_flags|=WINS_NGROUP;
+ }
+ }
} else {
/* can be unique or multi-homed */
- if (namerec->data.num_ips>1)
+ if (namerec->data.num_ips>1) {
namerec->data.wins_flags|=WINS_MHOMED;
- else
+ } else {
namerec->data.wins_flags|=WINS_UNIQUE;
+ }
}
/* the node type are the same bits */
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.death_time == PERMANENT_TTL) {
namerec->data.wins_flags|=WINS_STATIC;
+ }
/* and add the given bits */
namerec->data.wins_flags|=flags;
@@ -95,12 +394,14 @@ static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
*current_id = general_id;
- if (update)
+ if (update) {
general_id++;
+ }
}
/****************************************************************************
Possibly call the WINS hook external program when a WINS change is made.
+ Also stores the changed record back in the wins_tdb.
*****************************************************************************/
static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
@@ -110,7 +411,11 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt
char *p, *namestr;
int i;
- if (!cmd || !*cmd) return;
+ wins_store_changed_namerec(namerec);
+
+ if (!cmd || !*cmd) {
+ return;
+ }
for (p=namerec->name.name; *p; p++) {
if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
@@ -122,8 +427,9 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt
/* Use the name without the nametype (and scope) appended */
namestr = nmb_namestr(&namerec->name);
- if ((p = strchr(namestr, '<')))
+ if ((p = strchr(namestr, '<'))) {
*p = 0;
+ }
p = command;
p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
@@ -141,7 +447,6 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt
smbrun(command, NULL);
}
-
/****************************************************************************
Determine if this packet should be allocated to the WINS server.
*****************************************************************************/
@@ -157,8 +462,9 @@ BOOL packet_is_for_wins_server(struct packet_struct *packet)
}
/* Check for node status requests. */
- if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
+ if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
return False;
+ }
switch(nmb->header.opcode) {
/*
@@ -210,11 +516,13 @@ static int get_ttl_from_packet(struct nmb_packet *nmb)
{
int ttl = nmb->additional->ttl;
- if(ttl < lp_min_wins_ttl() )
+ if (ttl < lp_min_wins_ttl()) {
ttl = lp_min_wins_ttl();
+ }
- if(ttl > lp_max_wins_ttl() )
+ if (ttl > lp_max_wins_ttl()) {
ttl = lp_max_wins_ttl();
+ }
return ttl;
}
@@ -229,8 +537,19 @@ BOOL initialise_wins(void)
XFILE *fp;
pstring line;
- if(!lp_we_are_a_wins_server())
+ if(!lp_we_are_a_wins_server()) {
return True;
+ }
+
+ /* Open the wins.tdb. */
+ wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600);
+ if (!wins_tdb) {
+ DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
+ strerror(errno) ));
+ return False;
+ }
+
+ tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
add_samba_names_to_subnet(wins_server_subnet);
@@ -344,8 +663,9 @@ BOOL initialise_wins(void)
continue;
}
- if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
+ if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
nb_flags_str[strlen(nb_flags_str)-1] = '\0';
+ }
/* Netbios name. # divides the name from the type (hex): netbios#xx */
pstrcpy(name,name_str);
@@ -361,8 +681,9 @@ BOOL initialise_wins(void)
/* add all entries that have 60 seconds or more to live */
if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
- if(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));
@@ -370,7 +691,8 @@ BOOL initialise_wins(void)
(void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
ttl, REGISTER_NAME, num_ips, ip_list );
} else {
- DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
+ 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));
}
@@ -396,16 +718,21 @@ static void send_wins_wack_response(int ttl, struct packet_struct *p)
identical bytes from the requesting packet header. */
rdata[0] = (nmb->header.opcode & 0xF) << 3;
- if (nmb->header.nm_flags.authoritative && nmb->header.response)
+ if (nmb->header.nm_flags.authoritative && nmb->header.response) {
rdata[0] |= 0x4;
- if (nmb->header.nm_flags.trunc)
+ }
+ if (nmb->header.nm_flags.trunc) {
rdata[0] |= 0x2;
- if (nmb->header.nm_flags.recursion_desired)
+ }
+ if (nmb->header.nm_flags.recursion_desired) {
rdata[0] |= 0x1;
- if (nmb->header.nm_flags.recursion_available && nmb->header.response)
+ }
+ if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
rdata[1] |= 0x80;
- if (nmb->header.nm_flags.bcast)
+ }
+ if (nmb->header.nm_flags.bcast) {
rdata[1] |= 0x10;
+ }
reply_netbios_packet(p, /* Packet to reply to. */
0, /* Result code. */
@@ -545,7 +872,7 @@ void wins_process_name_refresh_request( struct subnet_record *subrec,
* names update the ttl and return success.
*/
if( (!group || (group && (question->name_type == 0x1c)))
- && find_ip_in_name_record(namerec, from_ip) ) {
+ && find_ip_in_name_record(namerec, from_ip) ) {
/*
* Update the ttl.
*/
@@ -584,6 +911,7 @@ void wins_process_name_refresh_request( struct subnet_record *subrec,
* 255.255.255.255 so we can't search for the IP address.
*/
update_name_ttl(namerec, ttl);
+ wins_hook("refresh", namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
return;
} else if(!group && (question->name_type == 0x1d)) {
@@ -669,16 +997,19 @@ static void wins_register_query_fail(struct subnet_record *subrec,
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) ) {
+ if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
+ ip_equal(rrec->packet->ip, *namerec->data.ip)) {
remove_name_from_namelist( subrec, namerec);
namerec = NULL;
}
- if(namerec == NULL)
+ if(namerec == NULL) {
wins_process_name_registration_request(subrec, orig_reg_packet);
- else
- DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
-querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
+ } else {
+ DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
+ "querying for name %s in order to replace it and this reply.\n",
+ nmb_namestr(question_name) ));
+ }
orig_reg_packet->locked = False;
free_packet(orig_reg_packet);
@@ -828,8 +1159,9 @@ to register name %s. Name already exists in WINS with source type %d.\n",
* Group names with type 0x1c are registered with individual IP addresses.
*/
- if(registering_group_name && (question->name_type != 0x1c))
+ if(registering_group_name && (question->name_type != 0x1c)) {
from_ip = *interpret_addr2("255.255.255.255");
+ }
/*
* Ignore all attempts to register a unique 0x1d name, although return success.
@@ -876,6 +1208,7 @@ to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
update_wins_owner(namerec, our_fake_ip);
}
update_name_ttl(namerec, ttl);
+ wins_hook("refresh", namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
return;
} else {
@@ -905,8 +1238,11 @@ already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
* reject without doing the query - we know we will reject it.
*/
- if ( namerec != NULL )
+ if ( namerec != NULL ) {
pull_ascii_nstring(name, sizeof(name), namerec->name.name);
+ } else {
+ name[0] = '\0';
+ }
if( is_myname(name) ) {
if(!ismyip(from_ip)) {
@@ -919,8 +1255,8 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
* It's one of our names and one of our IP's - update the ttl.
*/
update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
wins_hook("refresh", namerec, ttl);
+ send_wins_name_registration_response(0, ttl, p);
return;
}
}
@@ -940,8 +1276,8 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
&& ip_equal( namerec->data.ip[0], from_ip )
&& ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
update_name_ttl( namerec, ttl );
- send_wins_name_registration_response( 0, ttl, p );
wins_hook("refresh", namerec, ttl);
+ send_wins_name_registration_response( 0, ttl, p );
return;
}
@@ -1061,15 +1397,16 @@ a subsequent IP address.\n", nmb_namestr(question_name) ));
return;
}
- if(!find_ip_in_name_record(namerec, from_ip))
+ if(!find_ip_in_name_record(namerec, from_ip)) {
add_ip_to_name_record(namerec, from_ip);
+ }
get_global_id_and_update(&namerec->data.id, True);
update_wins_owner(namerec, our_fake_ip);
update_wins_flag(namerec, WINS_ACTIVE);
update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, orig_reg_packet);
wins_hook("add", namerec, ttl);
+ send_wins_name_registration_response(0, ttl, orig_reg_packet);
orig_reg_packet->locked = False;
free_packet(orig_reg_packet);
@@ -1237,18 +1574,17 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
* It's one of our names and one of our IP's. Ensure the IP is in the record and
* update the ttl. Update the version ID to force replication.
*/
+ update_name_ttl(namerec, ttl);
+
if(!find_ip_in_name_record(namerec, from_ip)) {
get_global_id_and_update(&namerec->data.id, True);
update_wins_owner(namerec, our_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);
}
- update_name_ttl(namerec, ttl);
+ wins_hook("refresh", namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
return;
}
@@ -1272,8 +1608,8 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
update_wins_flag(namerec, WINS_ACTIVE);
}
- send_wins_name_registration_response(0, ttl, p);
wins_hook("refresh", namerec, ttl);
+ send_wins_name_registration_response(0, ttl, p);
return;
}
@@ -1348,6 +1684,37 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
}
/***********************************************************************
+ Fetch all *<1b> names from the WINS db and store on the namelist.
+***********************************************************************/
+
+static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ struct name_record *namerec = NULL;
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ /* Filter out all non-1b names. */
+ if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ DLIST_ADD(wins_server_subnet->namelist, namerec);
+ return 0;
+}
+
+void fetch_all_active_wins_1b_names(void)
+{
+ tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
+}
+
+/***********************************************************************
Deal with the special name query for *<1b>.
***********************************************************************/
@@ -1365,10 +1732,13 @@ static void process_wins_dmb_query_request(struct subnet_record *subrec,
*/
num_ips = 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 )
+
+ fetch_all_active_wins_1b_names();
+
+ for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
+ if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
num_ips += namerec->data.num_ips;
+ }
}
if(num_ips == 0) {
@@ -1391,9 +1761,8 @@ static void process_wins_dmb_query_request(struct subnet_record *subrec,
*/
num_ips = 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) {
+ for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
+ if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
int i;
for(i = 0; i < namerec->data.num_ips; i++) {
set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
@@ -1465,8 +1834,9 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p,
prdata, /* data to send. */
reply_data_len); /* data length. */
- if(prdata != rdata)
+ if(prdata != rdata) {
SAFE_FREE(prdata);
+ }
}
/***********************************************************************
@@ -1548,7 +1918,7 @@ void wins_process_name_query_request(struct subnet_record *subrec,
DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
nmb_namestr(question) ));
- queue_dns_query(p, question, &namerec);
+ queue_dns_query(p, question);
return;
}
@@ -1680,6 +2050,7 @@ release name %s as this record is not active anymore.\n", nmb_namestr(question)
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)));
+ wins_hook("delete", namerec, 0);
send_wins_name_release_response(0, p);
return;
}
@@ -1689,118 +2060,235 @@ release name %s as this record is not active anymore.\n", nmb_namestr(question)
* 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);
+ send_wins_name_release_response(0, p);
}
/*******************************************************************
WINS time dependent processing.
******************************************************************/
+static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ time_t t = *(time_t *)state;
+ BOOL store_record = False;
+ struct name_record *namerec = NULL;
+ struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
+ if( namerec->data.source == SELF_NAME ) {
+ DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
+ wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
+ namerec->data.death_time += 300;
+ store_record = True;
+ goto done;
+ } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
+ DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
+ nmb_namestr(&namerec->name)));
+ remove_name_from_wins_namelist(namerec );
+ goto done;
+ }
+
+ /* handle records, samba is the wins owner */
+ if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
+ 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;
+ DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
+ nmb_namestr(&namerec->name)));
+ store_record = True;
+ goto done;
+ case WINS_RELEASED:
+ namerec->data.wins_flags&=~WINS_STATE_MASK;
+ namerec->data.wins_flags|=WINS_TOMBSTONED;
+ namerec->data.death_time = t + EXTINCTION_TIMEOUT;
+ get_global_id_and_update(&namerec->data.id, True);
+ DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
+ nmb_namestr(&namerec->name)));
+ store_record = True;
+ goto done;
+ case WINS_TOMBSTONED:
+ DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
+ nmb_namestr(&namerec->name)));
+ remove_name_from_wins_namelist(namerec );
+ goto done;
+ }
+ } else {
+ switch (namerec->data.wins_flags | WINS_STATE_MASK) {
+ case WINS_ACTIVE:
+ /* 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;
+ DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
+ nmb_namestr(&namerec->name)));
+ store_record = True;
+ goto done;
+ case WINS_TOMBSTONED:
+ DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
+ nmb_namestr(&namerec->name)));
+ remove_name_from_wins_namelist(namerec );
+ goto done;
+ case WINS_RELEASED:
+ DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
+we are not the wins owner !\n", nmb_namestr(&namerec->name)));
+ goto done;
+ }
+ }
+ }
+
+ done:
+
+ if (store_record) {
+ wins_store_changed_namerec(namerec);
+ }
+
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+
+ return 0;
+}
+
+/*******************************************************************
+ Time dependent wins processing.
+******************************************************************/
+
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");
+ struct name_record *nr = NULL;
+ struct name_record *nrnext = NULL;
- if (!lasttime)
+ if (!lasttime) {
lasttime = t;
- if (t - lasttime < 20)
+ }
+ if (t - lasttime < 20) {
return;
+ }
+
+ if(!lp_we_are_a_wins_server()) {
+ lasttime = t;
+ return;
+ }
+
+ tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
+
+
+ /* Delete all temporary name records on the wins subnet linked list. */
+ for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
+ nrnext = nr->next;
+ DLIST_REMOVE(wins_server_subnet->namelist, nr);
+ SAFE_FREE(nr->data.ip);
+ SAFE_FREE(nr);
+ }
+
+ wins_write_database(t, True);
lasttime = t;
+}
- if(!lp_we_are_a_wins_server())
- return;
+/*******************************************************************
+ Write out one record.
+******************************************************************/
- for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
- namerec;
- 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.source == SELF_NAME ) {
- DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n",
- wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
- namerec->data.death_time += 300;
- namerec->subnet->namelist_changed = True;
- continue;
- } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
- DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n",
- nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- continue;
- }
+void wins_write_name_record(struct name_record *namerec, XFILE *fp)
+{
+ int i;
+ struct tm *tm;
- /* handle records, samba is the wins owner */
- if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
- 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;
- 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;
- get_global_id_and_update(&namerec->data.id, True);
- DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
- break;
- case WINS_TOMBSTONED:
- DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- break;
- }
- } else {
- switch (namerec->data.wins_flags | WINS_STATE_MASK) {
- case WINS_ACTIVE:
- /* 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;
- 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)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- break;
- case WINS_RELEASED:
- DEBUG(0,("initiate_wins_processing: %s is in released state and\
-we are not the wins owner !\n", nmb_namestr(&namerec->name)));
- break;
- }
- }
+ DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
+
+ if( namerec->data.death_time != PERMANENT_TTL ) {
+ char *ts, *nl;
+ tm = localtime(&namerec->data.death_time);
+ ts = asctime(tm);
+ nl = strrchr( ts, '\n' );
+ if( NULL != nl ) {
+ *nl = '\0';
}
+ DEBUGADD(4,("TTL = %s ", ts ));
+ } else {
+ DEBUGADD(4,("TTL = PERMANENT "));
+ }
+
+ for (i = 0; i < namerec->data.num_ips; i++) {
+ DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
}
+ DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
- if(wins_server_subnet->namelist_changed)
- wins_write_database(True);
+ if( namerec->data.source == REGISTER_NAME ) {
+ unstring name;
+ pull_ascii_nstring(name, sizeof(name), namerec->name.name);
+ x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
+ (int)namerec->data.death_time);
- wins_server_subnet->namelist_changed = False;
+ for (i = 0; i < namerec->data.num_ips; i++)
+ x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
+ x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
+ }
}
/*******************************************************************
Write out the current WINS database.
******************************************************************/
-void wins_write_database(BOOL background)
+static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ struct name_record *namerec = NULL;
+ XFILE *fp = (XFILE *)state;
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ wins_write_name_record(namerec, fp);
+
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+ return 0;
+}
+
+
+void wins_write_database(time_t t, BOOL background)
{
- struct name_record *namerec;
+ static time_t last_write_time = 0;
pstring fname, fnamenew;
XFILE *fp;
- if(!lp_we_are_a_wins_server())
+ if (background) {
+ if (!last_write_time) {
+ last_write_time = t;
+ }
+ if (t - last_write_time < 120) {
+ return;
+ }
+
+ }
+
+ if(!lp_we_are_a_wins_server()) {
return;
+ }
/* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
if (background) {
@@ -1808,6 +2296,11 @@ void wins_write_database(BOOL background)
if (sys_fork()) {
return;
}
+ if (tdb_reopen(wins_tdb)) {
+ DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
+ strerror(errno)));
+ return;
+ }
}
slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
@@ -1826,41 +2319,8 @@ void wins_write_database(BOOL background)
x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
- for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
- int i;
- struct tm *tm;
-
- DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
-
- if( namerec->data.death_time != PERMANENT_TTL ) {
- char *ts, *nl;
-
- tm = localtime(&namerec->data.death_time);
- ts = asctime(tm);
- nl = strrchr( ts, '\n' );
- if( NULL != nl )
- *nl = '\0';
- DEBUGADD(4,("TTL = %s ", ts ));
- } else {
- DEBUGADD(4,("TTL = PERMANENT "));
- }
+ tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
- for (i = 0; i < namerec->data.num_ips; i++)
- DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
- DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
-
- if( namerec->data.source == REGISTER_NAME ) {
- unstring name;
- pull_ascii_nstring(name, sizeof(name), namerec->name.name);
- x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
- (int)namerec->data.death_time);
-
- for (i = 0; i < namerec->data.num_ips; i++)
- x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
- x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
- }
- }
-
x_fclose(fp);
chmod(fnamenew,0644);
unlink(fname);
@@ -1870,6 +2330,8 @@ void wins_write_database(BOOL background)
}
}
+#if 0
+ Until winsrepl is done.
/****************************************************************************
Process a internal Samba message receiving a wins record.
***************************************************************************/
@@ -1885,8 +2347,9 @@ void nmbd_wins_new_entry(int msg_type, struct process_id src,
struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
int i;
- if (buf==NULL)
+ if (buf==NULL) {
return;
+ }
/* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
record=(WINS_RECORD *)buf;
@@ -1900,8 +2363,15 @@ void nmbd_wins_new_entry(int msg_type, struct process_id src,
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)));
- 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);
+ 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);
+
if (new_namerec!=NULL) {
update_wins_owner(new_namerec, record->wins_ip);
update_wins_flag(new_namerec, record->wins_flags);
@@ -2019,3 +2489,4 @@ void nmbd_wins_new_entry(int msg_type, struct process_id src,
}
}
+#endif