diff options
-rw-r--r-- | source4/lib/basic.mk | 1 | ||||
-rw-r--r-- | source4/lib/genrand.c | 16 | ||||
-rw-r--r-- | source4/lib/system.c | 31 | ||||
-rw-r--r-- | source4/lib/wins_srv.c | 362 | ||||
-rw-r--r-- | source4/libcli/config.mk | 4 | ||||
-rw-r--r-- | source4/libcli/nbt/nbtsocket.c | 4 | ||||
-rw-r--r-- | source4/libcli/resolve/bcast.c | 116 | ||||
-rw-r--r-- | source4/libcli/resolve/nbtlist.c | 170 | ||||
-rw-r--r-- | source4/libcli/resolve/resolve.c | 113 | ||||
-rw-r--r-- | source4/libcli/resolve/wins.c | 58 | ||||
-rw-r--r-- | source4/param/loadparm.c | 6 |
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) |