removed all of lukes recent changes. I need to do a p2 release but
[Samba/gbeck.git] / source / namebrowse.c
blobb426bc7a15005404137016c35ab6664a5b1e37d1
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
21 Revision History:
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
28 #include "includes.h"
29 #include "smb.h"
31 extern int ClientNMB;
33 extern int DEBUGLEVEL;
35 /* this is our browse master/backup cache database */
36 static struct browse_cache_record *browserlist = NULL;
39 /***************************************************************************
40 add a browser into the list
41 **************************************************************************/
42 static void add_browse_cache(struct browse_cache_record *b)
44 struct browse_cache_record *b2;
46 if (!browserlist)
48 browserlist = b;
49 b->prev = NULL;
50 b->next = NULL;
51 return;
54 for (b2 = browserlist; b2->next; b2 = b2->next) ;
56 b2->next = b;
57 b->next = NULL;
58 b->prev = b2;
62 /*******************************************************************
63 remove old browse entries
64 ******************************************************************/
65 void expire_browse_cache(time_t t)
67 struct browse_cache_record *b;
68 struct browse_cache_record *nextb;
70 /* expire old entries in the serverlist */
71 for (b = browserlist; b; b = nextb)
73 if (b->synced && b->sync_time < t)
75 DEBUG(3,("Removing dead cached browser %s\n",b->name));
76 nextb = b->next;
78 if (b->prev) b->prev->next = b->next;
79 if (b->next) b->next->prev = b->prev;
81 if (browserlist == b) browserlist = b->next;
83 free(b);
85 else
87 nextb = b->next;
93 /****************************************************************************
94 add a browser entry
95 ****************************************************************************/
96 struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
97 time_t ttl, struct in_addr ip, BOOL local)
99 BOOL newentry=False;
101 struct browse_cache_record *b;
103 /* search for the entry: if it's already in the cache, update that entry */
104 for (b = browserlist; b; b = b->next)
106 if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break;
109 if (b && b->synced)
111 /* entries get left in the cache for a while. this stops sync'ing too
112 often if the network is large */
113 DEBUG(4, ("browser %s %s %s already sync'd at time %d\n",
114 b->name, b->group, inet_ntoa(b->ip), b->sync_time));
115 return NULL;
118 if (!b)
120 newentry = True;
121 b = (struct browse_cache_record *)malloc(sizeof(*b));
123 if (!b) return(NULL);
125 bzero((char *)b,sizeof(*b));
128 /* update the entry */
129 ttl = time(NULL)+ttl;
131 StrnCpy(b->name ,name,sizeof(b->name )-1);
132 StrnCpy(b->group,wg ,sizeof(b->group)-1);
133 strupper(b->name);
134 strupper(b->group);
136 b->ip = ip;
137 b->type = type;
138 b->local = local; /* local server list sync or complete sync required */
140 if (newentry || ttl < b->sync_time)
141 b->sync_time = ttl;
143 if (newentry)
145 b->synced = False;
146 add_browse_cache(b);
148 DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
149 wg, name, type, inet_ntoa(ip),ttl));
151 else
153 DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n",
154 wg, name, type, inet_ntoa(ip),ttl));
157 return(b);
161 /****************************************************************************
162 find a server responsible for a workgroup, and sync browse lists
163 **************************************************************************/
164 static void start_sync_browse_entry(struct browse_cache_record *b)
166 struct subnet_record *d;
167 struct work_record *work;
169 if (!(d = find_subnet(b->ip))) return;
171 if (!(work = find_workgroupstruct(d, b->group, False))) return;
173 /* only sync if we are the master */
174 if (AM_MASTER(work)) {
176 /* first check whether the group we intend to sync with exists. if it
177 doesn't, the server must have died. o dear. */
179 /* see response_netbios_packet() or expire_netbios_response_entries() */
180 queue_netbios_packet(d,ClientNMB,NMB_QUERY,
181 b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
182 b->group,0x20,0,0,0,NULL,NULL,
183 False,False,b->ip,b->ip);
186 b->synced = True;
190 /****************************************************************************
191 search through browser list for an entry to sync with
192 **************************************************************************/
193 void do_browser_lists(void)
195 struct browse_cache_record *b;
196 static time_t last = 0;
197 time_t t = time(NULL);
199 if (t-last < 20) return; /* don't do too many of these at once! */
200 /* XXXX equally this period should not be too long
201 the server may die in the intervening gap */
203 last = t;
205 /* pick any entry in the list, preferably one whose time is up */
206 for (b = browserlist; b && b->next; b = b->next)
208 if (b->sync_time < t && b->synced == False) break;
211 if (b && !b->synced)
213 /* sync with the selected entry then remove some dead entries */
214 start_sync_browse_entry(b);
215 expire_browse_cache(t - 60);