s4:libcli/resolve: add resolve_name_all*() which return all addresses not only the...
[abartlet/samba.git/.git] / source4 / libcli / resolve / bcast.c
index d424b5303aed84736f6e7e662a3c7484b83ce489..0a71ebed99106fc11757c95178819775a3d7f843 100644 (file)
@@ -4,10 +4,11 @@
    broadcast name resolution module
 
    Copyright (C) Andrew Tridgell 2005
+   Copyright (C) Jelmer Vernooij 2007
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "libcli/resolve/resolve.h"
 #include "system/network.h"
-#include "libcli/raw/libcliraw.h"
-#include "libcli/nbt/libnbt.h"
-#include "libcli/composite/composite.h"
+#include "lib/socket/netif.h"
+#include "param/param.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;
+struct resolve_bcast_data {
+       struct interface *ifaces;
+       uint16_t nbt_port;
+       int nbt_timeout;
 };
 
-/*
-  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)
+struct composite_context *resolve_name_bcast_send(TALLOC_CTX *mem_ctx, 
+                                                 struct event_context *event_ctx,
+                                                 void *userdata,
+                                                 struct nbt_name *name)
 {
-       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;
-
-       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++) {
-               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;
+       int num_interfaces;
+       const char **address_list;
+       struct composite_context *c;
+       int i, count=0;
+       struct resolve_bcast_data *data = talloc_get_type(userdata, struct resolve_bcast_data);
+
+       num_interfaces = iface_count(data->ifaces);
+
+       address_list = talloc_array(mem_ctx, const char *, num_interfaces+1);
+       if (address_list == NULL) return NULL;
+
+       for (i=0;i<num_interfaces;i++) {
+               const char *bcast = iface_n_bcast(data->ifaces, i);
+               if (bcast == NULL) continue;
+               address_list[count] = talloc_strdup(address_list, bcast);
+               if (address_list[count] == NULL) {
+                       talloc_free(address_list);
+                       return NULL;
+               }
+               count++;
        }
+       address_list[count] = 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(mem_ctx, event_ctx, name, address_list, data->ifaces, data->nbt_port, data->nbt_timeout, true, false);
+       talloc_free(address_list);
 
-failed:
-       talloc_free(c);
-       return NULL;
+       return c;       
 }
 
 /*
   broadcast name resolution method - recv side
  */
-NTSTATUS resolve_name_bcast_recv(struct smbcli_composite *c, 
-                                TALLOC_CTX *mem_ctx, const char **reply_addr)
+NTSTATUS resolve_name_bcast_recv(struct composite_context *c, 
+                                TALLOC_CTX *mem_ctx,
+                                struct socket_address ***addrs)
 {
-       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);
+       NTSTATUS status = resolve_name_nbtlist_recv(c, mem_ctx, addrs);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+               /* this makes much more sense for a bcast name resolution
+                  timeout */
+               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
-
-       talloc_free(c);
        return status;
 }
 
@@ -155,9 +90,33 @@ NTSTATUS resolve_name_bcast_recv(struct smbcli_composite *c,
  */
 NTSTATUS resolve_name_bcast(struct nbt_name *name, 
                            TALLOC_CTX *mem_ctx,
-                           const char **reply_addr)
+                           struct interface *ifaces,
+                           uint16_t nbt_port,
+                           int nbt_timeout,
+                           struct socket_address ***addrs)
+{
+       struct resolve_bcast_data *data = talloc(mem_ctx, struct resolve_bcast_data);
+       struct composite_context *c;
+       data->ifaces = talloc_reference(data, ifaces);
+       data->nbt_port = nbt_port;
+       data->nbt_timeout = nbt_timeout;
+       
+       c = resolve_name_bcast_send(mem_ctx, NULL, data, name);
+       return resolve_name_bcast_recv(c, mem_ctx, addrs);
+}
+
+bool resolve_context_add_bcast_method(struct resolve_context *ctx, struct interface *ifaces, uint16_t nbt_port, int nbt_timeout)
 {
-       struct smbcli_composite *c = resolve_name_bcast_send(name, NULL);
-       return resolve_name_bcast_recv(c, mem_ctx, reply_addr);
+       struct resolve_bcast_data *data = talloc(ctx, struct resolve_bcast_data);
+       data->ifaces = ifaces;
+       data->nbt_port = nbt_port;
+       data->nbt_timeout = nbt_timeout;
+       return resolve_context_add_method(ctx, resolve_name_bcast_send, resolve_name_bcast_recv, data);
 }
 
+bool resolve_context_add_bcast_method_lp(struct resolve_context *ctx, struct loadparm_context *lp_ctx)
+{
+       struct interface *ifaces;
+       load_interfaces(ctx, lp_interfaces(lp_ctx), &ifaces);
+       return resolve_context_add_bcast_method(ctx, ifaces, lp_nbt_port(lp_ctx), lp_parm_int(lp_ctx, NULL, "nbt", "timeout", 1));
+}