summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/include/proto.h17
-rw-r--r--source3/lib/wins_srv.c218
-rw-r--r--source3/libsmb/namequery.c6
-rw-r--r--source3/nmbd/nmbd_subnetdb.c6
-rw-r--r--source3/nsswitch/wins.c2
-rw-r--r--source3/param/loadparm.c16
7 files changed, 250 insertions, 17 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 07a6fbbe94..fa80957aac 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -103,7 +103,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/interfaces.o lib/pidfile.o lib/replace.o \
lib/signal.o lib/slprintf.o lib/system.o lib/doscalls.o lib/time.o \
lib/ufc.o lib/genrand.o lib/username.o lib/access.o lib/smbrun.o \
- lib/bitmap.o lib/crc32.o lib/snprintf.o \
+ lib/bitmap.o lib/crc32.o lib/snprintf.o lib/wins_srv.o \
lib/util_array.o lib/util_str.o lib/util_sid.o \
lib/util_unistr.o lib/util_file.o \
lib/util.o lib/util_sock.o lib/util_sec.o smbd/ssl.o \
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 2335b8f07d..1b7225d6b9 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -410,16 +410,6 @@ char **file_lines_pload(char *syscmd, int *numlines);
void file_lines_free(char **lines);
void file_lines_slashcont(char **lines);
-/*The following definitions come from lib/util_list.c */
-
-BOOL copy_policy_hnd (POLICY_HND *dest, const POLICY_HND *src);
-BOOL compare_rpc_hnd_node(const RPC_HND_NODE *x,
- const RPC_HND_NODE *y);
-BOOL RpcHndList_set_connection(const POLICY_HND *hnd,
- struct cli_connection *con);
-BOOL RpcHndList_del_connection(const POLICY_HND *hnd);
-struct cli_connection* RpcHndList_get_connection(const POLICY_HND *hnd);
-
/*The following definitions come from lib/util_seaccess.c */
BOOL se_access_check(SEC_DESC *sd, struct current_user *user,
@@ -603,6 +593,13 @@ void split_at_last_component_w(smb_ucs2_t *path, smb_ucs2_t *front, smb_ucs2_t s
smb_ucs2_t *octal_string_w(int i);
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 );
+unsigned long wins_srv_count( void );
+
/*The following definitions come from libsmb/cliconnect.c */
BOOL cli_session_setup(struct cli_state *cli,
diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c
new file mode 100644
index 0000000000..e84ac342f5
--- /dev/null
+++ b/source3/lib/wins_srv.c
@@ -0,0 +1,218 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Samba utility functions
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/* -------------------------------------------------------------------------- **
+ * Discussion...
+ *
+ * This module implements WINS failover.
+ *
+ * Microsoft's WINS servers provide a feature called WINS replication,
+ * which synchronises the WINS name databases between two or more servers.
+ * This means that the two servers can be used interchangably (more or
+ * less). WINS replication is particularly useful if you are trying to
+ * synchronise the WINS namespace between servers in remote locations, or
+ * if your WINS servers tend to crash a lot.
+ *
+ * WINS failover allows the client to 'switch' to a different WINS server
+ * if the current WINS server mysteriously disappears. On Windows
+ * systems, this is typically represented as 'primary' and 'secondary'
+ * WINS servers.
+ *
+ * Failover only works if the WINS servers are synced. If they are not,
+ * then
+ * a) if the primary WINS server never fails the client will never 'see'
+ * the secondary (or tertiary or...) WINS server name space.
+ * b) if the primary *does* fail, the client will be entering an
+ * unfamiliar namespace. The client itself will not be registered in
+ * that namespace and any names which match names in the previous
+ * space will likely resolve to different host IP addresses.
+ *
+ * One key thing to remember regarding WINS failover is that Samba does
+ * not (yet) implement WINS replication. For those interested, sniff port
+ * 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).
+ *
+ * Multi-membership is a little wierd. The idea is that the client can
+ * register itself with multiple non-replicated WINS servers, and query
+ * all of those servers (in a prescribed sequence) to resolve a name.
+ *
+ * The implications of multi-membership are not quite clear. Worth
+ * trying, I suppose. Changes will be needed in the name query and
+ * registration code to accomodate this feature. Also, there will need to
+ * be some sort of syntax extension for the 'wins server' parameter in
+ * smb.conf. I'm thinking that a colon could be used as a separator.
+ *
+ * Of course, for each WINS namespace there might be multiple, synced WINS
+ * servers. The change to this module would likely be the addition of a
+ * linked list of linked lists.
+ *
+ * crh@samba.org
+ */
+
+/* -------------------------------------------------------------------------- **
+ * Defines...
+ *
+ * NECROMANCYCLE - The dead server retry period, in seconds. When a WINS
+ * server is declared dead, wait this many seconds before
+ * attempting to communicate with it.
+ */
+
+#define NECROMANCYCLE 600 /* 600 seconds == 10 minutes. */
+
+/* -------------------------------------------------------------------------- **
+ * Typedefs...
+ */
+
+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. */
+ } list_entry;
+
+/* -------------------------------------------------------------------------- **
+ * Private, static variables.
+ */
+
+static ubi_slNewList( wins_srv_list );
+
+/* -------------------------------------------------------------------------- **
+ * Functions...
+ */
+
+
+BOOL wins_srv_load_list( char *src )
+ /* ------------------------------------------------------------------------ **
+ * Create or recreate the linked list of failover WINS servers.
+ */
+ {
+ list_entry *entry;
+ char *p = src;
+ pstring wins_id_bufr;
+ unsigned long count;
+
+ /* Empty the list. */
+ while( NULL != (entry =(list_entry *)ubi_slRemHead( wins_srv_list )) )
+ {
+ if( entry->server )
+ free( entry->server );
+ free( entry );
+ }
+ (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") );
+ while( next_token( &p, wins_id_bufr, LIST_SEP, sizeof( wins_id_bufr ) ) )
+ {
+ entry = (list_entry *)malloc( sizeof( list_entry ) );
+ if( NULL == entry )
+ {
+ DEBUG( 0, ("wins_srv_load_list(): malloc(list_entry) failed.\n") );
+ }
+ else
+ {
+ entry->mourning = 0;
+ if( NULL == (entry->server = strdup( wins_id_bufr )) )
+ {
+ free( entry );
+ DEBUG( 0, ("wins_srv_load_list(): strdup(\"%s\") failed.\n", wins_id_bufr) );
+ }
+ else
+ {
+ /* Add server to list. */
+ (void)ubi_slAddTail( wins_srv_list, entry );
+ DEBUGADD( 4, ("\t\t%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" ) );
+
+ return( (count > 0) ? True : False );
+ } /* wins_srv_load_list */
+
+
+char *wins_srv( 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) )
+ {
+ entry = (list_entry *)ubi_slNext( entry );
+ if( entry->mourning < coldest->mourning )
+ coldest = entry;
+ }
+
+ /* 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") );
+ }
+
+ /* The list could be empty. Check it. */
+ if( NULL == entry )
+ return( NULL );
+ return( entry->server );
+ } /* wins_srv */
+
+
+void wins_srv_died( char *boothill )
+ /* ------------------------------------------------------------------------ **
+ * Called to indicate that a specific WINS server has died.
+ */
+ {
+ list_entry *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 ) )
+ {
+ entry->mourning = time(NULL) + NECROMANCYCLE;
+ DEBUG( 2, ("wins_srv: WINS server %s appears to be down.\n", boothill) );
+ return;
+ }
+ entry = (list_entry *)ubi_slNext( entry );
+ }
+ } /* wins_srv_died */
+
+
+unsigned long wins_srv_count( void )
+ /* ------------------------------------------------------------------------ **
+ * Return the total number of entries in the list, dead or alive.
+ */
+ {
+ return( ubi_slCount( wins_srv_list ) );
+ } /* wins_srv_count */
+
+/* ========================================================================== */
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 193731768f..0237a9752f 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -529,12 +529,12 @@ static BOOL resolve_wins(const char *name, int name_type,
DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
- if(!*lp_wins_server()) {
- DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS server present.\n"));
+ if( wins_srv_count() < 1 ) {
+ DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
return False;
}
- wins_ip = *interpret_addr2(lp_wins_server());
+ wins_ip = *interpret_addr2( wins_srv() );
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 330be4057f..57f937148e 100644
--- a/source3/nmbd/nmbd_subnetdb.c
+++ b/source3/nmbd/nmbd_subnetdb.c
@@ -271,12 +271,16 @@ BOOL create_subnets(void)
* get the ip address of it here. If we are the WINS server then
* set the unicast subnet address to be the first of our own real
* addresses.
+ *
+ * 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.
*/
if(*lp_wins_server())
{
struct in_addr real_wins_ip;
- real_wins_ip = *interpret_addr2(lp_wins_server());
+ real_wins_ip = *interpret_addr2( wins_srv() );
if (!zero_ip(real_wins_ip))
{
diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c
index f8a05a9fbf..41b71c64bb 100644
--- a/source3/nsswitch/wins.c
+++ b/source3/nsswitch/wins.c
@@ -56,7 +56,7 @@ struct in_addr *lookup_backend(const char *name, int *count)
set_socket_options(fd,"SO_BROADCAST");
- p = lp_wins_server();
+ p = wins_srv();
if (p && *p) {
ret = name_query(fd,name,0x20,False,True, *interpret_addr2(p), count);
goto out;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 3650d4edd3..61e38bea60 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -509,6 +509,7 @@ static BOOL handle_vfs_object(char *pszParmValue, char **ptr);
static BOOL handle_source_env(char *pszParmValue, char **ptr);
static BOOL handle_netbios_name(char *pszParmValue, char **ptr);
static BOOL handle_winbind_id(char *pszParmValue, char **ptr);
+static BOOL handle_wins_server_list(char *pszParmValue, char **ptr);
static void set_server_role(void);
static void set_default_server_announce_type(void);
@@ -863,7 +864,7 @@ static struct parm_struct parm_table[] = {
{"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, 0},
{"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, 0},
- {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL, NULL, FLAG_BASIC},
+ {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, handle_wins_server_list, NULL, FLAG_BASIC},
{"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC},
{"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, 0},
@@ -2373,6 +2374,19 @@ static BOOL handle_winbind_id(char *pszParmValue, char **ptr)
}
/***************************************************************************
+ Handle the WINS SERVER list
+***************************************************************************/
+static BOOL handle_wins_server_list( char *pszParmValue, char **ptr )
+ {
+ if( !wins_srv_load_list( pszParmValue ) )
+ return( False ); /* Parse failed. */
+
+ string_set( ptr, pszParmValue );
+ return( True );
+ }
+
+
+/***************************************************************************
initialise a copymap
***************************************************************************/
static void init_copymap(service * pservice)