summaryrefslogtreecommitdiff
path: root/source4/libcli/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libcli/resolve')
-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
4 files changed, 354 insertions, 103 deletions
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);
+}
+