r4898: - removed the unused wins_srv_*() code
authorAndrew Tridgell <tridge@samba.org>
Fri, 21 Jan 2005 13:13:24 +0000 (13:13 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:04 +0000 (13:09 -0500)
- 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 used to be commit 266fd2751c01808e5a18d4094032af50554ceb7a)

source4/lib/basic.mk
source4/lib/genrand.c
source4/lib/system.c
source4/lib/wins_srv.c [deleted file]
source4/libcli/config.mk
source4/libcli/nbt/nbtsocket.c
source4/libcli/resolve/bcast.c
source4/libcli/resolve/nbtlist.c [new file with mode: 0644]
source4/libcli/resolve/resolve.c
source4/libcli/resolve/wins.c [new file with mode: 0644]
source4/param/loadparm.c

index a14201d9be671e7bd5d20261d13a6f0619df6bec..ec6071e726209572f31138ad0b02c8c56557aa9b 100644 (file)
@@ -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 \
index e11f37e0e9f804be3aee76d0f94a0c9f92c2cbf7..aab42864e026daac7475bb5d930f41829553012f 100644 (file)
@@ -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;
@@ -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
 */
index 9fa71c449a77684b988732524f7ed0d8ef9b34a4..b23529f5fe0d5f409306beefea5b357b2978bc8f 100644 (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.
diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c
deleted file mode 100644 (file)
index 0338db8..0000000
+++ /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;
-}
index 21cfed898781d7f24cbfeb365a82962f08f48a11..904a07dc0fb5650722438e2cbc16c27e61fdb444 100644 (file)
@@ -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]
index 6d5b450a31fae43ddbb421f2efde174eeec7f983..865c542ca80e07fb0c3d552b899862bd496500da 100644 (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 */
        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;
index d424b5303aed84736f6e7e662a3c7484b83ce489..9aefa32fae7bf014b7e52c70f2e0fcbed277542e 100644 (file)
 #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 (file)
index 0000000..036e983
--- /dev/null
@@ -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);
+}
+
index e83b11c95e00b460ab10b8e5b1504e0f53276ead..b36d6e8ee6b2b00fc1c31a802e588c3368a8f653 100644 (file)
 #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 (file)
index 0000000..5a0e067
--- /dev/null
@@ -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);
+}
+
index 616cf50afb07734e47525ccaaf873a99be1533e8..0582d5551185eb4edcbd81ea254b3319ab50bc1c 100644 (file)
@@ -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)