if we are adding a new sambaAccount, make sure that we add a
[Samba.git] / source / lib / wins_srv.c
blob23700a026b5cbe1c84e20795bc940c0fc8e096cf
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Christopher R. Hertel 2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 /* -------------------------------------------------------------------------- **
26 * Discussion...
28 * This module implements WINS failover.
30 * Microsoft's WINS servers provide a feature called WINS replication,
31 * which synchronises the WINS name databases between two or more servers.
32 * This means that the two servers can be used interchangably (more or
33 * less). WINS replication is particularly useful if you are trying to
34 * synchronise the WINS namespace between servers in remote locations, or
35 * if your WINS servers tend to crash a lot.
37 * WINS failover allows the client to 'switch' to a different WINS server
38 * if the current WINS server mysteriously disappears. On Windows
39 * systems, this is typically represented as 'primary' and 'secondary'
40 * WINS servers.
42 * Failover only works if the WINS servers are synced. If they are not,
43 * then
44 * a) if the primary WINS server never fails the client will never 'see'
45 * the secondary (or tertiary or...) WINS server name space.
46 * b) if the primary *does* fail, the client will be entering an
47 * unfamiliar namespace. The client itself will not be registered in
48 * that namespace and any names which match names in the previous
49 * space will likely resolve to different host IP addresses.
51 * One key thing to remember regarding WINS failover is that Samba does
52 * not (yet) implement WINS replication. For those interested, sniff port
53 * 42 (TCP? UDP? ...dunno off hand) and see what two MS WINS servers do.
55 * At this stage, only failover is implemented. The next thing is to add
56 * support for multi-WINS server registration and query (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 > current time then server is dead, Jim. */
93 char *server; /* DNS name or IP of NBNS server to query. */
94 struct in_addr ip_addr; /* Cache translated IP. */
95 } list_entry;
97 /* -------------------------------------------------------------------------- **
98 * Private, static variables.
101 static ubi_slNewList( wins_srv_list );
103 /* -------------------------------------------------------------------------- **
104 * Functions...
108 BOOL wins_srv_load_list( char *src )
109 /* ------------------------------------------------------------------------ **
110 * Create or recreate the linked list of failover WINS servers.
112 * Input: src - String of DNS names and/or IP addresses delimited by the
113 * characters listed in LIST_SEP (see include/local.h).
115 * Output: True if at least one name or IP could be parsed out of the
116 * list, else False.
118 * Notes: There is no syntax checking done on the names or IPs. We do
119 * check to see if the field is an IP, in which case we copy it
120 * to the ip_addr field of the entry. Don't bother to to a host
121 * name lookup on all names now. They're done as needed in
122 * wins_srv_ip().
125 list_entry *entry;
126 char *p = src;
127 pstring wins_id_bufr;
128 unsigned long count;
130 /* Empty the list. */
131 while( NULL != (entry =(list_entry *)ubi_slRemHead( wins_srv_list )) )
133 SAFE_FREE( entry->server );
134 SAFE_FREE( entry );
136 (void)ubi_slInitList( wins_srv_list ); /* shouldn't be needed */
138 /* Parse out the DNS names or IP addresses of the WINS servers. */
139 DEBUG( 4, ("wins_srv_load_list(): Building WINS server list:\n") );
140 while( next_token( &p, wins_id_bufr, LIST_SEP, sizeof( wins_id_bufr ) ) )
142 entry = (list_entry *)malloc( sizeof( list_entry ) );
143 if( NULL == entry )
145 DEBUG( 0, ("wins_srv_load_list(): malloc(list_entry) failed.\n") );
147 else
149 entry->mourning = 0;
150 if( NULL == (entry->server = strdup( wins_id_bufr )) )
152 SAFE_FREE( entry );
153 DEBUG( 0, ("wins_srv_load_list(): strdup(\"%s\") failed.\n", wins_id_bufr) );
155 else
157 /* Add server to list. */
158 if( is_ipaddress( wins_id_bufr ) )
159 entry->ip_addr = *interpret_addr2( wins_id_bufr );
160 else
161 entry->ip_addr = *interpret_addr2( "0.0.0.0" );
162 (void)ubi_slAddTail( wins_srv_list, entry );
163 DEBUGADD( 4, ("%s,\n", wins_id_bufr) );
168 count = ubi_slCount( wins_srv_list );
169 DEBUGADD( 4, ( "%d WINS server%s listed.\n", (int)count, (1==count)?"":"s" ) );
171 return( (count > 0) ? True : False );
172 } /* wins_srv_load_list */
175 struct in_addr wins_srv_ip( void )
176 /* ------------------------------------------------------------------------ **
179 time_t now = time(NULL);
180 list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
182 while( NULL != entry )
184 if( now >= entry->mourning ) /* Found a live one. */
186 /* If we don't have the IP, look it up. */
187 if( is_zero_ip( entry->ip_addr ) )
188 entry->ip_addr = *interpret_addr2( entry->server );
190 /* If we still don't have the IP then kill it, else return it. */
191 if( is_zero_ip( entry->ip_addr ) )
192 entry->mourning = now + NECROMANCYCLE;
193 else
194 return( entry->ip_addr );
196 entry = (list_entry *)ubi_slNext( entry );
199 /* If there are no live entries, return the zero IP. */
200 return( *interpret_addr2( "0.0.0.0" ) );
201 } /* wins_srv_ip */
204 void wins_srv_died( struct in_addr boothill_ip )
205 /* ------------------------------------------------------------------------ **
206 * Called to indicate that a specific WINS server has died.
209 list_entry *entry;
211 if( is_zero_ip( boothill_ip ) )
213 DEBUG( 4, ("wins_srv_died(): Got request to mark zero IP down.\n") );
214 return;
217 entry = (list_entry *)ubi_slFirst( wins_srv_list );
218 while( NULL != entry )
220 /* Match based on IP. */
221 if( ip_equal( boothill_ip, entry->ip_addr ) )
223 entry->mourning = time(NULL) + NECROMANCYCLE;
224 entry->ip_addr.s_addr = 0; /* Force a re-lookup at re-birth. */
225 DEBUG( 2, ( "wins_srv_died(): WINS server %s appears to be down.\n",
226 entry->server ) );
227 return;
229 entry = (list_entry *)ubi_slNext( entry );
232 if( DEBUGLVL( 1 ) )
234 dbgtext( "wins_srv_died(): Could not mark WINS server %s down.\n",
235 inet_ntoa( boothill_ip ) );
236 dbgtext( "Address not found in server list.\n" );
238 } /* wins_srv_died */
241 unsigned long wins_srv_count( void )
242 /* ------------------------------------------------------------------------ **
243 * Return the total number of entries in the list, dead or alive.
246 unsigned long count = ubi_slCount( wins_srv_list );
248 if( DEBUGLVL( 8 ) )
250 list_entry *entry = (list_entry *)ubi_slFirst( wins_srv_list );
251 time_t now = time(NULL);
253 dbgtext( "wins_srv_count: WINS status: %ld servers.\n", count );
254 while( NULL != entry )
256 dbgtext( " %s <%s>: ", entry->server, inet_ntoa( entry->ip_addr ) );
257 if( now >= entry->mourning )
258 dbgtext( "alive\n" );
259 else
260 dbgtext( "dead for %d more seconds\n", (int)(entry->mourning - now) );
262 entry = (list_entry *)ubi_slNext( entry );
266 return( count );
267 } /* wins_srv_count */
269 /* ========================================================================== */