Use global iconv convenience rather than global loadparm.
[ira/wip.git] / source4 / libcli / resolve / nbtlist.c
index f8fe5df9a1bd39e6a10dd34bc23d8366676f0ffc..ec4cfb81b414fe5b2a368c4f896d18112c24a5a3 100644 (file)
@@ -7,7 +7,7 @@
    
    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,
@@ -16,8 +16,7 @@
    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/raw/libcliraw.h"
-#include "libcli/nbt/libnbt.h"
 #include "libcli/composite/composite.h"
+#include "system/network.h"
+#include "lib/socket/netif.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "../libcli/nbt/libnbt.h"
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
 
 struct nbtlist_state {
        struct nbt_name name;
@@ -36,6 +39,7 @@ struct nbtlist_state {
        struct nbt_name_request **queries;
        struct nbt_name_query *io_queries;
        const char *reply_addr;
+       struct interface *ifaces;
 };
 
 /*
@@ -43,9 +47,10 @@ struct nbtlist_state {
 */
 static void nbtlist_handler(struct nbt_name_request *req)
 {
-       struct composite_context *c = talloc_get_type(req->async.private
+       struct composite_context *c = talloc_get_type(req->async.private_data,
                                                      struct composite_context);
        struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
+       struct nbt_name_query *q;
        int i;
 
        for (i=0;i<state->num_queries;i++) {
@@ -54,117 +59,121 @@ static void nbtlist_handler(struct nbt_name_request *req)
 
        if (i == state->num_queries) {
                /* not for us?! */
-               c->status = NT_STATUS_INTERNAL_ERROR;
-               c->state = COMPOSITE_STATE_ERROR;               
-               goto done;
+               composite_error(c, NT_STATUS_INTERNAL_ERROR);
+               return;
        }
 
-       c->status = nbt_name_query_recv(req, state, &state->io_queries[i]);
-       if (!NT_STATUS_IS_OK(c->status)) {
-               c->state = COMPOSITE_STATE_ERROR;
-
-       } else {
-               if (state->io_queries[i].out.num_addrs < 1) {
-                       c->state = COMPOSITE_STATE_ERROR;
-                       c->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
-
-               } else {
-                       struct nbt_name_query *q = &state->io_queries[i];
-                       c->state = COMPOSITE_STATE_DONE;
-                       /* favor a local address if possible */
-                       state->reply_addr = NULL;
-
-                       for (i=0;i<q->out.num_addrs;i++) {
-                               if (iface_is_local(q->out.reply_addrs[i])) {
-                                       state->reply_addr = talloc_steal(state, 
-                                                                        q->out.reply_addrs[i]);
-                                       break;
-                               }
-                       }
-
-                       if (state->reply_addr == NULL) {
-                               state->reply_addr = talloc_steal(state, 
-                                                                q->out.reply_addrs[0]);
-                       }
+       q = &state->io_queries[i];
+
+       c->status = nbt_name_query_recv(req, state, q);
+
+       /* free the network resource directly */
+       talloc_free(state->nbtsock);
+       if (!composite_is_ok(c)) return;
+
+       if (state->io_queries[i].out.num_addrs < 1) {
+               composite_error(c, NT_STATUS_UNEXPECTED_NETWORK_ERROR);
+               return;
+       }
+
+       /* favor a local address if possible */
+       state->reply_addr = NULL;
+       for (i=0;i<q->out.num_addrs;i++) {
+               if (iface_is_local(state->ifaces, q->out.reply_addrs[i])) {
+                       state->reply_addr = talloc_steal(state, 
+                                                        q->out.reply_addrs[i]);
+                       break;
                }
        }
 
-done:
-       talloc_free(state->nbtsock);
-       if (c->async.fn) {
-               c->async.fn(c);
+       if (state->reply_addr == NULL) {
+               state->reply_addr = talloc_steal(state, 
+                                                q->out.reply_addrs[0]);
        }
+
+       composite_done(c);
 }
 
 /*
   nbtlist name resolution method - async send
  */
-struct composite_context *resolve_name_nbtlist_send(struct nbt_name *name, 
-                                                  struct event_context *event_ctx,
-                                                  const char **address_list,
-                                                  BOOL broadcast,
-                                                  BOOL wins_lookup)
+struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx,
+                                                   struct event_context *event_ctx,
+                                                   struct nbt_name *name, 
+                                                   const char **address_list,
+                                                   struct interface *ifaces,
+                                                   uint16_t nbt_port,
+                                                   int nbt_timeout,
+                                                   bool broadcast,
+                                                   bool wins_lookup)
 {
        struct composite_context *c;
        struct nbtlist_state *state;
        int i;
-       NTSTATUS status;
 
-       c = talloc_zero(NULL, struct composite_context);
-       if (c == NULL) goto failed;
+       c = composite_create(mem_ctx, event_ctx);
+       if (c == NULL) return NULL;
+
+       if (composite_nomem(c->event_ctx, c)) return c;
 
        state = talloc(c, struct nbtlist_state);
-       if (state == NULL) goto failed;
+       if (composite_nomem(state, c)) return c;
+       c->private_data = state;
 
-       status = nbt_name_dup(state, name, &state->name);
-       if (!NT_STATUS_IS_OK(status)) goto failed;
+       c->status = nbt_name_dup(state, name, &state->name);
+       if (!composite_is_ok(c)) return c;
 
        state->name.name = strupper_talloc(state, state->name.name);
-       if (state->name.name == NULL) goto failed;
+       if (composite_nomem(state->name.name, c)) return c;
        if (state->name.scope) {
                state->name.scope = strupper_talloc(state, state->name.scope);
-               if (state->name.scope == NULL) goto failed;
+               if (composite_nomem(state->name.scope, c)) return c;
+       }
+
+       state->ifaces = talloc_reference(state, ifaces);
+
+       /*
+        * we can't push long names on the wire,
+        * so bail out here to give a useful error message
+        */
+       if (strlen(state->name.name) > 15) {
+               composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+               return c;
        }
 
-       state->nbtsock = nbt_name_socket_init(state, event_ctx);
-       if (state->nbtsock == NULL) goto failed;
+       state->nbtsock = nbt_name_socket_init(state, event_ctx, 
+                                             global_iconv_convenience);
+       if (composite_nomem(state->nbtsock, c)) return c;
 
        /* 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;
+       if (composite_nomem(state->io_queries, c)) return c;
 
        state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
-       if (!state->queries) goto failed;
+       if (composite_nomem(state->queries, c)) return c;
 
        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.dest_port   = nbt_port;
+               if (composite_nomem(state->io_queries[i].in.dest_addr, c)) return c;
 
                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", 1);
+               state->io_queries[i].in.timeout     = nbt_timeout;
                state->io_queries[i].in.retries     = 2;
 
                state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
-               if (!state->queries[i]) goto failed;
+               if (composite_nomem(state->queries[i], c)) return c;
 
                state->queries[i]->async.fn      = nbtlist_handler;
-               state->queries[i]->async.private = c;
+               state->queries[i]->async.private_data = c;
        }
 
-       c->state = COMPOSITE_STATE_IN_PROGRESS;
-       c->private_data = state;
-       c->event_ctx = talloc_reference(c, state->nbtsock->event_ctx);
-
        return c;
-
-failed:
-       talloc_free(c);
-       return NULL;
 }
 
 /*
@@ -192,11 +201,17 @@ NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c,
 NTSTATUS resolve_name_nbtlist(struct nbt_name *name, 
                              TALLOC_CTX *mem_ctx,
                              const char **address_list,
-                             BOOL broadcast, BOOL wins_lookup,
+                             struct interface *ifaces, 
+                             uint16_t nbt_port,
+                             int nbt_timeout,
+                             bool broadcast, bool wins_lookup,
                              const char **reply_addr)
 {
-       struct composite_context *c = resolve_name_nbtlist_send(name, NULL, address_list, 
-                                                              broadcast, wins_lookup);
+       struct composite_context *c = resolve_name_nbtlist_send(mem_ctx, NULL, 
+                                                               name, address_list, 
+                                                               ifaces, nbt_port,
+                                                               nbt_timeout,
+                                                               broadcast, wins_lookup);
        return resolve_name_nbtlist_recv(c, mem_ctx, reply_addr);
 }