root/source4/libcli/resolve/nbtlist.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nbtlist_handler
  2. resolve_name_nbtlist_send
  3. resolve_name_nbtlist_recv

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    nbt list of addresses name resolution module
   5 
   6    Copyright (C) Andrew Tridgell 2005
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 /*
  23   TODO: we should lower the timeout, and add retries for each name
  24 */
  25 
  26 #include "includes.h"
  27 #include "libcli/composite/composite.h"
  28 #include "system/network.h"
  29 #include "lib/socket/socket.h"
  30 #include "lib/socket/netif.h"
  31 #include "librpc/gen_ndr/ndr_nbt.h"
  32 #include "../libcli/nbt/libnbt.h"
  33 #include "param/param.h"
  34 #include "libcli/resolve/resolve.h"
  35 
  36 struct nbtlist_state {
  37         uint16_t flags;
  38         uint16_t port;
  39         struct nbt_name name;
  40         struct nbt_name_socket *nbtsock;
  41         int num_queries;
  42         struct nbt_name_request **queries;
  43         struct nbt_name_query *io_queries;
  44         struct socket_address **addrs;
  45         char **names;
  46         struct interface *ifaces;
  47 };
  48 
  49 /*
  50   handle events during nbtlist name resolution
  51 */
  52 static void nbtlist_handler(struct nbt_name_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  53 {
  54         struct composite_context *c = talloc_get_type(req->async.private_data,
  55                                                       struct composite_context);
  56         struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
  57         struct nbt_name_query *q;
  58         int i;
  59 
  60         for (i=0;i<state->num_queries;i++) {
  61                 if (req == state->queries[i]) break;
  62         }
  63 
  64         if (i == state->num_queries) {
  65                 /* not for us?! */
  66                 composite_error(c, NT_STATUS_INTERNAL_ERROR);
  67                 return;
  68         }
  69 
  70         q = &state->io_queries[i];
  71 
  72         c->status = nbt_name_query_recv(req, state, q);
  73 
  74         /* free the network resource directly */
  75         talloc_free(state->nbtsock);
  76         if (!composite_is_ok(c)) return;
  77 
  78         if (q->out.num_addrs < 1) {
  79                 composite_error(c, NT_STATUS_UNEXPECTED_NETWORK_ERROR);
  80                 return;
  81         }
  82 
  83         state->addrs = talloc_array(state, struct socket_address *,
  84                                     q->out.num_addrs + 1);
  85         if (composite_nomem(state->addrs, c)) return;
  86 
  87         state->names = talloc_array(state, char *, q->out.num_addrs + 1);
  88         if (composite_nomem(state->names, c)) return;
  89 
  90         for (i=0;i<q->out.num_addrs;i++) {
  91                 state->addrs[i] = socket_address_from_strings(state->addrs,
  92                                                               "ipv4",
  93                                                               q->out.reply_addrs[i],
  94                                                               state->port);
  95                 if (composite_nomem(state->addrs[i], c)) return;
  96 
  97                 state->names[i] = talloc_strdup(state->names, state->name.name);
  98                 if (composite_nomem(state->names[i], c)) return;
  99         }
 100         state->addrs[i] = NULL;
 101         state->names[i] = NULL;
 102 
 103         composite_done(c);
 104 }
 105 
 106 /*
 107   nbtlist name resolution method - async send
 108  */
 109 struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 110                                                     struct tevent_context *event_ctx,
 111                                                     uint32_t flags,
 112                                                     uint16_t port,
 113                                                     struct nbt_name *name, 
 114                                                     const char **address_list,
 115                                                     struct interface *ifaces,
 116                                                     uint16_t nbt_port,
 117                                                     int nbt_timeout,
 118                                                     bool broadcast,
 119                                                     bool wins_lookup)
 120 {
 121         struct composite_context *c;
 122         struct nbtlist_state *state;
 123         int i;
 124 
 125         c = composite_create(mem_ctx, event_ctx);
 126         if (c == NULL) return NULL;
 127 
 128         if (flags & RESOLVE_NAME_FLAG_FORCE_DNS) {
 129                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 130                 return c;
 131         }
 132 
 133         if (strlen(name->name) > 15) {
 134                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 135                 return c;
 136         }
 137 
 138         state = talloc(c, struct nbtlist_state);
 139         if (composite_nomem(state, c)) return c;
 140         c->private_data = state;
 141 
 142         state->flags = flags;
 143         state->port = port;
 144 
 145         c->status = nbt_name_dup(state, name, &state->name);
 146         if (!composite_is_ok(c)) return c;
 147 
 148         state->name.name = strupper_talloc(state, state->name.name);
 149         if (composite_nomem(state->name.name, c)) return c;
 150         if (state->name.scope) {
 151                 state->name.scope = strupper_talloc(state, state->name.scope);
 152                 if (composite_nomem(state->name.scope, c)) return c;
 153         }
 154 
 155         state->ifaces = talloc_reference(state, ifaces);
 156 
 157         /*
 158          * we can't push long names on the wire,
 159          * so bail out here to give a useful error message
 160          */
 161         if (strlen(state->name.name) > 15) {
 162                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 163                 return c;
 164         }
 165 
 166         state->nbtsock = nbt_name_socket_init(state, event_ctx, 
 167                                               global_iconv_convenience);
 168         if (composite_nomem(state->nbtsock, c)) return c;
 169 
 170         /* count the address_list size */
 171         for (i=0;address_list[i];i++) /* noop */ ;
 172 
 173         state->num_queries = i;
 174         state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
 175         if (composite_nomem(state->io_queries, c)) return c;
 176 
 177         state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
 178         if (composite_nomem(state->queries, c)) return c;
 179 
 180         for (i=0;i<state->num_queries;i++) {
 181                 state->io_queries[i].in.name        = state->name;
 182                 state->io_queries[i].in.dest_addr   = talloc_strdup(state->io_queries, address_list[i]);
 183                 state->io_queries[i].in.dest_port   = nbt_port;
 184                 if (composite_nomem(state->io_queries[i].in.dest_addr, c)) return c;
 185 
 186                 state->io_queries[i].in.broadcast   = broadcast;
 187                 state->io_queries[i].in.wins_lookup = wins_lookup;
 188                 state->io_queries[i].in.timeout     = nbt_timeout;
 189                 state->io_queries[i].in.retries     = 2;
 190 
 191                 state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
 192                 if (composite_nomem(state->queries[i], c)) return c;
 193 
 194                 state->queries[i]->async.fn      = nbtlist_handler;
 195                 state->queries[i]->async.private_data = c;
 196         }
 197 
 198         return c;
 199 }
 200 
 201 /*
 202   nbt list of addresses name resolution method - recv side
 203  */
 204 NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c, 
     /* [<][>][^][v][top][bottom][index][help] */
 205                                    TALLOC_CTX *mem_ctx,
 206                                    struct socket_address ***addrs,
 207                                    char ***names)
 208 {
 209         NTSTATUS status;
 210 
 211         status = composite_wait(c);
 212 
 213         if (NT_STATUS_IS_OK(status)) {
 214                 struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
 215                 *addrs = talloc_steal(mem_ctx, state->addrs);
 216                 if (names) {
 217                         *names = talloc_steal(mem_ctx, state->names);
 218                 }
 219         }
 220 
 221         talloc_free(c);
 222         return status;
 223 }
 224 

/* [<][>][^][v][top][bottom][index][help] */