summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/libsmb_compat.c8
-rw-r--r--source3/libsmb/libsmbclient.c169
-rw-r--r--source3/libsmb/namecache.c323
-rw-r--r--source3/libsmb/namequery.c189
4 files changed, 431 insertions, 258 deletions
diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c
index 27b274953a..bba90c648e 100644
--- a/source3/libsmb/libsmb_compat.c
+++ b/source3/libsmb/libsmb_compat.c
@@ -24,7 +24,11 @@
#include "includes.h"
-#include "../include/libsmb_internal.h"
+/*
+ * Define this to get the real SMBCFILE and SMBCSRV structures
+ */
+#define _SMBC_INTERNAL
+#include "../include/libsmbclient.h"
struct smbc_compat_fdlist {
SMBCFILE * file;
@@ -268,7 +272,7 @@ int smbc_open_print_job(const char *fname)
return (int) file;
}
-int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn)
+int smbc_list_print_jobs(const char *purl, smbc_get_print_job_info fn)
{
return statcont->list_print_jobs(statcont, purl, fn);
}
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index edf582b34d..a1fb380c37 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -23,7 +23,7 @@
#include "includes.h"
-#include "../include/libsmb_internal.h"
+#include "../include/libsmbclient.h"
/*
* Functions exported by libsmb_cache.c that we need here
@@ -218,7 +218,7 @@ int smbc_check_server(SMBCCTX * context, SMBCSRV * server)
}
/*
- * Remove a server from the cached server list it's unused.
+ * Remove a server from the list server_table if it's unused.
* On success, 0 is returned. 1 is returned if the server could not be removed.
*
* Also useable outside libsmbclient
@@ -228,12 +228,11 @@ int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv)
SMBCFILE * file;
/* are we being fooled ? */
- if (!context || !context->internal ||
- !context->internal->_initialized || !srv) return 1;
+ if (!context || !context->_initialized || !srv) return 1;
/* Check all open files/directories for a relation with this server */
- for (file = context->internal->_files; file; file=file->next) {
+ for (file = context->_files; file; file=file->next) {
if (file->srv == srv) {
/* Still used */
DEBUG(3, ("smbc_remove_usused_server: %p still used by %p.\n",
@@ -242,7 +241,7 @@ int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv)
}
}
- DLIST_REMOVE(context->internal->_servers, srv);
+ DLIST_REMOVE(context->_servers, srv);
cli_shutdown(&srv->cli);
@@ -475,8 +474,7 @@ static SMBCFILE *smbc_open_ctx(SMBCCTX *context, const char *fname, int flags, m
SMBCFILE *file = NULL;
int fd;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return NULL;
@@ -543,7 +541,7 @@ static SMBCFILE *smbc_open_ctx(SMBCCTX *context, const char *fname, int flags, m
file->offset = 0;
file->file = True;
- DLIST_ADD(context->internal->_files, file);
+ DLIST_ADD(context->_files, file);
return file;
}
@@ -574,8 +572,7 @@ static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC; /* FIXME: Do we need this
static SMBCFILE *smbc_creat_ctx(SMBCCTX *context, const char *path, mode_t mode)
{
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return NULL;
@@ -593,8 +590,7 @@ static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t
{
int ret;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -603,7 +599,7 @@ static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t
DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count));
- if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -644,15 +640,14 @@ static ssize_t smbc_write_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_
{
int ret;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -690,15 +685,14 @@ static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file)
{
SMBCSRV *srv;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -720,7 +714,7 @@ static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file)
* from the server cache if unused */
errno = smbc_errno(context, &file->srv->cli);
srv = file->srv;
- DLIST_REMOVE(context->internal->_files, file);
+ DLIST_REMOVE(context->_files, file);
SAFE_FREE(file->fname);
SAFE_FREE(file);
context->callbacks.remove_unused_server_fn(context, srv);
@@ -742,7 +736,7 @@ static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file)
* from the server cache if unused */
errno = smbc_errno(context, &file->srv->cli);
srv = file->srv;
- DLIST_REMOVE(context->internal->_files, file);
+ DLIST_REMOVE(context->_files, file);
SAFE_FREE(file->fname);
SAFE_FREE(file);
context->callbacks.remove_unused_server_fn(context, srv);
@@ -750,7 +744,7 @@ static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file)
return -1;
}
- DLIST_REMOVE(context->internal->_files, file);
+ DLIST_REMOVE(context->_files, file);
SAFE_FREE(file->fname);
SAFE_FREE(file);
@@ -767,8 +761,7 @@ static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path,
SMB_INO_T *ino)
{
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -804,8 +797,7 @@ static int smbc_unlink_ctx(SMBCCTX *context, const char *fname)
pstring path;
SMBCSRV *srv = NULL;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || context->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return -1;
@@ -899,10 +891,8 @@ static int smbc_rename_ctx(SMBCCTX *ocontext, const char *oname,
pstring path1, path2;
SMBCSRV *srv = NULL;
- if (!ocontext || !ncontext ||
- !ocontext->internal || !ncontext->internal ||
- !ocontext->internal->_initialized ||
- !ncontext->internal->_initialized) {
+ if (!ocontext || !ncontext ||
+ !ocontext->_initialized || !ncontext->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return -1;
@@ -970,15 +960,14 @@ static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int
{
size_t size;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -1031,8 +1020,7 @@ static
ino_t smbc_inode(SMBCCTX *context, const char *name)
{
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -1100,8 +1088,7 @@ static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st)
uint16 mode = 0;
SMB_INO_T ino = 0;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return -1;
@@ -1184,15 +1171,14 @@ static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st)
uint16 mode;
SMB_INO_T ino = 0;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -1285,6 +1271,9 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint
ZERO_STRUCTP(dirent);
+ ZERO_STRUCTP(dirent);
+
+
if (dir->dir_list == NULL) {
dir->dir_list = malloc(sizeof(struct smbc_dir_list));
@@ -1365,6 +1354,8 @@ list_fn(const char *name, uint32 type, const char *comment, void *state)
dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */
break;
}
+ ZERO_STRUCTP(dir->dir_list);
+
}
else dirent_type = dir->dir_type;
@@ -1399,9 +1390,9 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
SMBCSRV *srv = NULL;
SMBCFILE *dir = NULL;
struct in_addr rem_ip;
+ int slot = 0;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return NULL;
@@ -1497,6 +1488,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
return NULL;
}
+ ZERO_STRUCTP(dir->dir_end);
dir->srv = srv;
@@ -1676,7 +1668,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
}
- DLIST_ADD(context->internal->_files, dir);
+ DLIST_ADD(context->_files, dir);
return dir;
}
@@ -1688,15 +1680,14 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
static int smbc_closedir_ctx(SMBCCTX *context, SMBCFILE *dir)
{
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return -1;
@@ -1705,7 +1696,7 @@ static int smbc_closedir_ctx(SMBCCTX *context, SMBCFILE *dir)
smbc_remove_dir(dir); /* Clean it up */
- DLIST_REMOVE(context->internal->_files, dir);
+ DLIST_REMOVE(context->_files, dir);
if (dir) {
@@ -1728,15 +1719,14 @@ struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
/* Check that all is ok first ... */
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return NULL;
}
- if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return NULL;
@@ -1765,12 +1755,12 @@ struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
/* Hmmm, do I even need to copy it? */
- memcpy(context->internal->_dirent, dirent, dirent->dirlen); /* Copy the dirent */
- dirp = (struct smbc_dirent *)context->internal->_dirent;
+ memcpy(context->_dirent, dirent, dirent->dirlen); /* Copy the dirent */
+ dirp = (struct smbc_dirent *)context->_dirent;
dirp->comment = (char *)(&dirp->name + dirent->namelen + 1);
dir->dir_next = dir->dir_next->next;
- return (struct smbc_dirent *)context->internal->_dirent;
+ return (struct smbc_dirent *)context->_dirent;
}
}
@@ -1787,15 +1777,14 @@ static int smbc_getdents_ctx(SMBCCTX *context, SMBCFILE *dir, struct smbc_dirent
/* Check that all is ok first ... */
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return -1;
@@ -1874,8 +1863,7 @@ static int smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode)
fstring server, share, user, password, workgroup;
pstring path;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -1961,8 +1949,7 @@ static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname)
fstring server, share, user, password, workgroup;
pstring path;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2059,15 +2046,14 @@ static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname)
static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir)
{
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return -1;
@@ -2124,8 +2110,7 @@ static int smbc_lseekdir_ctx(SMBCCTX *context, SMBCFILE *dir, off_t offset)
struct smbc_dirent *dirent = (struct smbc_dirent *)offset;
struct smbc_dir_list *list_ent = NULL;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2171,8 +2156,7 @@ static int smbc_lseekdir_ctx(SMBCCTX *context, SMBCFILE *dir, off_t offset)
static int smbc_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st)
{
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2194,8 +2178,7 @@ static SMBCFILE *smbc_open_print_job_ctx(SMBCCTX *context, const char *fname)
fstring server, share, user, password;
pstring path;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || context->_initialized) {
errno = EINVAL;
return NULL;
@@ -2232,8 +2215,8 @@ static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_pr
int bytes, saverr, tot_bytes = 0;
char buf[4096];
- if (!c_file || !c_file->internal->_initialized || !c_print ||
- !c_print->internal->_initialized) {
+ if (!c_file || !c_file->_initialized || !c_print ||
+ !c_print->_initialized) {
errno = EINVAL;
return -1;
@@ -2302,14 +2285,13 @@ static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_pr
* Routine to list print jobs on a printer share ...
*/
-static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_list_print_job_fn fn)
+static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, void (*fn)(struct print_job_info *))
{
SMBCSRV *srv;
fstring server, share, user, password, workgroup;
pstring path;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2339,7 +2321,7 @@ static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_li
}
- if (cli_print_queue(&srv->cli, (void (*)(struct print_job_info *))fn) < 0) {
+ if (cli_print_queue(&srv->cli, fn) < 0) {
errno = smbc_errno(context, &srv->cli);
return -1;
@@ -2361,8 +2343,7 @@ static int smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id
pstring path;
int err;
- if (!context || !context->internal ||
- !context->internal->_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2413,23 +2394,14 @@ SMBCCTX * smbc_new_context(void)
{
SMBCCTX * context;
- context = malloc(sizeof(SMBCCTX));
+ context = malloc(sizeof(*context));
if (!context) {
errno = ENOMEM;
return NULL;
}
-
+
ZERO_STRUCTP(context);
- context->internal = malloc(sizeof(struct smbc_internal_data));
- if (!context->internal) {
- errno = ENOMEM;
- return NULL;
- }
-
- ZERO_STRUCTP(context->internal);
-
-
/* ADD REASONABLE DEFAULTS */
context->debug = 0;
context->timeout = 20000; /* 20 seconds */
@@ -2484,25 +2456,25 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx)
SMBCFILE * f;
DEBUG(1,("Performing aggressive shutdown.\n"));
- f = context->internal->_files;
+ f = context->_files;
while (f) {
context->close(context, f);
f = f->next;
}
- context->internal->_files = NULL;
+ context->_files = NULL;
/* First try to remove the servers the nice way. */
if (context->callbacks.purge_cached_fn(context)) {
SMBCSRV * s;
DEBUG(1, ("Could not purge all servers, Nice way shutdown failed.\n"));
- s = context->internal->_servers;
+ s = context->_servers;
while (s) {
cli_shutdown(&s->cli);
context->callbacks.remove_cached_srv_fn(context, s);
SAFE_FREE(s);
s = s->next;
}
- context->internal->_servers = NULL;
+ context->_servers = NULL;
}
}
else {
@@ -2512,12 +2484,12 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx)
errno = EBUSY;
return 1;
}
- if (context->internal->_servers) {
+ if (context->_servers) {
DEBUG(1, ("Active servers in context, free_context failed.\n"));
errno = EBUSY;
return 1;
}
- if (context->internal->_files) {
+ if (context->_files) {
DEBUG(1, ("Active files in context, free_context failed.\n"));
errno = EBUSY;
return 1;
@@ -2530,7 +2502,6 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx)
SAFE_FREE(context->user);
DEBUG(3, ("Context %p succesfully freed\n", context));
- SAFE_FREE(context->internal);
SAFE_FREE(context);
return 0;
}
@@ -2549,13 +2520,13 @@ SMBCCTX * smbc_init_context(SMBCCTX * context)
int pid;
char *user = NULL, *home = NULL;
- if (!context || !context->internal) {
+ if (!context) {
errno = EBADF;
return NULL;
}
/* Do not initialise the same client twice */
- if (context->internal->_initialized) {
+ if (context->_initialized) {
return 0;
}
@@ -2662,7 +2633,7 @@ SMBCCTX * smbc_init_context(SMBCCTX * context)
* FIXME: Should we check the function pointers here?
*/
- context->internal->_initialized = 1;
+ context->_initialized = 1;
return context;
}
diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c
index 40777011a1..724e0237d2 100644
--- a/source3/libsmb/namecache.c
+++ b/source3/libsmb/namecache.c
@@ -1,10 +1,9 @@
/*
Unix SMB/CIFS implementation.
- NetBIOS name cache module on top of gencache mechanism.
-
- Copyright (C) Tim Potter 2002
- Copyright (C) Rafal Szczesniak 2002
+ 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
@@ -23,224 +22,242 @@
#include "includes.h"
-#define NBTKEY_FMT "NBT/%s#%02X"
+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[1]; /* Address list */
+};
-/**
- * Initialise namecache system. Function calls gencache
- * initialisation function to perform necessary actions
- *
- * @return true upon successful initialisation of the cache or
- * false on failure
- **/
+/* Initialise namecache system */
BOOL namecache_enable(void)
{
- /*
- * Check if name caching disabled by setting the name cache
- * timeout to zero.
- */
+ /* Check if we have been here before, or name caching disabled
+ by setting the name cache timeout to zero. */
+
+ if (done_namecache_init)
+ return False;
+
+ done_namecache_init = True;
if (lp_name_cache_timeout() == 0) {
- DEBUG(5, ("namecache_enable: disabling netbios name cache\n"));
+ DEBUG(5, ("namecache_init: disabling netbios name cache\n"));
return False;
}
- /* Init namecache by calling gencache initialisation */
+ /* Open namecache tdb in read/write or readonly mode */
- if (!gencache_init()) {
- DEBUG(2, ("namecache_enable: Couldn't initialise namecache on top of gencache.\n"));
+ 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 False;
}
- /* I leave it for now, though I don't think we really need this (mimir, 27.09.2002) */
- DEBUG(5, ("namecache_enable: enabling netbios namecache, timeout %d "
+ DEBUG(5, ("namecache_init: enabling netbios namecache, timeout %d "
"seconds\n", lp_name_cache_timeout()));
+ enable_namecache = True;
+
return True;
}
+/* Return a key for a name and name type. The caller must free
+ retval.dptr when finished. */
-/**
- * Shutdown namecache. Routine calls gencache close function
- * to safely close gencache file.
- *
- * @return true upon successful shutdown of the cache or
- * false on failure
- **/
-
-BOOL namecache_shutdown(void)
+static TDB_DATA namecache_key(const char *name, int name_type)
{
- if (!gencache_shutdown()) {
- DEBUG(2, ("namecache_shutdown: Couldn't close namecache on top of gencache.\n"));
- return False;
- }
-
- DEBUG(5, ("namecache_shutdown: netbios namecache closed successfully.\n"));
- return True;
-}
+ TDB_DATA retval;
+ char *keystr;
+ asprintf(&keystr, "%s#%02X", strupper_static(name), name_type);
-/**
- * Generates a key for netbios name lookups on basis of
- * netbios name and type.
- * The caller must free returned key string when finished.
- *
- * @param name netbios name string (case insensitive)
- * @param name_type netbios type of the name being looked up
- *
- * @return string consisted of uppercased name and appended
- * type number
- */
+ retval.dsize = strlen(keystr) + 1;
+ retval.dptr = keystr;
-static char* namecache_key(const char *name, int name_type)
+ 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)
{
- char *keystr;
- asprintf(&keystr, NBTKEY_FMT, strupper_static(name), name_type);
+ TDB_DATA retval;
+ struct nc_value *value;
+ int size = sizeof(struct nc_value);
- return keystr;
-}
+ if (num_names > 0)
+ size += sizeof(struct in_addr) * (num_names-1);
+
+ value = (struct nc_value *)malloc(size);
+
+ memset(value, 0, size);
+
+ value->expiry = expiry;
+ value->count = num_names;
+ if (ip_list)
+ memcpy(value->ip_list, ip_list, sizeof(struct in_addr) * num_names);
-/**
- * Store a name(s) in the name cache
- *
- * @param name netbios names array
- * @param name_type integer netbios name type
- * @param num_names number of names being stored
- * @param ip_list array of in_addr structures containing
- * ip addresses being stored
- **/
+ retval.dptr = (char *)value;
+ retval.dsize = size;
-BOOL namecache_store(const char *name, int name_type,
- int num_names, struct in_addr *ip_list)
+ 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;
- char *key, *value_string;
int i;
- /*
- * we use gecache call to avoid annoying debug messages about
- * initialised namecache again and again...
- */
- if (!gencache_init()) return False;
+ if (!enable_namecache)
+ return;
DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
- num_names, num_names == 1 ? "": "es", name, name_type));
+ 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) ? "" : ", "));
+ 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!
- */
+ /* 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)
+ if (name_type != 0x1b || name_type != 0x1c)
expiry = time(NULL) + 10;
else
expiry = time(NULL) + lp_name_cache_timeout();
- /*
- * Generate string representation of ip addresses list
- * First, store the number of ip addresses and then
- * place each single ip
- */
- ipstr_list_make(&value_string, ip_list, num_names);
-
- /* set the entry */
- return (gencache_set(key, value_string, expiry));
-}
+ 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 cache.
- *
- * @param name netbios name to look up for
- * @param name_type netbios name type of @param name
- * @param ip_list mallocated list of IP addresses if found in the cache,
- * NULL otherwise
- * @param num_names number of entries found
- *
- * @return true upon successful fetch or
- * false if name isn't found in the cache or has expired
- **/
+/* 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)
+ int *num_names)
{
- char *key, *value;
- time_t timeout;
+ TDB_DATA key, value;
+ struct nc_value *data = NULL;
+ time_t now;
+ int i;
+ *ip_list = NULL;
*num_names = 0;
- /* exit now if null pointers were passed as they're required further */
- if (!ip_list || !num_names) return False;
-
- if (!gencache_init())
+ if (!enable_namecache)
return False;
- /*
- * Use gencache interface - lookup the key
- */
+ /* Read value */
+
key = namecache_key(name, name_type);
- if (!gencache_get(key, &value, &timeout)) {
- DEBUG(5, ("no entry for %s#%02X found.\n", name, name_type));
- SAFE_FREE(key);
- return False;
- } else {
- DEBUG(5, ("name %s#%02X found.\n", name, name_type));
- }
-
- /*
- * Split up the stored value into the list of IP adresses
- */
- *num_names = ipstr_list_parse(value, ip_list);
+ value = tdb_fetch(namecache_tdb, key);
- SAFE_FREE(key);
- SAFE_FREE(value);
- return *num_names > 0; /* true only if some ip has been fetched */
-}
+ if (!value.dptr) {
+ DEBUG(5, ("namecache_fetch: %s#%02x not found\n",
+ name, name_type));
+ goto done;
+ }
+ data = (struct nc_value *)value.dptr;
-/**
- * Delete single namecache entry. Look at the
- * gencache_iterate definition.
- *
- **/
+ /* Check expiry time */
-static void flush_netbios_name(const char* key, const char *value, time_t timeout, void* dptr)
-{
- gencache_del(key);
- DEBUG(5, ("Deleting entry %s\n", key));
-}
+ 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;
-/**
- * Flush all names from the name cache.
- * It's done by gencache_iterate()
- *
- * @return True upon successful deletion or
- * False in case of an error
- **/
+ 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 */
+
+ DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
+ data->count, data->count == 1 ? "" : "es", name, name_type));
+
+ if (data->count) {
+
+ *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;
+
+ 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(data);
+
+ return value.dsize > 0;
+}
+
+/* Flush all names from the name cache */
void namecache_flush(void)
{
- if (!gencache_init())
+ int result;
+
+ if (!namecache_tdb)
return;
- /*
- * iterate through each NBT cache's entry and flush it
- * by flush_netbios_name function
- */
- gencache_iterate(flush_netbios_name, NULL, "NBT/*");
- DEBUG(5, ("Namecache flushed\n"));
-}
+ 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"));
+}
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index f446453b9a..0f81ff3eab 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -837,6 +837,11 @@ static BOOL internal_resolve_name(const char *name, int name_type,
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")) {
@@ -911,10 +916,7 @@ static BOOL internal_resolve_name(const char *name, int name_type,
}
/* Save in name cache */
- for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
- DEBUG(100, ("Storing name %s of type %d (ip: %s)\n", name,
- name_type, inet_ntoa((*return_iplist)[i])));
-
+
namecache_store(name, name_type, *return_count, *return_iplist);
/* Display some debugging info */
@@ -1001,6 +1003,7 @@ BOOL find_master_ip(const char *group, struct in_addr *master_ip)
BOOL lookup_dc_name(const char *srcname, const char *domain,
struct in_addr *dc_ip, char *ret_name)
{
+#if !defined(I_HATE_WINDOWS_REPLY_CODE)
fstring dc_name;
BOOL ret;
@@ -1024,6 +1027,184 @@ BOOL lookup_dc_name(const char *srcname, const char *domain,
}
return False;
+
+#else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
+
+JRA - This code is broken with BDC rollover - we need to do a full
+NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
+
+ int retries = 3;
+ int retry_time = 2000;
+ struct timeval tval;
+ struct packet_struct p;
+ struct dgram_packet *dgram = &p.packet.dgram;
+ char *ptr,*p2;
+ char tmp[4];
+ int len;
+ struct sockaddr_in sock_name;
+ int sock_len = sizeof(sock_name);
+ const char *mailslot = NET_LOGON_MAILSLOT;
+ char *mailslot_name;
+ char buffer[1024];
+ char *bufp;
+ int dgm_id = generate_trn_id();
+ int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
+
+ if(sock == -1)
+ return False;
+
+ /* Find out the transient UDP port we have been allocated. */
+ if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
+ DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
+ strerror(errno)));
+ close(sock);
+ return False;
+ }
+
+ /*
+ * Create the request data.
+ */
+
+ memset(buffer,'\0',sizeof(buffer));
+ bufp = buffer;
+ SSVAL(bufp,0,QUERYFORPDC);
+ bufp += 2;
+ fstrcpy(bufp,srcname);
+ bufp += (strlen(bufp) + 1);
+ slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
+ mailslot_name = bufp;
+ bufp += (strlen(bufp) + 1);
+ bufp = ALIGN2(bufp, buffer);
+ bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
+
+ SIVAL(bufp,0,1);
+ SSVAL(bufp,4,0xFFFF);
+ SSVAL(bufp,6,0xFFFF);
+ bufp += 8;
+ len = PTR_DIFF(bufp,buffer);
+
+ memset((char *)&p,'\0',sizeof(p));
+
+ /* DIRECT GROUP or UNIQUE datagram. */
+ dgram->header.msg_type = 0x10;
+ dgram->header.flags.node_type = M_NODE;
+ dgram->header.flags.first = True;
+ dgram->header.flags.more = False;
+ dgram->header.dgm_id = dgm_id;
+ dgram->header.source_ip = *iface_ip(*pdc_ip);
+ dgram->header.source_port = ntohs(sock_name.sin_port);
+ dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
+ dgram->header.packet_offset = 0;
+
+ make_nmb_name(&dgram->source_name,srcname,0);
+ make_nmb_name(&dgram->dest_name,domain,0x1C);
+
+ ptr = &dgram->data[0];
+
+ /* Setup the smb part. */
+ ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
+ memcpy(tmp,ptr,4);
+ set_message(ptr,17,17 + len,True);
+ memcpy(ptr,tmp,4);
+
+ CVAL(ptr,smb_com) = SMBtrans;
+ SSVAL(ptr,smb_vwv1,len);
+ SSVAL(ptr,smb_vwv11,len);
+ SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
+ SSVAL(ptr,smb_vwv13,3);
+ SSVAL(ptr,smb_vwv14,1);
+ SSVAL(ptr,smb_vwv15,1);
+ SSVAL(ptr,smb_vwv16,2);
+ p2 = smb_buf(ptr);
+ pstrcpy(p2,mailslot);
+ p2 = skip_string(p2,1);
+
+ memcpy(p2,buffer,len);
+ p2 += len;
+
+ dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
+
+ p.ip = *pdc_ip;
+ p.port = DGRAM_PORT;
+ p.fd = sock;
+ p.timestamp = time(NULL);
+ p.packet_type = DGRAM_PACKET;
+
+ GetTimeOfDay(&tval);
+
+ if (!send_packet(&p)) {
+ DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
+ close(sock);
+ return False;
+ }
+
+ retries--;
+
+ while (1) {
+ struct timeval tval2;
+ struct packet_struct *p_ret;
+
+ GetTimeOfDay(&tval2);
+ if (TvalDiff(&tval,&tval2) > retry_time) {
+ if (!retries)
+ break;
+ if (!send_packet(&p)) {
+ DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
+ close(sock);
+ return False;
+ }
+ GetTimeOfDay(&tval);
+ retries--;
+ }
+
+ if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
+ struct dgram_packet *dgram2 = &p_ret->packet.dgram;
+ char *buf;
+ char *buf2;
+
+ buf = &dgram2->data[0];
+ buf -= 4;
+
+ if (CVAL(buf,smb_com) != SMBtrans) {
+ DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
+ CVAL(buf,smb_com), (unsigned int)SMBtrans ));
+ free_packet(p_ret);
+ continue;
+ }
+
+ len = SVAL(buf,smb_vwv11);
+ buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
+
+ if (len <= 0) {
+ DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
+ free_packet(p_ret);
+ continue;
+ }
+
+ DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
+ nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
+ inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
+
+ if(SVAL(buf2,0) != QUERYFORPDC_R) {
+ DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
+ (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
+ free_packet(p_ret);
+ continue;
+ }
+
+ buf2 += 2;
+ /* Note this is safe as it is a bounded strcpy. */
+ fstrcpy(ret_name, buf2);
+ ret_name[sizeof(fstring)-1] = '\0';
+ close(sock);
+ free_packet(p_ret);
+ return True;
+ }
+ }
+
+ close(sock);
+ return False;
+#endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
}
/********************************************************