1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

Merge of netbios namecache code from APPLIANCE_HEAD.

Tridge suggested a generic caching mechanism for Samba to avoid the
proliferation of little cache files hanging around limpet like in the
locks directory.  Someone should probably implement this at some
stage.
(This used to be commit dad31483b3)
This commit is contained in:
Tim Potter 2002-08-16 00:25:48 +00:00
parent 298f956eaf
commit 88d321becd
7 changed files with 299 additions and 5 deletions

View File

@ -166,7 +166,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \
libsmb/passchange.o libsmb/unexpected.o libsmb/doserr.o \
$(RPC_PARSE_OBJ1)
libsmb/namecache.o $(RPC_PARSE_OBJ1)
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \

View File

@ -212,6 +212,18 @@ int strwicmp(const char *psz1, const char *psz2)
}
/* Convert a string to upper case, but don't modify it */
char *strupper_static(char *s)
{
static pstring str;
pstrcpy(str, s);
strupper(str);
return str;
}
/*******************************************************************
convert a string to "normal" form
********************************************************************/

252
source3/libsmb/namecache.c Normal file
View File

@ -0,0 +1,252 @@
/*
Unix SMB/CIFS implementation.
NetBIOS name cache module.
Copyright (C) Tim Potter, 2002
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.
*/
#include "includes.h"
static BOOL done_namecache_init;
static BOOL enable_namecache;
static TDB_CONTEXT *namecache_tdb;
struct nc_value {
time_t expiry; /* When entry expires */
int count; /* Number of addresses */
struct in_addr ip_list[0]; /* Address list */
};
/* Initialise namecache system */
void namecache_enable(void)
{
/* Check if we have been here before, or name caching disabled
by setting the name cache timeout to zero. */
if (done_namecache_init)
return;
done_namecache_init = True;
if (lp_name_cache_timeout() == 0) {
DEBUG(5, ("namecache_init: disabling netbios name cache\n"));
return;
}
/* Open namecache tdb in read/write or readonly mode */
namecache_tdb = tdb_open_log(
lock_path("namecache.tdb"), 0,
TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
if (!namecache_tdb) {
DEBUG(5, ("namecache_init: could not open %s\n",
lock_path("namecache.tdb")));
return;
}
DEBUG(5, ("namecache_init: enabling netbios namecache, timeout %d "
"seconds\n", lp_name_cache_timeout()));
enable_namecache = True;
}
/* Return a key for a name and name type. The caller must free
retval.dptr when finished. */
static TDB_DATA namecache_key(const char *name, int name_type)
{
TDB_DATA retval;
char *keystr;
asprintf(&keystr, "%s#%02X", strupper_static(name), name_type);
retval.dsize = strlen(keystr) + 1;
retval.dptr = keystr;
return retval;
}
/* Return a data value for an IP list. The caller must free
retval.dptr when finished. */
static TDB_DATA namecache_value(struct in_addr *ip_list, int num_names,
time_t expiry)
{
TDB_DATA retval;
struct nc_value *value;
int size;
size = sizeof(struct nc_value) + sizeof(struct in_addr) *
num_names;
value = (struct nc_value *)malloc(size);
value->expiry = expiry;
value->count = num_names;
memcpy(value->ip_list, ip_list, num_names * sizeof(struct in_addr));
retval.dptr = (char *)value;
retval.dsize = size;
return retval;
}
/* Store a name in the name cache */
void namecache_store(const char *name, int name_type,
int num_names, struct in_addr *ip_list)
{
TDB_DATA key, value;
time_t expiry;
int i;
if (!enable_namecache)
return;
DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
num_names, num_names == 1 ? "": "es", name, name_type));
for (i = 0; i < num_names; i++)
DEBUGADD(5, ("%s%s", inet_ntoa(ip_list[i]),
i == (num_names - 1) ? "" : ", "));
DEBUGADD(5, ("\n"));
key = namecache_key(name, name_type);
/* Cache pdc location or dc lists for only a little while
otherwise if we lock on to a bad DC we can potentially be
out of action for the entire cache timeout time! */
if (name_type != 0x1b || name_type != 0x1c)
expiry = time(NULL) + 10;
else
expiry = time(NULL) + lp_name_cache_timeout();
value = namecache_value(ip_list, num_names, expiry);
tdb_store(namecache_tdb, key, value, TDB_REPLACE);
free(key.dptr);
free(value.dptr);
}
/* Look up a name in the name cache. Return a mallocated list of IP
addresses if the name is contained in the cache. */
BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list,
int *num_names)
{
TDB_DATA key, value;
struct nc_value *data;
time_t now;
int i;
if (!enable_namecache)
return False;
/* Read value */
key = namecache_key(name, name_type);
value = tdb_fetch(namecache_tdb, key);
if (!value.dptr) {
DEBUG(5, ("namecache_fetch: %s#%02x not found\n",
name, name_type));
goto done;
}
data = (struct nc_value *)value.dptr;
/* Check expiry time */
now = time(NULL);
if (now > data->expiry) {
DEBUG(5, ("namecache_fetch: entry for %s#%02x expired\n",
name, name_type));
tdb_delete(namecache_tdb, key);
value = tdb_null;
goto done;
}
if ((data->expiry - now) > lp_name_cache_timeout()) {
/* Someone may have changed the system time on us */
DEBUG(5, ("namecache_fetch: entry for %s#%02x has bad expiry\n",
name, name_type));
tdb_delete(namecache_tdb, key);
value = tdb_null;
goto done;
}
/* Extract and return namelist */
*ip_list = (struct in_addr *)malloc(
sizeof(struct in_addr) * data->count);
memcpy(*ip_list, data->ip_list, sizeof(struct in_addr) *
data->count);
*num_names = data->count;
DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
*num_names, *num_names == 1 ? "" : "es", name, name_type));
for (i = 0; i < *num_names; i++)
DEBUGADD(5, ("%s%s", inet_ntoa((*ip_list)[i]),
i == (*num_names - 1) ? "" : ", "));
DEBUGADD(5, ("\n"));
done:
SAFE_FREE(key.dptr);
SAFE_FREE(value.dptr);
return value.dsize > 0;
}
/* Flush all names from the name cache */
void namecache_flush(void)
{
int result;
if (!namecache_tdb)
return;
result = tdb_traverse(namecache_tdb, tdb_traverse_delete_fn, NULL);
if (result == -1)
DEBUG(5, ("namecache_flush: error deleting cache entries\n"));
else
DEBUG(5, ("namecache_flush: deleted %d cache entr%s\n",
result, result == 1 ? "y" : "ies"));
}

View File

@ -783,7 +783,7 @@ static BOOL resolve_hosts(const char *name,
*********************************************************/
static BOOL internal_resolve_name(const char *name, int name_type,
struct in_addr **return_iplist, int *return_count)
struct in_addr **return_iplist, int *return_count)
{
pstring name_resolve_list;
fstring tok;
@ -816,6 +816,15 @@ static BOOL internal_resolve_name(const char *name, int name_type,
return True;
}
/* Check netbios name cache */
if (namecache_fetch(name, name_type, return_iplist, return_count)) {
/* This could be a negative response */
return (*return_count > 0);
}
pstrcpy(name_resolve_list, lp_name_resolve_order());
ptr = name_resolve_list;
if (!ptr || !*ptr)
@ -823,9 +832,16 @@ static BOOL internal_resolve_name(const char *name, int name_type,
while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
if((strequal(tok, "host") || strequal(tok, "hosts"))) {
if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
result = True;
goto done;
if (name_type == 0x20) {
if (resolve_hosts(name, return_iplist, return_count)) {
result = True;
goto done;
} else {
/* Store negative lookup result */
namecache_store(name, name_type, 0, NULL);
}
}
} else if(strequal( tok, "lmhosts")) {
if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
@ -897,6 +913,10 @@ static BOOL internal_resolve_name(const char *name, int name_type,
*return_iplist = nodupes_iplist;
*return_count = nodupes_count;
}
/* Save in name cache */
namecache_store(name, name_type, *return_count, *return_iplist);
/* Display some debugging info */

View File

@ -691,6 +691,8 @@ int winbind_setup_common(void)
}
namecache_enable(); /* Enable netbios namecache */
/* Get list of domains we look up requests for. This includes the
domain which we are a member of as well as any trusted
domains. */

View File

@ -260,6 +260,7 @@ typedef struct
BOOL bUnixExtensions;
BOOL bDisableNetbios;
int restrict_anonymous;
int name_cache_timeout;
}
global;
@ -838,6 +839,8 @@ static struct parm_struct parm_table[] = {
{"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, 0},
{"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_SHARE},
{"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, 0},
{"Printing Options", P_SEP, P_SEPARATOR},
{"total print jobs", P_INTEGER, P_GLOBAL, &Globals.iTotalPrintJobs, NULL, NULL, FLAG_PRINT},
@ -1375,6 +1378,8 @@ static void init_globals(void)
Globals.bWinbindEnumGroups = True;
Globals.bWinbindUseDefaultDomain = False;
Globals.name_cache_timeout = 660; /* In seconds */
Globals.bUseSpnego = True;
string_set(&Globals.smb_ports, SMB_PORTS);
@ -1740,6 +1745,7 @@ FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase)
FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
typedef struct _param_opt_struct param_opt_struct;
struct _param_opt_struct {

View File

@ -881,6 +881,8 @@ static void usage(char *pname)
* everything after this point is run after the fork()
*/
namecache_enable();
if (!locking_init(0))
exit(1);