summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorChristopher R. Hertel <crh@samba.org>2000-07-19 05:32:43 +0000
committerChristopher R. Hertel <crh@samba.org>2000-07-19 05:32:43 +0000
commit3c9e410c340d53897a3f97243d8286812704f6c0 (patch)
tree4198a4ba079626201d4fec3ce29f680b65331596 /source3
parentb35f21fb3a19417e2aab82a573ff121a086b224c (diff)
downloadsamba-3c9e410c340d53897a3f97243d8286812704f6c0.tar.gz
samba-3c9e410c340d53897a3f97243d8286812704f6c0.tar.bz2
samba-3c9e410c340d53897a3f97243d8286812704f6c0.zip
Instead of handing back a string (which might be a DNS name or an IP
string), the wins_srv module now hands back a struct in_addr when it's called. It caches the IP address once it has been looked up. The IP is cleared (and must be looked up again) if the 'wins server' parameter is reread, or if the node is marked 'dead'. A dead node will not be re-tried for 10 minutes (per a #define in wins_srv.c). As it was, the code was reading the WINS server name or IP directly from lp_wins_server. That's okay, except that if the value was expressed as a name, then a DNS lookup would be done every time the client wanted to talk to the server. I still need to work out the implications of failover regarding the 'unicast subnet' list. Chris -)----- (This used to be commit 73aa188320fd3bf10b5dfc057323f40aff2c13bd)
Diffstat (limited to 'source3')
-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;
}