First cut toward adding WINS server failover.
[Samba/reqa.git] / source3 / lib / wins_srv.c
blobe84ac342f5d094ce7e81ce037589e87e840c3bf5
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 /* -------------------------------------------------------------------------- **
25 * Discussion...
27 * This module implements WINS failover.
29 * Microsoft's WINS servers provide a feature called WINS replication,
30 * which synchronises the WINS name databases between two or more servers.
31 * This means that the two servers can be used interchangably (more or
32 * less). WINS replication is particularly useful if you are trying to
33 * synchronise the WINS namespace between servers in remote locations, or
34 * if your WINS servers tend to crash a lot.
36 * WINS failover allows the client to 'switch' to a different WINS server
37 * if the current WINS server mysteriously disappears. On Windows
38 * systems, this is typically represented as 'primary' and 'secondary'
39 * WINS servers.
41 * Failover only works if the WINS servers are synced. If they are not,
42 * then
43 * a) if the primary WINS server never fails the client will never 'see'
44 * the secondary (or tertiary or...) WINS server name space.
45 * b) if the primary *does* fail, the client will be entering an
46 * unfamiliar namespace. The client itself will not be registered in
47 * that namespace and any names which match names in the previous
48 * space will likely resolve to different host IP addresses.
50 * One key thing to remember regarding WINS failover is that Samba does
51 * not (yet) implement WINS replication. For those interested, sniff port
52 * 42 (TCP? UDP? ...dunno off hand) and see what two MS WINS servers do.
54 * At this stage, only failover is implemented. The next thing is to add
55 * support for multi-WINS server registration and query
56 * (multi-membership).
58 * Multi-membership is a little wierd. The idea is that the client can
59 * register itself with multiple non-replicated WINS servers, and query
60 * all of those servers (in a prescribed sequence) to resolve a name.
62 * The implications of multi-membership are not quite clear. Worth
63 * trying, I suppose. Changes will be needed in the name query and
64 * registration code to accomodate this feature. Also, there will need to
65 * be some sort of syntax extension for the 'wins server' parameter in
66 * smb.conf. I'm thinking that a colon could be used as a separator.
68 * Of course, for each WINS namespace there might be multiple, synced WINS
69 * servers. The change to this module would likely be the addition of a
70 * linked list of linked lists.
72 * crh@samba.org
75 /* -------------------------------------------------------------------------- **
76 * Defines...
78 * NECROMANCYCLE - The dead server retry period, in seconds. When a WINS
79 * server is declared dead, wait this many seconds before
80 * attempting to communicate with it.
83 #define NECROMANCYCLE 600 /* 600 seconds == 10 minutes. */
85 /* -------------------------------------------------------------------------- **
86 * Typedefs...
89 typedef struct
91 ubi_slNode node; /* Linked list node structure. */
92 time_t mourning; /* If greater than current time server is dead, Jim. */
93 char *server; /* DNS name or IP of NBNS server to query. */
94 } list_entry;
96 /* -------------------------------------------------------------------------- **
97 * Private, static variables.
100 static ubi_slNewList( wins_srv_list );
102 /* -------------------------------------------------------------------------- **
103 * Functions...
107 BOOL wins_srv_load_list( char *src )
108 /* ------------------------------------------------------------------------ **
109 * Create or recreate the linked list of failover WINS servers.
112 list_entry *entry;
113 char *p = src;
114 pstring wins_id_bufr;
115 unsigned long count;
117 /* Empty the list. */
118 while( NULL != (entry =(list_entry *)ubi_slRemHead( wins_srv_list )) )
120 if( entry->server )
121 free( entry->server );
122 free( entry );
124 (void)ubi_slInitList( wins_srv_list ); /* shouldn't be needed */
126 /* Parse out the DNS names or IP addresses of the WINS servers. */
127 DEBUG( 4, ("wins_srv: Building WINS server list:\n") );
128 while( next_token( &p, wins_id_bufr, LIST_SEP, sizeof( wins_id_bufr ) ) )
130 entry = (list_entry *)malloc( sizeof( list_entry ) );
131 if( NULL == entry )
133 DEBUG( 0, ("wins_srv_load_list(): malloc(list_entry) failed.\n") );
135 else
137 entry->mourning = 0;
138 if( NULL == (entry->server = strdup( wins_id_bufr )) )
140 free( entry );
141 DEBUG( 0, ("wins_srv_load_list(): strdup(\"%s\") failed.\n", wins_id_bufr) );
143 else
145 /* Add server to list. */
146 (void)ubi_slAddTail( wins_srv_list, entry );
147 DEBUGADD( 4, ("\t\t%s,\n", wins_id_bufr) );
152 count = ubi_slCount( wins_srv_list );
153 DEBUGADD( 4, ( "\t\t%d WINS server%s listed.\n", count, (1==count)?"":"s" ) );
155 return( (count > 0) ? True : False );
156 } /* wins_srv_load_list */
159 char *wins_srv( void )
160 /* ------------------------------------------------------------------------ **
163 time_t now = time(NULL);
164 list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
165 list_entry *coldest = entry;
167 /* Go through the list. Look for the first live entry. */
168 while( (NULL != entry) && (now < entry->mourning) )
170 entry = (list_entry *)ubi_slNext( entry );
171 if( entry->mourning < coldest->mourning )
172 coldest = entry;
175 /* If they were all dead, then return the one that's been dead longest. */
176 if( NULL == entry )
178 entry = coldest;
179 DEBUG( 4, ("wins_srv: All WINS servers appear to have failed.\n") );
182 /* The list could be empty. Check it. */
183 if( NULL == entry )
184 return( NULL );
185 return( entry->server );
186 } /* wins_srv */
189 void wins_srv_died( char *boothill )
190 /* ------------------------------------------------------------------------ **
191 * Called to indicate that a specific WINS server has died.
194 list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
196 while( NULL != entry )
198 /* Match based on server ID [DNS name or IP]. */
199 if( 0 == strcmp( boothill, entry->server ) )
201 entry->mourning = time(NULL) + NECROMANCYCLE;
202 DEBUG( 2, ("wins_srv: WINS server %s appears to be down.\n", boothill) );
203 return;
205 entry = (list_entry *)ubi_slNext( entry );
207 } /* wins_srv_died */
210 unsigned long wins_srv_count( void )
211 /* ------------------------------------------------------------------------ **
212 * Return the total number of entries in the list, dead or alive.
215 return( ubi_slCount( wins_srv_list ) );
216 } /* wins_srv_count */
218 /* ========================================================================== */