1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-30 20:23:49 +03:00

r4898: - removed the unused wins_srv_*() code

- expanded the generic async name resolver to try multiple methods

- added wins resolutions to the list of methods tried

- fixed up the random trn id generation to use the good random generator
This commit is contained in:
Andrew Tridgell
2005-01-21 13:13:24 +00:00
committed by Gerald (Jerry) Carter
parent eb46adade4
commit 266fd2751c
11 changed files with 375 additions and 506 deletions

View File

@@ -48,7 +48,6 @@ ADD_OBJ_FILES = \
lib/username.o \ lib/username.o \
lib/dprintf.o \ lib/dprintf.o \
lib/xfile.o \ lib/xfile.o \
lib/wins_srv.o \
lib/util_str.o \ lib/util_str.o \
lib/util_strlist.o \ lib/util_strlist.o \
lib/util_unistr.o \ lib/util_unistr.o \

View File

@@ -192,10 +192,9 @@ static int do_reseed(BOOL use_fd, int fd)
return -1; return -1;
} }
/******************************************************************* /*
Interface to the (hopefully) good crypto random number generator. Interface to the (hopefully) good crypto random number generator.
********************************************************************/ */
void generate_random_buffer(uint8_t *out, int len) void generate_random_buffer(uint8_t *out, int len)
{ {
static int urand_fd = -1; static int urand_fd = -1;
@@ -239,6 +238,17 @@ void generate_random_buffer(uint8_t *out, int len)
} }
} }
/*
generate a single random uint32_t
*/
uint32_t generate_random(void)
{
uint8_t v[4];
generate_random_buffer(v, 4);
return IVAL(v, 0);
}
/* /*
very basic password quality checker very basic password quality checker
*/ */

View File

@@ -181,37 +181,6 @@ struct hostent *sys_gethostbyname(const char *name)
} }
/**************************************************************************
Wrapper for random().
****************************************************************************/
long sys_random(void)
{
#if defined(HAVE_RANDOM)
return (long)random();
#elif defined(HAVE_RAND)
return (long)rand();
#else
DEBUG(0,("Error - no random function available !\n"));
exit(1);
#endif
}
/**************************************************************************
Wrapper for srandom().
****************************************************************************/
void sys_srandom(uint_t seed)
{
#if defined(HAVE_SRANDOM)
srandom(seed);
#elif defined(HAVE_SRAND)
srand(seed);
#else
DEBUG(0,("Error - no srandom function available !\n"));
exit(1);
#endif
}
/************************************************************************** /**************************************************************************
Wrappers for dlopen, dlsym, dlclose. Wrappers for dlopen, dlsym, dlclose.

View File

@@ -1,362 +0,0 @@
/*
Unix SMB/CIFS implementation.
Samba wins server helper functions
Copyright (C) Andrew Tridgell 1992-2002
Copyright (C) Christopher R. Hertel 2000
Copyright (C) Tim Potter 2003
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"
#include "system/time.h"
/*
This is pretty much a complete rewrite of the earlier code. The main
aim of the rewrite is to add support for having multiple wins server
lists, so Samba can register with multiple groups of wins servers
and each group has a failover list of wins servers.
Central to the way it all works is the idea of a wins server
'tag'. A wins tag is a label for a group of wins servers. For
example if you use
wins server = fred:192.168.2.10 mary:192.168.3.199 fred:192.168.2.61
then you would have two groups of wins servers, one tagged with the
name 'fred' and the other with the name 'mary'. I would usually
recommend using interface names instead of 'fred' and 'mary' but
they can be any alpha string.
Now, how does it all work. Well, nmbd needs to register each of its
IPs with each of its names once with each group of wins servers. So
it tries registering with the first one mentioned in the list, then
if that fails it marks that WINS server dead and moves onto the next
one.
In the client code things are a bit different. As each of the groups
of wins servers is a separate name space we need to try each of the
groups until we either succeed or we run out of wins servers to
try. If we get a negative response from a wins server then that
means the name doesn't exist in that group, so we give up on that
group and move to the next group. If we don't get a response at all
then maybe the wins server is down, in which case we need to
failover to the next one for that group.
confused yet? (tridge)
*/
/* how long a server is marked dead for */
#define DEATH_TIME 600
/* The list of dead wins servers is stored in gencache.tdb. Each server is
marked dead from the point of view of a given source address. We keep a
separate dead list for each src address to cope with multiple interfaces
that are not routable to each other.
*/
#define WINS_SRV_FMT "WINS_SRV_DEAD/%s,%s" /* wins_ip,src_ip */
static char *wins_srv_keystr(struct ipv4_addr wins_ip, struct ipv4_addr src_ip)
{
char *keystr;
if (asprintf(&keystr, WINS_SRV_FMT, sys_inet_ntoa(wins_ip),
sys_inet_ntoa(src_ip)) == -1) {
DEBUG(0, ("wins_srv_is_dead: malloc error\n"));
return NULL;
}
return keystr;
}
/*
see if an ip is on the dead list
*/
BOOL wins_srv_is_dead(struct ipv4_addr wins_ip, struct ipv4_addr src_ip)
{
char *keystr = wins_srv_keystr(wins_ip, src_ip);
BOOL result;
/* If the key exists then the WINS server has been marked as dead */
result = gencache_get(keystr, NULL, NULL);
SAFE_FREE(keystr);
DEBUG(4, ("wins_srv_is_dead: %s is %s\n", sys_inet_ntoa(wins_ip),
result ? "dead" : "alive"));
return result;
}
/*
mark a wins server as being alive (for the moment)
*/
void wins_srv_alive(struct ipv4_addr wins_ip, struct ipv4_addr src_ip)
{
char *keystr = wins_srv_keystr(wins_ip, src_ip);
gencache_del(keystr);
SAFE_FREE(keystr);
DEBUG(4, ("wins_srv_alive: marking wins server %s alive\n",
sys_inet_ntoa(wins_ip)));
}
/*
mark a wins server as temporarily dead
*/
void wins_srv_died(struct ipv4_addr wins_ip, struct ipv4_addr src_ip)
{
char *keystr;
if (is_zero_ip(wins_ip) || wins_srv_is_dead(wins_ip, src_ip))
return;
keystr = wins_srv_keystr(wins_ip, src_ip);
gencache_set(keystr, "DOWN", time(NULL) + DEATH_TIME);
SAFE_FREE(keystr);
DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n",
sys_inet_ntoa(wins_ip), DEATH_TIME, sys_inet_ntoa(src_ip)));
}
/*
return the total number of wins servers, dead or not
*/
uint_t wins_srv_count(void)
{
const char **list;
int count = 0;
if (lp_wins_support()) {
/* simple - just talk to ourselves */
return 1;
}
list = lp_wins_server_list();
for (count=0; list && list[count]; count++)
/* nop */ ;
return count;
}
/* an internal convenience structure for an IP with a short string tag
attached */
struct tagged_ip {
fstring tag;
struct ipv4_addr ip;
};
/*
parse an IP string that might be in tagged format
the result is a tagged_ip structure containing the tag
and the ip in in_addr format. If there is no tag then
use the tag '*'
*/
static void parse_ip(TALLOC_CTX *mem_ctx, struct tagged_ip *ip, const char *str)
{
char *s = strchr(str, ':');
if (!s) {
fstrcpy(ip->tag, "*");
ip->ip = interpret_addr2(str);
return;
}
ip->ip = interpret_addr2(s+1);
fstrcpy(ip->tag, str);
s = strchr(ip->tag, ':');
if (s) *s = 0;
}
/*
return the list of wins server tags. A 'tag' is used to distinguish
wins server as either belonging to the same name space or a separate
name space. Usually you would setup your 'wins server' option to
list one or more wins server per interface and use the interface
name as your tag, but you are free to use any tag you like.
*/
char **wins_srv_tags(void)
{
char **ret = NULL;
int count=0, i, j;
const char **list;
TALLOC_CTX *mem_ctx;
if (lp_wins_support()) {
/* give the caller something to chew on. This makes
the rest of the logic simpler (ie. less special cases) */
ret = malloc_array_p(char *, 2);
if (!ret) return NULL;
ret[0] = strdup("*");
ret[1] = NULL;
return ret;
}
list = lp_wins_server_list();
if (!list)
return NULL;
mem_ctx = talloc_init("wins_ssrv_tags");
if (!mem_ctx) {
return NULL;
}
/* yes, this is O(n^2) but n is very small */
for (i=0;list[i];i++) {
struct tagged_ip t_ip;
parse_ip(mem_ctx, &t_ip, list[i]);
/* see if we already have it */
for (j=0;j<count;j++) {
if (strcmp(ret[j], t_ip.tag) == 0) {
break;
}
}
if (j != count) {
/* we already have it. Move along */
continue;
}
/* add it to the list */
ret = realloc_p(ret, char *, count+2);
ret[count] = strdup(t_ip.tag);
if (!ret[count]) break;
count++;
}
if (count) {
/* make sure we null terminate */
ret[count] = NULL;
}
return ret;
}
/* free a list of wins server tags given by wins_srv_tags */
void wins_srv_tags_free(char **list)
{
int i;
if (!list) return;
for (i=0; list[i]; i++) {
free(list[i]);
}
free(list);
}
/*
return the IP of the currently active wins server for the given tag,
or the zero IP otherwise
*/
struct ipv4_addr wins_srv_ip_tag(const char *tag, struct ipv4_addr src_ip)
{
const char **list;
int i;
struct tagged_ip t_ip;
TALLOC_CTX *mem_ctx;
/* if we are a wins server then we always just talk to ourselves */
if (lp_wins_support()) {
extern struct ipv4_addr loopback_ip;
return loopback_ip;
}
list = lp_wins_server_list();
if (!list || !list[0]) {
struct ipv4_addr ip;
zero_ip(&ip);
return ip;
}
mem_ctx = talloc_init("wins_srv_ip_tag");
/* find the first live one for this tag */
for (i=0; list[i]; i++) {
parse_ip(mem_ctx, &t_ip, list[i]);
if (strcmp(tag, t_ip.tag) != 0) {
/* not for the right tag. Move along */
continue;
}
if (!wins_srv_is_dead(t_ip.ip, src_ip)) {
char *src_name;
src_name = talloc_strdup(mem_ctx, sys_inet_ntoa(src_ip));
DEBUG(6,("Current wins server for tag '%s' with source %s is %s\n",
tag,
src_name,
sys_inet_ntoa(t_ip.ip)));
goto exit;
}
}
/* they're all dead - try the first one until they revive */
for (i=0; list[i]; i++) {
parse_ip(mem_ctx, &t_ip, list[i]);
if (strcmp(tag, t_ip.tag) != 0) {
continue;
}
goto exit;
}
/* this can't happen?? */
zero_ip(&t_ip.ip);
exit:
talloc_destroy(mem_ctx);
return t_ip.ip;
}
/*
return a count of the number of IPs for a particular tag, including
dead ones
*/
uint_t wins_srv_count_tag(const char *tag)
{
const char **list;
int i, count=0;
TALLOC_CTX *mem_ctx;
/* if we are a wins server then we always just talk to ourselves */
if (lp_wins_support()) {
return 1;
}
list = lp_wins_server_list();
if (!list || !list[0]) {
return 0;
}
/* find the first live one for this tag */
mem_ctx = talloc_init("wins_srv_count_tag");
if (!mem_ctx) {
return 0;
}
for (i=0; list[i]; i++) {
struct tagged_ip t_ip;
parse_ip(mem_ctx, &t_ip, list[i]);
if (strcmp(tag, t_ip.tag) == 0) {
count++;
}
}
talloc_destroy(mem_ctx);
return count;
}

View File

@@ -30,7 +30,9 @@ REQUIRED_SUBSYSTEMS = NDR_NBT
[SUBSYSTEM::LIBCLI_RESOLVE] [SUBSYSTEM::LIBCLI_RESOLVE]
ADD_OBJ_FILES = \ ADD_OBJ_FILES = \
libcli/resolve/resolve.o \ libcli/resolve/resolve.o \
libcli/resolve/bcast.o libcli/resolve/nbtlist.o \
libcli/resolve/bcast.o \
libcli/resolve/wins.o
REQUIRED_SUBSYSTEMS = LIBCLI_NBT REQUIRED_SUBSYSTEMS = LIBCLI_NBT
[SUBSYSTEM::LIBCLI] [SUBSYSTEM::LIBCLI]

View File

@@ -331,7 +331,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
/* we select a random transaction id unless the user supplied one */ /* we select a random transaction id unless the user supplied one */
if (req->request->name_trn_id == 0) { if (req->request->name_trn_id == 0) {
req->request->name_trn_id = random() % UINT16_MAX; req->request->name_trn_id = generate_random() % UINT16_MAX;
} }
/* choose the next available transaction id >= the one asked for. /* choose the next available transaction id >= the one asked for.
@@ -342,7 +342,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
id = idr_get_new_above(req->nbtsock->idr, req, id = idr_get_new_above(req->nbtsock->idr, req,
req->request->name_trn_id, UINT16_MAX); req->request->name_trn_id, UINT16_MAX);
if (id == -1) { if (id == -1) {
id = idr_get_new_above(req->nbtsock->idr, req, 1+(random()%(UINT16_MAX/2)), id = idr_get_new_above(req->nbtsock->idr, req, 1+(generate_random()%(UINT16_MAX/2)),
UINT16_MAX); UINT16_MAX);
} }
if (id == -1) goto failed; if (id == -1) goto failed;

View File

@@ -23,112 +23,36 @@
#include "includes.h" #include "includes.h"
#include "system/network.h" #include "system/network.h"
#include "libcli/raw/libcliraw.h" #include "libcli/raw/libcliraw.h"
#include "libcli/nbt/libnbt.h"
#include "libcli/composite/composite.h" #include "libcli/composite/composite.h"
struct bcast_state {
struct nbt_name name;
struct nbt_name_socket *nbtsock;
int num_queries;
struct nbt_name_request **queries;
struct nbt_name_query *io_queries;
const char *reply_addr;
};
/*
handle events during broadcast name resolution
*/
static void bcast_handler(struct nbt_name_request *req)
{
struct smbcli_composite *c = talloc_get_type(req->async.private,
struct smbcli_composite);
struct bcast_state *state = talloc_get_type(c->private, struct bcast_state);
int i;
for (i=0;i<state->num_queries;i++) {
if (req == state->queries[i]) break;
}
if (i == state->num_queries) {
/* not for us?! */
c->status = NT_STATUS_INTERNAL_ERROR;
c->state = SMBCLI_REQUEST_ERROR;
goto done;
}
c->status = nbt_name_query_recv(req, state, &state->io_queries[i]);
if (!NT_STATUS_IS_OK(c->status)) {
c->state = SMBCLI_REQUEST_ERROR;
} else {
c->state = SMBCLI_REQUEST_DONE;
state->reply_addr = talloc_steal(state, state->io_queries[i].out.reply_addr);
}
done:
talloc_free(state->nbtsock);
if (c->async.fn) {
c->async.fn(c);
}
}
/* /*
broadcast name resolution method - async send broadcast name resolution method - async send
*/ */
struct smbcli_composite *resolve_name_bcast_send(struct nbt_name *name, struct smbcli_composite *resolve_name_bcast_send(struct nbt_name *name,
struct event_context *event_ctx) struct event_context *event_ctx)
{ {
int num_interfaces = iface_count();
const char **address_list;
struct smbcli_composite *c; struct smbcli_composite *c;
struct bcast_state *state;
int i; int i;
NTSTATUS status;
c = talloc_zero(NULL, struct smbcli_composite); address_list = talloc_array(NULL, const char *, num_interfaces+1);
if (c == NULL) goto failed; if (address_list == NULL) return NULL;
state = talloc(c, struct bcast_state); for (i=0;i<num_interfaces;i++) {
if (state == NULL) goto failed;
status = nbt_name_dup(state, name, &state->name);
if (!NT_STATUS_IS_OK(status)) goto failed;
state->nbtsock = nbt_name_socket_init(state, event_ctx);
if (state->nbtsock == NULL) goto failed;
state->num_queries = iface_count();
state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
if (!state->io_queries) goto failed;
state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
if (!state->queries) goto failed;
for (i=0;i<state->num_queries;i++) {
struct ipv4_addr *ip = iface_n_bcast(i); struct ipv4_addr *ip = iface_n_bcast(i);
const char *addr = sys_inet_ntoa(*ip); address_list[i] = talloc_strdup(address_list, sys_inet_ntoa(*ip));
if (!addr) goto failed; if (address_list[i] == NULL) {
talloc_free(address_list);
state->io_queries[i].in.name = state->name; return NULL;
state->io_queries[i].in.dest_addr = talloc_strdup(state->io_queries, addr); }
if (!state->io_queries[i].in.dest_addr) goto failed;
state->io_queries[i].in.broadcast = True;
state->io_queries[i].in.wins_lookup = False;
state->io_queries[i].in.timeout = lp_parm_int(-1, "nbt", "bcastTimeout", 5);
state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
if (!state->queries[i]) goto failed;
state->queries[i]->async.fn = bcast_handler;
state->queries[i]->async.private = c;
} }
address_list[i] = NULL;
c->state = SMBCLI_REQUEST_SEND; c = resolve_name_nbtlist_send(name, event_ctx, address_list, True, False);
c->private = state; talloc_free(address_list);
c->event_ctx = talloc_reference(c, state->nbtsock->event_ctx);
return c; return c;
failed:
talloc_free(c);
return NULL;
} }
/* /*
@@ -137,17 +61,7 @@ failed:
NTSTATUS resolve_name_bcast_recv(struct smbcli_composite *c, NTSTATUS resolve_name_bcast_recv(struct smbcli_composite *c,
TALLOC_CTX *mem_ctx, const char **reply_addr) TALLOC_CTX *mem_ctx, const char **reply_addr)
{ {
NTSTATUS status; return resolve_name_nbtlist_recv(c, mem_ctx, reply_addr);
status = smb_composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
struct bcast_state *state = talloc_get_type(c->private, struct bcast_state);
*reply_addr = talloc_steal(mem_ctx, state->reply_addr);
}
talloc_free(c);
return status;
} }
/* /*

View File

@@ -0,0 +1,170 @@
/*
Unix SMB/CIFS implementation.
nbt list of addresses name resolution module
Copyright (C) Andrew Tridgell 2005
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.
*/
/*
TODO: we should lower the timeout, and add retries for each name
*/
#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/nbt/libnbt.h"
#include "libcli/composite/composite.h"
struct nbtlist_state {
struct nbt_name name;
struct nbt_name_socket *nbtsock;
int num_queries;
struct nbt_name_request **queries;
struct nbt_name_query *io_queries;
const char *reply_addr;
};
/*
handle events during nbtlist name resolution
*/
static void nbtlist_handler(struct nbt_name_request *req)
{
struct smbcli_composite *c = talloc_get_type(req->async.private,
struct smbcli_composite);
struct nbtlist_state *state = talloc_get_type(c->private, struct nbtlist_state);
int i;
for (i=0;i<state->num_queries;i++) {
if (req == state->queries[i]) break;
}
if (i == state->num_queries) {
/* not for us?! */
c->status = NT_STATUS_INTERNAL_ERROR;
c->state = SMBCLI_REQUEST_ERROR;
goto done;
}
c->status = nbt_name_query_recv(req, state, &state->io_queries[i]);
if (!NT_STATUS_IS_OK(c->status)) {
c->state = SMBCLI_REQUEST_ERROR;
} else {
c->state = SMBCLI_REQUEST_DONE;
state->reply_addr = talloc_steal(state, state->io_queries[i].out.reply_addr);
}
done:
talloc_free(state->nbtsock);
if (c->async.fn) {
c->async.fn(c);
}
}
/*
nbtlist name resolution method - async send
*/
struct smbcli_composite *resolve_name_nbtlist_send(struct nbt_name *name,
struct event_context *event_ctx,
const char **address_list,
BOOL broadcast,
BOOL wins_lookup)
{
struct smbcli_composite *c;
struct nbtlist_state *state;
int i;
NTSTATUS status;
c = talloc_zero(NULL, struct smbcli_composite);
if (c == NULL) goto failed;
state = talloc(c, struct nbtlist_state);
if (state == NULL) goto failed;
status = nbt_name_dup(state, name, &state->name);
if (!NT_STATUS_IS_OK(status)) goto failed;
state->nbtsock = nbt_name_socket_init(state, event_ctx);
if (state->nbtsock == NULL) goto failed;
/* count the address_list size */
for (i=0;address_list[i];i++) /* noop */ ;
state->num_queries = i;
state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
if (!state->io_queries) goto failed;
state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
if (!state->queries) goto failed;
for (i=0;i<state->num_queries;i++) {
state->io_queries[i].in.name = state->name;
state->io_queries[i].in.dest_addr = talloc_strdup(state->io_queries, address_list[i]);
if (!state->io_queries[i].in.dest_addr) goto failed;
state->io_queries[i].in.broadcast = broadcast;
state->io_queries[i].in.wins_lookup = wins_lookup;
state->io_queries[i].in.timeout = lp_parm_int(-1, "nbt", "timeout", 3);
state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
if (!state->queries[i]) goto failed;
state->queries[i]->async.fn = nbtlist_handler;
state->queries[i]->async.private = c;
}
c->state = SMBCLI_REQUEST_SEND;
c->private = state;
c->event_ctx = talloc_reference(c, state->nbtsock->event_ctx);
return c;
failed:
talloc_free(c);
return NULL;
}
/*
nbt list of addresses name resolution method - recv side
*/
NTSTATUS resolve_name_nbtlist_recv(struct smbcli_composite *c,
TALLOC_CTX *mem_ctx, const char **reply_addr)
{
NTSTATUS status;
status = smb_composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
struct nbtlist_state *state = talloc_get_type(c->private, struct nbtlist_state);
*reply_addr = talloc_steal(mem_ctx, state->reply_addr);
}
talloc_free(c);
return status;
}
/*
nbt list of addresses name resolution method - sync call
*/
NTSTATUS resolve_name_nbtlist(struct nbt_name *name,
TALLOC_CTX *mem_ctx,
const char **address_list,
BOOL broadcast, BOOL wins_lookup,
const char **reply_addr)
{
struct smbcli_composite *c = resolve_name_nbtlist_send(name, NULL, address_list,
broadcast, wins_lookup);
return resolve_name_nbtlist_recv(c, mem_ctx, reply_addr);
}

View File

@@ -24,12 +24,111 @@
#include "libcli/raw/libcliraw.h" #include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h" #include "libcli/composite/composite.h"
struct resolve_state {
struct nbt_name name;
const char **methods;
struct smbcli_composite *req;
const char *reply_addr;
};
static struct smbcli_composite *setup_next_method(struct smbcli_composite *c);
/*
handle completion of one name resolve method
*/
static void resolve_handler(struct smbcli_composite *req)
{
struct smbcli_composite *c = req->async.private;
struct resolve_state *state = talloc_get_type(c->private, struct resolve_state);
const char *method = state->methods[0];
if (strcasecmp(method, "bcast")) {
c->status = resolve_name_bcast_recv(req, state, &state->reply_addr);
} else if (strcasecmp(method, "wins")) {
c->status = resolve_name_wins_recv(req, state, &state->reply_addr);
} else {
c->status = NT_STATUS_INTERNAL_ERROR;
}
if (!NT_STATUS_IS_OK(c->status)) {
state->methods++;
state->req = setup_next_method(c);
if (state->req != NULL) {
return;
}
}
if (!NT_STATUS_IS_OK(c->status)) {
c->state = SMBCLI_REQUEST_ERROR;
} else {
c->state = SMBCLI_REQUEST_DONE;
}
if (c->async.fn) {
c->async.fn(c);
}
}
static struct smbcli_composite *setup_next_method(struct smbcli_composite *c)
{
struct resolve_state *state = talloc_get_type(c->private, struct resolve_state);
const char *method;
struct smbcli_composite *req = NULL;
do {
method = state->methods[0];
if (method == NULL) break;
if (strcasecmp(method, "bcast")) {
req = resolve_name_bcast_send(&state->name, c->event_ctx);
} else if (strcasecmp(method, "wins")) {
req = resolve_name_wins_send(&state->name, c->event_ctx);
}
if (req == NULL) state->methods++;
} while (!req && state->methods[0]);
if (req) {
req->async.fn = resolve_handler;
req->async.private = c;
}
return req;
}
/* /*
general name resolution - async send general name resolution - async send
*/ */
struct smbcli_composite *resolve_name_send(struct nbt_name *name, struct event_context *event_ctx) struct smbcli_composite *resolve_name_send(struct nbt_name *name, struct event_context *event_ctx)
{ {
return resolve_name_bcast_send(name, event_ctx); struct smbcli_composite *c;
struct resolve_state *state;
NTSTATUS status;
c = talloc_zero(NULL, struct smbcli_composite);
if (c == NULL) goto failed;
state = talloc(c, struct resolve_state);
if (state == NULL) goto failed;
status = nbt_name_dup(state, name, &state->name);
if (!NT_STATUS_IS_OK(status)) goto failed;
state->methods = lp_name_resolve_order();
if (state->methods == NULL) {
return NULL;
}
c->state = SMBCLI_REQUEST_SEND;
c->private = state;
c->event_ctx = talloc_reference(c, event_ctx);
state->req = setup_next_method(c);
if (state->req == NULL) goto failed;
return c;
failed:
talloc_free(c);
return NULL;
} }
/* /*
@@ -38,7 +137,17 @@ struct smbcli_composite *resolve_name_send(struct nbt_name *name, struct event_c
NTSTATUS resolve_name_recv(struct smbcli_composite *c, NTSTATUS resolve_name_recv(struct smbcli_composite *c,
TALLOC_CTX *mem_ctx, const char **reply_addr) TALLOC_CTX *mem_ctx, const char **reply_addr)
{ {
return resolve_name_bcast_recv(c, mem_ctx, reply_addr); NTSTATUS status;
status = smb_composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
struct resolve_state *state = talloc_get_type(c->private, struct resolve_state);
*reply_addr = talloc_steal(mem_ctx, state->reply_addr);
}
talloc_free(c);
return status;
} }
/* /*

View File

@@ -0,0 +1,58 @@
/*
Unix SMB/CIFS implementation.
wins name resolution module
Copyright (C) Andrew Tridgell 2005
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"
#include "system/network.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
/*
wins name resolution method - async send
*/
struct smbcli_composite *resolve_name_wins_send(struct nbt_name *name,
struct event_context *event_ctx)
{
const char **address_list = lp_wins_server_list();
if (address_list == NULL) return NULL;
return resolve_name_nbtlist_send(name, event_ctx, address_list, False, True);
}
/*
wins name resolution method - recv side
*/
NTSTATUS resolve_name_wins_recv(struct smbcli_composite *c,
TALLOC_CTX *mem_ctx, const char **reply_addr)
{
return resolve_name_nbtlist_recv(c, mem_ctx, reply_addr);
}
/*
wins name resolution method - sync call
*/
NTSTATUS resolve_name_wins(struct nbt_name *name,
TALLOC_CTX *mem_ctx,
const char **reply_addr)
{
struct smbcli_composite *c = resolve_name_wins_send(name, NULL);
return resolve_name_wins_recv(c, mem_ctx, reply_addr);
}

View File

@@ -190,7 +190,7 @@ typedef struct
char **szNetbiosAliases; char **szNetbiosAliases;
char *szNetbiosScope; char *szNetbiosScope;
char *szDomainOtherSIDs; char *szDomainOtherSIDs;
char *szNameResolveOrder; char **szNameResolveOrder;
char *szPanicAction; char *szPanicAction;
char *szAddUserScript; char *szAddUserScript;
char *szAddMachineScript; char *szAddMachineScript;
@@ -627,7 +627,7 @@ static struct parm_struct parm_table[] = {
{"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
{"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
@@ -1164,7 +1164,7 @@ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram) FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat) FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers) FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder) FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
FN_GLOBAL_STRING(lp_realm, &Globals.szRealm) FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver) FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options) FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)