From 6f0aef31cdfa9b486d1f2e0f097e071830f5600d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Jan 2005 13:13:24 +0000 Subject: r4898: - removed the unused wins_srv_*() code - expanded the generic async name resolver to try multiple methods - added wins resolutions to the list of methods tried - fixed up the random trn id generation to use the good random generator (This used to be commit 266fd2751c01808e5a18d4094032af50554ceb7a) --- source4/libcli/config.mk | 4 +- source4/libcli/nbt/nbtsocket.c | 4 +- source4/libcli/resolve/bcast.c | 116 ++++---------------------- source4/libcli/resolve/nbtlist.c | 170 +++++++++++++++++++++++++++++++++++++++ source4/libcli/resolve/resolve.c | 113 +++++++++++++++++++++++++- source4/libcli/resolve/wins.c | 58 +++++++++++++ 6 files changed, 359 insertions(+), 106 deletions(-) create mode 100644 source4/libcli/resolve/nbtlist.c create mode 100644 source4/libcli/resolve/wins.c (limited to 'source4/libcli') diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 21cfed89878..904a07dc0fb 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 6d5b450a31f..865c542ca80 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 d424b5303ae..9aefa32fae7 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;inum_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;inum_queries;i++) { + for (i=0;iio_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 00000000000..036e983fd21 --- /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;inum_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;inum_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 e83b11c95e0..b36d6e8ee6b 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 00000000000..5a0e067832d --- /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); +} + -- cgit