mirror of
https://github.com/samba-team/samba.git
synced 2025-01-20 14:03:59 +03:00
b50ff657dd
created namedb*.c nameservresp.c nameservreply.c and namepacket.c added modules to Makefile, downloading dan's current version first :-) shuffled docs to match source created more docs fixed bug in announce_backup() discovered when going nameannounce.doc: backup list requests to the master browser should be used when samba is not a master browser; backup list requests to the primary domain controller should be used when samba is not a primary domain controller. fixed bug in sync_server: it would never send MasterAnnounce packets. removed the code that ignored special browser names: these should only be ignored (except 0x1b names) when broadcasted name queries are sent, not when directed registration or directed queries are sent samba as a WINS server. (note: exactly what's going on is still uncertain). renamed NAME_QUERY_MST_SRV_CHK to NAME_QUERY_PDC_SRV_CHK (more accurate). renamed NAME_STATUS_MST_SRV_CHK to NAME_STATUS_PDC_SRV_CHK (more accurate). added secured WINS name registration: a new 'state' NAME_REGISTER_CHALLENGE; functions send_name_response(), response_name_query_register(); added sending of WAIT ACKNOWLEDGEMENT packet; added a reply_to_ip field to the response record structure so that after the name query challenge, you know who to inform of the outcome of that challenge. note: these are all currently untested modifications (yikes!) lkcl
-
218 lines
5.7 KiB
C
218 lines
5.7 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
NBT netbios routines and daemon - version 2
|
|
Copyright (C) Andrew Tridgell 1994-1995
|
|
|
|
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;
|
|
|
|
/* 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 in_addr ip)
|
|
{
|
|
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;
|
|
|
|
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;
|
|
struct work_record *work;
|
|
|
|
if (!(d = find_subnet(b->ip))) return;
|
|
|
|
if (!(work = find_workgroupstruct(d, b->group, False))) return;
|
|
|
|
/* only sync if we are the master */
|
|
if (AM_MASTER(work)) {
|
|
|
|
/* first check whether the group 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() */
|
|
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SYNC,
|
|
b->group,0x20,0,0,
|
|
False,False,b->ip,b->ip);
|
|
}
|
|
|
|
b->synced = True;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
search through browser list for an entry to sync with
|
|
**************************************************************************/
|
|
void do_browser_lists(void)
|
|
{
|
|
struct browse_cache_record *b;
|
|
static time_t last = 0;
|
|
time_t t = time(NULL);
|
|
|
|
if (t-last < 20) 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 */
|
|
start_sync_browse_entry(b);
|
|
expire_browse_cache(t - 60);
|
|
}
|
|
|
|
}
|
|
|