mirror of
https://github.com/samba-team/samba.git
synced 2025-01-20 14:03:59 +03:00
2c97b33fc0
Main change is removal of find_name_search() confusion. This has been replaced with find_name_on_subnet() which makes it explicit what is being searched. Also changed wins_subnet to be wins_client_subnet in preparation for splitting the wins subnet into client and server pieces. This is a big nmbd change and I'd appreciate any bug reports. Specific changes follow : asyncdns.c: Removed wins entry from add_netbios_entry(). This is now explicit in the subnet_record parameter. interface.c: iface_bcast(), iface_nmask(), iface_ip() return the default interface if none can be found. Made this behavior explicit - some code in nmbd incorrectly depended upon this (reply_name_status() for instance). nameannounce.c: find_name_search changes to find_name_on_subnet. namebrowse.c: wins_subnet renamed to wins_client_subnet. namedbname.c: find_name_search removed. find_name_on_subnet added. add_netbios_entry - wins parameter removed. namedbsubnet.c: find_req_subnet removed - not explicit enough. nameelect.c: wins_subnet renamed to wins_client_subnet. namepacket.c: listening() simplified. nameresp.c: wins_subnet renamed to wins_client_subnet. nameserv.c: find_name_search moved to find_name_on_subnet. nameserv.h: FIND_XXX -> changed to FIND_SELF_NAME, FIND_ANY_NAME. nameservreply.c: find_name_search moved to find_name_on_subnet. Debug entries changed. nameservresp.c: wins_subnet renamed to wins_client_subnet. namework.c: wins_subnet renamed to wins_client_subnet. nmbd.c: wins parameter removed from add_netbios_entry. nmbsync: wins_subnet renamed to wins_client_subnet. proto.h: The usual. server.c: remove accepted fd from fd_set. Jeremy (jallison@whistle.com)
-
247 lines
6.9 KiB
C
247 lines
6.9 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
NBT netbios routines and daemon - version 2
|
|
Copyright (C) Andrew Tridgell 1994-1997
|
|
|
|
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.
|
|
|
|
Revision History:
|
|
|
|
14 jan 96: lkcl@pires.co.uk
|
|
added multiple workgroup domain master support
|
|
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "smb.h"
|
|
|
|
extern int ClientNMB;
|
|
|
|
extern int DEBUGLEVEL;
|
|
|
|
extern struct in_addr wins_ip;
|
|
|
|
/* this is our browse master/backup cache database */
|
|
static struct browse_cache_record *browserlist = NULL;
|
|
|
|
|
|
/***************************************************************************
|
|
add a browser into the list
|
|
**************************************************************************/
|
|
static void add_browse_cache(struct browse_cache_record *b)
|
|
{
|
|
struct browse_cache_record *b2;
|
|
|
|
if (!browserlist)
|
|
{
|
|
browserlist = b;
|
|
b->prev = NULL;
|
|
b->next = NULL;
|
|
return;
|
|
}
|
|
|
|
for (b2 = browserlist; b2->next; b2 = b2->next) ;
|
|
|
|
b2->next = b;
|
|
b->next = NULL;
|
|
b->prev = b2;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
remove old browse entries
|
|
******************************************************************/
|
|
void expire_browse_cache(time_t t)
|
|
{
|
|
struct browse_cache_record *b;
|
|
struct browse_cache_record *nextb;
|
|
|
|
/* expire old entries in the serverlist */
|
|
for (b = browserlist; b; b = nextb)
|
|
{
|
|
if (b->synced && b->sync_time < t)
|
|
{
|
|
DEBUG(3,("Removing dead cached browser %s\n",b->name));
|
|
nextb = b->next;
|
|
|
|
if (b->prev) b->prev->next = b->next;
|
|
if (b->next) b->next->prev = b->prev;
|
|
|
|
if (browserlist == b) browserlist = b->next;
|
|
|
|
free(b);
|
|
}
|
|
else
|
|
{
|
|
nextb = b->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
add a browser entry
|
|
****************************************************************************/
|
|
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
|
|
time_t ttl, struct subnet_record *d,
|
|
struct in_addr ip, BOOL local)
|
|
{
|
|
BOOL newentry=False;
|
|
|
|
struct browse_cache_record *b;
|
|
|
|
/* search for the entry: if it's already in the cache, update that entry */
|
|
for (b = browserlist; b; b = b->next)
|
|
{
|
|
if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break;
|
|
}
|
|
|
|
if (b && b->synced)
|
|
{
|
|
/* entries get left in the cache for a while. this stops sync'ing too
|
|
often if the network is large */
|
|
DEBUG(4, ("browser %s %s %s already sync'd at time %d\n",
|
|
b->name, b->group, inet_ntoa(b->ip), b->sync_time));
|
|
return NULL;
|
|
}
|
|
|
|
if (!b)
|
|
{
|
|
newentry = True;
|
|
b = (struct browse_cache_record *)malloc(sizeof(*b));
|
|
|
|
if (!b) return(NULL);
|
|
|
|
bzero((char *)b,sizeof(*b));
|
|
}
|
|
|
|
/* update the entry */
|
|
ttl = time(NULL)+ttl;
|
|
|
|
StrnCpy(b->name ,name,sizeof(b->name )-1);
|
|
StrnCpy(b->group,wg ,sizeof(b->group)-1);
|
|
strupper(b->name);
|
|
strupper(b->group);
|
|
|
|
b->ip = ip;
|
|
b->type = type;
|
|
b->local = local; /* local server list sync or complete sync required */
|
|
b->subnet = d;
|
|
|
|
if (newentry || ttl < b->sync_time)
|
|
b->sync_time = ttl;
|
|
|
|
if (newentry)
|
|
{
|
|
b->synced = False;
|
|
add_browse_cache(b);
|
|
|
|
DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
|
|
wg, name, type, inet_ntoa(ip),ttl));
|
|
}
|
|
else
|
|
{
|
|
DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n",
|
|
wg, name, type, inet_ntoa(ip),ttl));
|
|
}
|
|
|
|
return(b);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
find a server responsible for a workgroup, and sync browse lists
|
|
**************************************************************************/
|
|
static void start_sync_browse_entry(struct browse_cache_record *b)
|
|
{
|
|
struct subnet_record *d = b->subnet;
|
|
struct work_record *work;
|
|
|
|
/* Check panic conditions - these should not be true. */
|
|
if(b->subnet != wins_client_subnet) {
|
|
DEBUG(0,
|
|
("start_sync_browse_entry: ERROR sync requested on non-WINS subnet.\n"));
|
|
return;
|
|
}
|
|
|
|
if (!(work = find_workgroupstruct(d, b->group, False))) {
|
|
DEBUG(0, ("start_sync_browse_entry: failed to get a \
|
|
workgroup for a browse cache entry workgroup %s, server %s\n",
|
|
b->group, b->name));
|
|
return;
|
|
}
|
|
|
|
DEBUG(4, ("start_sync_browse_entry: Initiating %s sync with %s<0x20>, \
|
|
workgroup %s\n",
|
|
b->local ? "local" : "remote", b->name, b->group));
|
|
|
|
/* first check whether the server we intend to sync with exists. if it
|
|
doesn't, the server must have died. o dear. */
|
|
|
|
/* see response_netbios_packet() or expire_netbios_response_entries() */
|
|
/* We cheat here by using the my_comment field of the response_record
|
|
struct as the workgroup name we are going to do the sync for.
|
|
This is because the reply packet doesn't include the workgroup, but
|
|
we need it when the reply comes back.
|
|
*/
|
|
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
|
|
b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
|
|
b->name,0x20,0,0,0,NULL,b->group,
|
|
False,False,b->ip,b->ip, 0);
|
|
|
|
b->synced = True;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
search through browser list for an entry to sync with
|
|
**************************************************************************/
|
|
void do_browser_lists(time_t t)
|
|
{
|
|
struct browse_cache_record *b;
|
|
static time_t last = 0;
|
|
|
|
if (t-last < 20)
|
|
{
|
|
DEBUG(9,("do_browser_lists: returning due to t(%d) - last(%d) < 20\n",
|
|
t, last));
|
|
return; /* don't do too many of these at once! */
|
|
/* XXXX equally this period should not be too long
|
|
the server may die in the intervening gap */
|
|
}
|
|
last = t;
|
|
|
|
/* pick any entry in the list, preferably one whose time is up */
|
|
for (b = browserlist; b && b->next; b = b->next)
|
|
{
|
|
if (b->sync_time < t && b->synced == False) break;
|
|
}
|
|
|
|
if (b && !b->synced)
|
|
{
|
|
/* sync with the selected entry then remove some dead entries */
|
|
DEBUG(4,("do_browser_lists: Initiating sync with %s, workgroup %s\n",
|
|
b->name, b->group));
|
|
start_sync_browse_entry(b);
|
|
}
|
|
else
|
|
{
|
|
DEBUG(9, ("do_browser_lists: no entries to sync.\n"));
|
|
}
|
|
|
|
expire_browse_cache(t - 60);
|
|
}
|
|
|