2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1995
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.
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
26 30 July 96: David.Chappell@mail.trincoll.edu
27 Expanded multiple workgroup domain master browser support.
36 extern int DEBUGLEVEL;
38 /* this is our browse master/backup cache database */
39 static struct browse_cache_record *browserlist = NULL;
42 /***************************************************************************
43 add a browser into the list
44 **************************************************************************/
45 static void add_browse_cache(struct browse_cache_record *b)
47 struct browse_cache_record *b2;
57 for (b2 = browserlist; b2->next; b2 = b2->next) ;
65 /*******************************************************************
66 remove old browse entries
67 ******************************************************************/
68 void expire_browse_cache(time_t t)
70 struct browse_cache_record *b;
71 struct browse_cache_record *nextb;
73 /* expire old entries in the serverlist */
74 for (b = browserlist; b; b = nextb)
76 if (b->synced && b->sync_time < t)
78 DEBUG(3,("Removing dead cached browser %s\n",b->name));
81 if (b->prev) b->prev->next = b->next;
82 if (b->next) b->next->prev = b->prev;
84 if (browserlist == b) browserlist = b->next;
96 /****************************************************************************
98 ****************************************************************************/
99 struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
100 time_t ttl, struct in_addr ip, BOOL local)
104 struct browse_cache_record *b;
106 /* search for the entry: if it's already in the cache, update that entry */
107 for (b = browserlist; b; b = b->next)
109 if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break;
114 /* entries get left in the cache for a while. this stops sync'ing too
115 often if the network is large */
116 DEBUG(4, ("browser %s %s %s already sync'd at time %d\n",
117 b->name, b->group, inet_ntoa(b->ip), b->sync_time));
124 b = (struct browse_cache_record *)malloc(sizeof(*b));
126 if (!b) return(NULL);
128 bzero((char *)b,sizeof(*b));
131 /* update the entry */
132 ttl = time(NULL)+ttl;
134 StrnCpy(b->name ,name,sizeof(b->name )-1);
135 StrnCpy(b->group,wg ,sizeof(b->group)-1);
141 b->local = local; /* local server list sync or complete sync required */
143 if (newentry || ttl < b->sync_time)
151 DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
152 wg, name, type, inet_ntoa(ip),ttl));
156 DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n",
157 wg, name, type, inet_ntoa(ip),ttl));
164 /****************************************************************************
165 find a server responsible for a workgroup, and sync browse lists
166 **************************************************************************/
167 static void start_sync_browse_entry(struct browse_cache_record *b)
169 struct subnet_record *d;
170 struct work_record *work;
172 if( (d = find_subnet(b->ip)) == (struct subnet_record *)NULL ) return;
174 if (!(work = find_workgroupstruct(d, b->group, False))) return;
176 /* only sync if we are the master */
177 if (AM_MASTER(work)) {
179 /* first check whether the group we intend to sync with exists. if it
180 doesn't, the server must have died. o dear. */
182 /* see response_netbios_packet() or expire_netbios_response_entries() */
183 queue_netbios_packet(d,ClientNMB,NMB_QUERY,
184 b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
185 work->token,b->group,0x20,0,0,0,NULL,NULL,
186 False,False,b->ip,b->ip);
193 /****************************************************************************
194 search through browser list for an entry to sync with
195 **************************************************************************/
196 void do_browser_lists(void)
198 struct browse_cache_record *b;
199 static time_t last = 0;
200 time_t t = time(NULL);
202 if (t-last < 20) return; /* don't do too many of these at once! */
203 /* XXXX equally this period should not be too long
204 the server may die in the intervening gap */
208 /* pick any entry in the list, preferably one whose time is up */
209 for (b = browserlist; b && b->next; b = b->next)
211 if (b->sync_time < t && b->synced == False) break;
216 /* sync with the selected entry then remove some dead entries */
217 start_sync_browse_entry(b);
218 expire_browse_cache(t - 60);