root/source4/libcli/resolve/resolve.c

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

DEFINITIONS

This source file includes following definitions.
  1. resolve_context_init
  2. resolve_context_add_method
  3. resolve_handler
  4. setup_next_method
  5. resolve_name_all_send
  6. resolve_name_all_recv
  7. resolve_name_send
  8. resolve_name_recv
  9. resolve_name
  10. make_nbt_name
  11. make_nbt_name_client
  12. make_nbt_name_server

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    general name resolution interface
   5 
   6    Copyright (C) Andrew Tridgell 2005
   7    Copyright (C) Jelmer Vernooij 2007
   8    
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 #include "libcli/composite/composite.h"
  25 #include "libcli/resolve/resolve.h"
  26 #include "librpc/gen_ndr/ndr_nbt.h"
  27 #include "system/network.h"
  28 #include "lib/socket/socket.h"
  29 #include "../lib/util/dlinklist.h"
  30 
  31 struct resolve_state {
  32         struct resolve_context *ctx;
  33         struct resolve_method *method;
  34         uint32_t flags;
  35         uint16_t port;
  36         struct nbt_name name;
  37         struct composite_context *creq;
  38         struct socket_address **addrs;
  39         char **names;
  40 };
  41 
  42 static struct composite_context *setup_next_method(struct composite_context *c);
  43 
  44 
  45 struct resolve_context {
  46         struct resolve_method {
  47                 resolve_name_send_fn send_fn;
  48                 resolve_name_recv_fn recv_fn;
  49                 void *privdata;
  50                 struct resolve_method *prev, *next;
  51         } *methods;
  52 };
  53 
  54 /**
  55  * Initialize a resolve context
  56  */
  57 struct resolve_context *resolve_context_init(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
  58 {
  59         return talloc_zero(mem_ctx, struct resolve_context);
  60 }
  61 
  62 /**
  63  * Add a resolve method
  64  */
  65 bool resolve_context_add_method(struct resolve_context *ctx, resolve_name_send_fn send_fn, 
     /* [<][>][^][v][top][bottom][index][help] */
  66                                 resolve_name_recv_fn recv_fn, void *userdata)
  67 {
  68         struct resolve_method *method = talloc_zero(ctx, struct resolve_method);
  69 
  70         if (method == NULL)
  71                 return false;
  72 
  73         method->send_fn = send_fn;
  74         method->recv_fn = recv_fn;
  75         method->privdata = userdata;
  76         DLIST_ADD_END(ctx->methods, method, struct resolve_method *);
  77         return true;
  78 }
  79 
  80 /**
  81   handle completion of one name resolve method
  82 */
  83 static void resolve_handler(struct composite_context *creq)
     /* [<][>][^][v][top][bottom][index][help] */
  84 {
  85         struct composite_context *c = (struct composite_context *)creq->async.private_data;
  86         struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
  87         const struct resolve_method *method = state->method;
  88 
  89         c->status = method->recv_fn(creq, state, &state->addrs, &state->names);
  90         
  91         if (!NT_STATUS_IS_OK(c->status)) {
  92                 state->method = state->method->next;
  93                 state->creq = setup_next_method(c);
  94                 if (state->creq != NULL) {
  95                         return;
  96                 }
  97         }
  98 
  99         if (!NT_STATUS_IS_OK(c->status)) {
 100                 c->state = COMPOSITE_STATE_ERROR;
 101         } else {
 102                 c->state = COMPOSITE_STATE_DONE;
 103         }
 104         if (c->async.fn) {
 105                 c->async.fn(c);
 106         }
 107 }
 108 
 109 
 110 static struct composite_context *setup_next_method(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 111 {
 112         struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
 113         struct composite_context *creq = NULL;
 114 
 115         do {
 116                 if (state->method) {
 117                         creq = state->method->send_fn(c, c->event_ctx,
 118                                                       state->method->privdata,
 119                                                       state->flags,
 120                                                       state->port,
 121                                                       &state->name);
 122                 }
 123                 if (creq == NULL && state->method) state->method = state->method->next;
 124 
 125         } while (!creq && state->method);
 126 
 127         if (creq) {
 128                 creq->async.fn = resolve_handler;
 129                 creq->async.private_data = c;
 130         }
 131 
 132         return creq;
 133 }
 134 
 135 /*
 136   general name resolution - async send
 137  */
 138 struct composite_context *resolve_name_all_send(struct resolve_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 139                                                 uint32_t flags,
 140                                                 uint16_t port,
 141                                                 struct nbt_name *name,
 142                                                 struct tevent_context *event_ctx)
 143 {
 144         struct composite_context *c;
 145         struct resolve_state *state;
 146 
 147         if (ctx == NULL || event_ctx == NULL) {
 148                 return NULL;
 149         }
 150 
 151         c = composite_create(ctx, event_ctx);
 152         if (c == NULL) return NULL;
 153 
 154         if (composite_nomem(c->event_ctx, c)) return c;
 155 
 156         state = talloc(c, struct resolve_state);
 157         if (composite_nomem(state, c)) return c;
 158         c->private_data = state;
 159 
 160         state->flags = flags;
 161         state->port = port;
 162 
 163         c->status = nbt_name_dup(state, name, &state->name);
 164         if (!composite_is_ok(c)) return c;
 165         
 166         state->ctx = talloc_reference(state, ctx);
 167         if (composite_nomem(state->ctx, c)) return c;
 168 
 169         if (is_ipaddress(state->name.name) || 
 170             strcasecmp(state->name.name, "localhost") == 0) {
 171                 struct in_addr ip = interpret_addr2(state->name.name);
 172 
 173                 state->addrs = talloc_array(state, struct socket_address *, 2);
 174                 if (composite_nomem(state->addrs, c)) return c;
 175                 state->addrs[0] = socket_address_from_strings(state->addrs, "ipv4",
 176                                                               inet_ntoa(ip), 0);
 177                 if (composite_nomem(state->addrs[0], c)) return c;
 178                 state->addrs[1] = NULL;
 179                 state->names = talloc_array(state, char *, 2);
 180                 if (composite_nomem(state->names, c)) return c;
 181                 state->names[0] = talloc_strdup(state->names, state->name.name);
 182                 if (composite_nomem(state->names[0], c)) return c;
 183                 state->names[1] = NULL;
 184                 composite_done(c);
 185                 return c;
 186         }
 187 
 188         state->method = ctx->methods;
 189         if (state->method == NULL) {
 190                 composite_error(c, NT_STATUS_BAD_NETWORK_NAME);
 191                 return c;
 192         }
 193         state->creq = setup_next_method(c);
 194         if (composite_nomem(state->creq, c)) return c;
 195         
 196         return c;
 197 }
 198 
 199 /*
 200   general name resolution method - recv side
 201  */
 202 NTSTATUS resolve_name_all_recv(struct composite_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 203                                TALLOC_CTX *mem_ctx,
 204                                struct socket_address ***addrs,
 205                                char ***names)
 206 {
 207         NTSTATUS status;
 208 
 209         status = composite_wait(c);
 210 
 211         if (NT_STATUS_IS_OK(status)) {
 212                 struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
 213                 *addrs = talloc_steal(mem_ctx, state->addrs);
 214                 if (names) {
 215                         *names = talloc_steal(mem_ctx, state->names);
 216                 }
 217         }
 218 
 219         talloc_free(c);
 220         return status;
 221 }
 222 
 223 struct composite_context *resolve_name_send(struct resolve_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 224                                             struct nbt_name *name,
 225                                             struct tevent_context *event_ctx)
 226 {
 227         return resolve_name_all_send(ctx, 0, 0, name, event_ctx);
 228 }
 229 
 230 NTSTATUS resolve_name_recv(struct composite_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 231                            TALLOC_CTX *mem_ctx,
 232                            const char **reply_addr)
 233 {
 234         NTSTATUS status;
 235         struct socket_address **addrs = NULL;
 236 
 237         status = resolve_name_all_recv(c, mem_ctx, &addrs, NULL);
 238 
 239         if (NT_STATUS_IS_OK(status)) {
 240                 *reply_addr = talloc_steal(mem_ctx, addrs[0]->addr);
 241                 talloc_free(addrs);
 242         }
 243 
 244         return status;
 245 }
 246 
 247 /*
 248   general name resolution - sync call
 249  */
 250 NTSTATUS resolve_name(struct resolve_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 251                           struct nbt_name *name,
 252                           TALLOC_CTX *mem_ctx,
 253                           const char **reply_addr,
 254                           struct tevent_context *ev)
 255 {
 256         struct composite_context *c = resolve_name_send(ctx, name, ev);
 257         return resolve_name_recv(c, mem_ctx, reply_addr);
 258 }
 259 
 260 /* Initialise a struct nbt_name with a NULL scope */
 261 
 262 void make_nbt_name(struct nbt_name *nbt, const char *name, int type)
     /* [<][>][^][v][top][bottom][index][help] */
 263 {
 264         nbt->name = name;
 265         nbt->scope = NULL;
 266         nbt->type = type;
 267 }
 268 
 269 /* Initialise a struct nbt_name with a NBT_NAME_CLIENT (0x00) name */
 270 
 271 void make_nbt_name_client(struct nbt_name *nbt, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 272 {
 273         make_nbt_name(nbt, name, NBT_NAME_CLIENT);
 274 }
 275 
 276 /* Initialise a struct nbt_name with a NBT_NAME_SERVER (0x20) name */
 277 
 278 void make_nbt_name_server(struct nbt_name *nbt, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 279 {
 280         make_nbt_name(nbt, name, NBT_NAME_SERVER);
 281 }
 282 
 283 

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