summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h4
-rw-r--r--source3/lib/wins_srv.c118
-rw-r--r--source3/libsmb/namequery.c2
-rw-r--r--source3/nmbd/nmbd_subnetdb.c17
-rw-r--r--source3/nsswitch/wins.c6
5 files changed, 99 insertions, 48 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 1b7225d6b9..e0ff128368 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -596,8 +596,8 @@ smb_ucs2_t *string_truncate_w(smb_ucs2_t *s, size_t length);
/*The following definitions come from lib/wins_srv.c */
BOOL wins_srv_load_list( char *src );
-char *wins_srv( void );
-void wins_srv_died( char *boothill );
+struct in_addr wins_srv_ip( void );
+void wins_srv_died( struct in_addr boothill_ip );
unsigned long wins_srv_count( void );
/*The following definitions come from libsmb/cliconnect.c */
diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c
index e84ac342f5..3a4489ce85 100644
--- a/source3/lib/wins_srv.c
+++ b/source3/lib/wins_srv.c
@@ -1,8 +1,9 @@
/*
Unix SMB/Netbios implementation.
- Version 1.9.
+ Version 2.
Samba utility functions
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Christopher R. Hertel 2000
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
@@ -52,8 +53,7 @@
* 42 (TCP? UDP? ...dunno off hand) and see what two MS WINS servers do.
*
* At this stage, only failover is implemented. The next thing is to add
- * support for multi-WINS server registration and query
- * (multi-membership).
+ * support for multi-WINS server registration and query (multi-membership).
*
* Multi-membership is a little wierd. The idea is that the client can
* register itself with multiple non-replicated WINS servers, and query
@@ -88,9 +88,10 @@
typedef struct
{
- ubi_slNode node; /* Linked list node structure. */
- time_t mourning; /* If greater than current time server is dead, Jim. */
- char *server; /* DNS name or IP of NBNS server to query. */
+ ubi_slNode node; /* Linked list node structure. */
+ time_t mourning; /* If > current time then server is dead, Jim. */
+ char *server; /* DNS name or IP of NBNS server to query. */
+ struct in_addr ip_addr; /* Cache translated IP. */
} list_entry;
/* -------------------------------------------------------------------------- **
@@ -107,6 +108,18 @@ static ubi_slNewList( wins_srv_list );
BOOL wins_srv_load_list( char *src )
/* ------------------------------------------------------------------------ **
* Create or recreate the linked list of failover WINS servers.
+ *
+ * Input: src - String of DNS names and/or IP addresses delimited by the
+ * characters listed in LIST_SEP (see include/local.h).
+ *
+ * Output: True if at least one name or IP could be parsed out of the
+ * list, else False.
+ *
+ * Notes: There is no syntax checking done on the names or IPs. We do
+ * check to see if the field is an IP, in which case we copy it
+ * to the ip_addr field of the entry. Don't bother to to a host
+ * name lookup on all names now. They're done as needed in
+ * wins_srv_ip().
*/
{
list_entry *entry;
@@ -124,7 +137,7 @@ BOOL wins_srv_load_list( char *src )
(void)ubi_slInitList( wins_srv_list ); /* shouldn't be needed */
/* Parse out the DNS names or IP addresses of the WINS servers. */
- DEBUG( 4, ("wins_srv: Building WINS server list:\n") );
+ DEBUG( 4, ("wins_srv_load_list(): Building WINS server list:\n") );
while( next_token( &p, wins_id_bufr, LIST_SEP, sizeof( wins_id_bufr ) ) )
{
entry = (list_entry *)malloc( sizeof( list_entry ) );
@@ -143,67 +156,86 @@ BOOL wins_srv_load_list( char *src )
else
{
/* Add server to list. */
+ if( is_ipaddress( wins_id_bufr ) )
+ entry->ip_addr = *interpret_addr2( wins_id_bufr );
+ else
+ entry->ip_addr = *interpret_addr2( "0.0.0.0" );
(void)ubi_slAddTail( wins_srv_list, entry );
- DEBUGADD( 4, ("\t\t%s,\n", wins_id_bufr) );
+ DEBUGADD( 4, ("%s,\n", wins_id_bufr) );
}
}
}
count = ubi_slCount( wins_srv_list );
- DEBUGADD( 4, ( "\t\t%d WINS server%s listed.\n", count, (1==count)?"":"s" ) );
+ DEBUGADD( 4, ( "%d WINS server%s listed.\n", count, (1==count)?"":"s" ) );
return( (count > 0) ? True : False );
} /* wins_srv_load_list */
-char *wins_srv( void )
+struct in_addr wins_srv_ip( void )
/* ------------------------------------------------------------------------ **
*/
{
time_t now = time(NULL);
list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
- list_entry *coldest = entry;
- /* Go through the list. Look for the first live entry. */
- while( (NULL != entry) && (now < entry->mourning) )
+ while( NULL != entry )
{
- entry = (list_entry *)ubi_slNext( entry );
- if( entry->mourning < coldest->mourning )
- coldest = entry;
- }
+ if( now >= entry->mourning ) /* Found a live one. */
+ {
+ /* If we don't have the IP, look it up. */
+ if( zero_ip( entry->ip_addr ) )
+ entry->ip_addr = *interpret_addr2( entry->server );
- /* If they were all dead, then return the one that's been dead longest. */
- if( NULL == entry )
- {
- entry = coldest;
- DEBUG( 4, ("wins_srv: All WINS servers appear to have failed.\n") );
+ /* If we still don't have the IP then kill it, else return it. */
+ if( zero_ip( entry->ip_addr ) )
+ entry->mourning = now + NECROMANCYCLE;
+ else
+ return( entry->ip_addr );
+ }
+ entry = (list_entry *)ubi_slNext( entry );
}
- /* The list could be empty. Check it. */
- if( NULL == entry )
- return( NULL );
- return( entry->server );
- } /* wins_srv */
+ /* If there are no live entries, return the zero IP. */
+ return( *interpret_addr2( "0.0.0.0" ) );
+ } /* wins_srv_ip */
-void wins_srv_died( char *boothill )
+void wins_srv_died( struct in_addr boothill_ip )
/* ------------------------------------------------------------------------ **
* Called to indicate that a specific WINS server has died.
*/
{
- list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
+ list_entry *entry;
+
+ if( zero_ip( boothill_ip ) )
+ {
+ DEBUG( 4, ("wins_srv_died(): Got request to mark zero IP down.\n") );
+ return;
+ }
+ entry = (list_entry *)ubi_slFirst( wins_srv_list );
while( NULL != entry )
{
- /* Match based on server ID [DNS name or IP]. */
- if( 0 == strcmp( boothill, entry->server ) )
+ /* Match based on IP. */
+ if( ip_equal( boothill_ip, entry->ip_addr ) )
{
entry->mourning = time(NULL) + NECROMANCYCLE;
- DEBUG( 2, ("wins_srv: WINS server %s appears to be down.\n", boothill) );
+ entry->ip_addr.s_addr = 0; /* Force a re-lookup at re-birth. */
+ DEBUG( 2, ( "wins_srv_died(): WINS server %s appears to be down.\n",
+ entry->server ) );
return;
}
entry = (list_entry *)ubi_slNext( entry );
}
+
+ if( DEBUGLVL( 1 ) )
+ {
+ dbgtext( "wins_srv_died(): Could not mark WINS server %s down.\n",
+ inet_ntoa( boothill_ip ) );
+ dbgtext( "Address not found in server list.\n" );
+ }
} /* wins_srv_died */
@@ -212,7 +244,27 @@ unsigned long wins_srv_count( void )
* Return the total number of entries in the list, dead or alive.
*/
{
- return( ubi_slCount( wins_srv_list ) );
+ unsigned long count = ubi_slCount( wins_srv_list );
+
+ if( DEBUGLVL( 8 ) )
+ {
+ list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
+ time_t now = time(NULL);
+
+ dbgtext( "wins_srv_count: WINS status: %ld servers.\n", count );
+ while( NULL != entry )
+ {
+ dbgtext( " %s <%s>: ", entry->server, inet_ntoa( entry->ip_addr ) );
+ if( now >= entry->mourning )
+ dbgtext( "alive\n" );
+ else
+ dbgtext( "dead for %d more seconds\n", (int)(entry->mourning - now) );
+
+ entry = (list_entry *)ubi_slNext( entry );
+ }
+ }
+
+ return( count );
} /* wins_srv_count */
/* ========================================================================== */
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 0237a9752f..6550d55206 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -534,7 +534,7 @@ static BOOL resolve_wins(const char *name, int name_type,
return False;
}
- wins_ip = *interpret_addr2( wins_srv() );
+ wins_ip = wins_srv_ip();
wins_ismyip = ismyip(wins_ip);
DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c
index 57f937148e..3bad3f9568 100644
--- a/source3/nmbd/nmbd_subnetdb.c
+++ b/source3/nmbd/nmbd_subnetdb.c
@@ -274,13 +274,13 @@ BOOL create_subnets(void)
*
* NOTE: I'm not sure of the implications of WINS server failover
* on this bit of code. Because of failover, the WINS
- * server address can change.
+ * server address can change. crh
*/
if(*lp_wins_server())
{
struct in_addr real_wins_ip;
- real_wins_ip = *interpret_addr2( wins_srv() );
+ real_wins_ip = wins_srv_ip();
if (!zero_ip(real_wins_ip))
{
@@ -288,9 +288,10 @@ BOOL create_subnets(void)
}
else
{
- /* The smb.conf's wins server parameter MUST be a host_name
- or an ip_address. */
- DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
+ /* wins_srv_ip() can return a zero IP if all servers are
+ * either down or incorrectly entered in smb.conf. crh
+ */
+ DEBUG(0,("No 'live' WINS servers found. Check 'wins server' parameter.\n"));
return False;
}
}
@@ -330,9 +331,9 @@ BOOL create_subnets(void)
if (lp_we_are_a_wins_server())
{
- if((wins_server_subnet = make_subnet("WINS_SERVER_SUBNET",
- WINS_SERVER_SUBNET,
- ipzero, ipzero, ipzero)) == NULL)
+ if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
+ WINS_SERVER_SUBNET,
+ ipzero, ipzero, ipzero )) == NULL )
return False;
}
diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c
index 41b71c64bb..ca0f22e3a6 100644
--- a/source3/nsswitch/wins.c
+++ b/source3/nsswitch/wins.c
@@ -36,7 +36,6 @@ struct in_addr *lookup_backend(const char *name, int *count)
int fd;
static int initialised;
struct in_addr *ret;
- char *p;
int j;
if (!initialised) {
@@ -56,9 +55,8 @@ struct in_addr *lookup_backend(const char *name, int *count)
set_socket_options(fd,"SO_BROADCAST");
- p = wins_srv();
- if (p && *p) {
- ret = name_query(fd,name,0x20,False,True, *interpret_addr2(p), count);
+ if( !zero_ip( wins_ip ) ) {
+ ret = name_query( fd, name, 0x20, False, True, wins_src_ip(), count );
goto out;
}