diff options
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rw-r--r-- | source3/lib/wins_srv.c | 118 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 2 | ||||
-rw-r--r-- | source3/nmbd/nmbd_subnetdb.c | 17 | ||||
-rw-r--r-- | source3/nsswitch/wins.c | 6 |
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; } |