summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/basic.mk1
-rw-r--r--source4/lib/genrand.c16
-rw-r--r--source4/lib/system.c31
-rw-r--r--source4/lib/wins_srv.c362
-rw-r--r--source4/libcli/config.mk4
-rw-r--r--source4/libcli/nbt/nbtsocket.c4
-rw-r--r--source4/libcli/resolve/bcast.c116
-rw-r--r--source4/libcli/resolve/nbtlist.c170
-rw-r--r--source4/libcli/resolve/resolve.c113
-rw-r--r--source4/libcli/resolve/wins.c58
-rw-r--r--source4/param/loadparm.c6
11 files changed, 375 insertions, 506 deletions
diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk
index a14201d9be..ec6071e726 100644
--- a/source4/lib/basic.mk
+++ b/source4/lib/basic.mk
@@ -48,7 +48,6 @@ ADD_OBJ_FILES = \
lib/username.o \
lib/dprintf.o \
lib/xfile.o \
- lib/wins_srv.o \
lib/util_str.o \
lib/util_strlist.o \
lib/util_unistr.o \
diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c
index e11f37e0e9..aab42864e0 100644
--- a/source4/lib/genrand.c
+++ b/source4/lib/genrand.c
@@ -192,10 +192,9 @@ static int do_reseed(BOOL use_fd, int fd)
return -1;
}
-/*******************************************************************
+/*
Interface to the (hopefully) good crypto random number generator.
-********************************************************************/
-
+*/
void generate_random_buffer(uint8_t *out, int len)
{
static int urand_fd = -1;
@@ -240,6 +239,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
*/
BOOL check_password_quality(const char *s)
diff --git a/source4/lib/system.c b/source4/lib/system.c
index 9fa71c449a..b23529f5fe 100644
--- a/source4/lib/system.c
+++ b/source4/lib/system.c
@@ -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.
diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c
deleted file mode 100644
index 0338db8b3d..0000000000
--- a/source4/lib/wins_srv.c
+++ /dev/null
@@ -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;
-}
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index 21cfed8987..904a07dc0f 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -30,7 +30,9 @@ REQUIRED_SUBSYSTEMS = NDR_NBT
[SUBSYSTEM::LIBCLI_RESOLVE]
ADD_OBJ_FILES = \
libcli/resolve/resolve.o \
- libcli/resolve/bcast.o
+ libcli/resolve/nbtlist.o \
+ libcli/resolve/bcast.o \
+ libcli/resolve/wins.o
REQUIRED_SUBSYSTEMS = LIBCLI_NBT
[SUBSYSTEM::LIBCLI]
diff --git a/source4/libcli/nbt/nbtsocket.c b/source4/libcli/nbt/nbtsocket.c
index 6d5b450a31..865c542ca8 100644
--- a/source4/libcli/nbt/nbtsocket.c
+++ b/source4/libcli/nbt/nbtsocket.c
@@ -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 */
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.
@@ -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,
req->request->name_trn_id, UINT16_MAX);
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);
}
if (id == -1) goto failed;
diff --git a/source4/libcli/resolve/bcast.c b/source4/libcli/resolve/bcast.c
index d424b5303a..9aefa32fae 100644
--- a/source4/libcli/resolve/bcast.c
+++ b/source4/libcli/resolve/bcast.c
@@ -23,112 +23,36 @@
#include "includes.h"
#include "system/network.h"
#include "libcli/raw/libcliraw.h"
-#include "libcli/nbt/libnbt.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
*/
struct smbcli_composite *resolve_name_bcast_send(struct nbt_name *name,
struct event_context *event_ctx)
{
+ int num_interfaces = iface_count();
+ const char **address_list;
struct smbcli_composite *c;
- struct bcast_state *state;
int i;
- NTSTATUS status;
-
- c = talloc_zero(NULL, struct smbcli_composite);
- if (c == NULL) goto failed;
- state = talloc(c, struct bcast_state);
- if (state == NULL) goto failed;
+ address_list = talloc_array(NULL, const char *, num_interfaces+1);
+ if (address_list == NULL) return NULL;
- 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++) {
+ for (i=0;i<num_interfaces;i++) {
struct ipv4_addr *ip = iface_n_bcast(i);
- const char *addr = sys_inet_ntoa(*ip);
- if (!addr) goto failed;
-
- state->io_queries[i].in.name = state->name;
- 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] = talloc_strdup(address_list, sys_inet_ntoa(*ip));
+ if (address_list[i] == NULL) {
+ talloc_free(address_list);
+ return NULL;
+ }
}
+ address_list[i] = NULL;
- c->state = SMBCLI_REQUEST_SEND;
- c->private = state;
- c->event_ctx = talloc_reference(c, state->nbtsock->event_ctx);
-
- return c;
+ c = resolve_name_nbtlist_send(name, event_ctx, address_list, True, False);
+ talloc_free(address_list);
-failed:
- talloc_free(c);
- return NULL;
+ return c;
}
/*
@@ -137,17 +61,7 @@ failed:
NTSTATUS resolve_name_bcast_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 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;
+ return resolve_name_nbtlist_recv(c, mem_ctx, reply_addr);
}
/*
diff --git a/source4/libcli/resolve/nbtlist.c b/source4/libcli/resolve/nbtlist.c
new file mode 100644
index 0000000000..036e983fd2
--- /dev/null
+++ b/source4/libcli/resolve/nbtlist.c
@@ -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);
+}
+
diff --git a/source4/libcli/resolve/resolve.c b/source4/libcli/resolve/resolve.c
index e83b11c95e..b36d6e8ee6 100644
--- a/source4/libcli/resolve/resolve.c
+++ b/source4/libcli/resolve/resolve.c
@@ -24,12 +24,111 @@
#include "libcli/raw/libcliraw.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
*/
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,
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;
}
/*
diff --git a/source4/libcli/resolve/wins.c b/source4/libcli/resolve/wins.c
new file mode 100644
index 0000000000..5a0e067832
--- /dev/null
+++ b/source4/libcli/resolve/wins.c
@@ -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);
+}
+
diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
index 616cf50afb..0582d55511 100644
--- a/source4/param/loadparm.c
+++ b/source4/param/loadparm.c
@@ -190,7 +190,7 @@ typedef struct
char **szNetbiosAliases;
char *szNetbiosScope;
char *szDomainOtherSIDs;
- char *szNameResolveOrder;
+ char **szNameResolveOrder;
char *szPanicAction;
char *szAddUserScript;
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 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 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},
@@ -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_chat, &Globals.szPasswdChat)
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_ads_server, &Globals.szADSserver)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)