LCOV - code coverage report
Current view: top level - source4/libcli/resolve - resolve.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 129 136 94.9 %
Date: 2024-02-28 12:06:22 Functions: 14 14 100.0 %

          Line data    Source code
       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             : #include "lib/tsocket/tsocket.h"
      31             : #include "lib/util/util_net.h"
      32             : 
      33             : #undef strcasecmp
      34             : 
      35             : struct resolve_state {
      36             :         struct resolve_context *ctx;
      37             :         struct resolve_method *method;
      38             :         uint32_t flags;
      39             :         uint16_t port;
      40             :         struct nbt_name name;
      41             :         struct composite_context *creq;
      42             :         struct socket_address **addrs;
      43             :         char **names;
      44             : };
      45             : 
      46             : static struct composite_context *setup_next_method(struct composite_context *c);
      47             : 
      48             : 
      49             : struct resolve_context {
      50             :         struct resolve_method {
      51             :                 resolve_name_send_fn send_fn;
      52             :                 resolve_name_recv_fn recv_fn;
      53             :                 void *privdata;
      54             :                 struct resolve_method *prev, *next;
      55             :         } *methods;
      56             : };
      57             : 
      58             : /**
      59             :  * Initialize a resolve context
      60             :  */
      61       67715 : struct resolve_context *resolve_context_init(TALLOC_CTX *mem_ctx)
      62             : {
      63       67715 :         return talloc_zero(mem_ctx, struct resolve_context);
      64             : }
      65             : 
      66             : /**
      67             :  * Add a resolve method
      68             :  */
      69      269848 : bool resolve_context_add_method(struct resolve_context *ctx, resolve_name_send_fn send_fn, 
      70             :                                 resolve_name_recv_fn recv_fn, void *userdata)
      71             : {
      72      269848 :         struct resolve_method *method = talloc_zero(ctx, struct resolve_method);
      73             : 
      74      269848 :         if (method == NULL)
      75           0 :                 return false;
      76             : 
      77      269848 :         method->send_fn = send_fn;
      78      269848 :         method->recv_fn = recv_fn;
      79      269848 :         method->privdata = userdata;
      80      269848 :         DLIST_ADD_END(ctx->methods, method);
      81      264560 :         return true;
      82             : }
      83             : 
      84             : /**
      85             :   handle completion of one name resolve method
      86             : */
      87      132050 : static void resolve_handler(struct composite_context *creq)
      88             : {
      89      132050 :         struct composite_context *c = (struct composite_context *)creq->async.private_data;
      90      132050 :         struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
      91      132050 :         const struct resolve_method *method = state->method;
      92             : 
      93      132050 :         c->status = method->recv_fn(creq, state, &state->addrs, &state->names);
      94             :         
      95      132050 :         if (!NT_STATUS_IS_OK(c->status)) {
      96       83267 :                 state->method = state->method->next;
      97       83267 :                 state->creq = setup_next_method(c);
      98       83267 :                 if (state->creq != NULL) {
      99       76514 :                         return;
     100             :                 }
     101             :         }
     102             : 
     103       54292 :         if (!NT_STATUS_IS_OK(c->status)) {
     104        5509 :                 c->state = COMPOSITE_STATE_ERROR;
     105             :         } else {
     106       48783 :                 c->state = COMPOSITE_STATE_DONE;
     107             :         }
     108       54292 :         if (c->async.fn) {
     109       53947 :                 c->async.fn(c);
     110             :         }
     111             : }
     112             : 
     113             : 
     114      137559 : static struct composite_context *setup_next_method(struct composite_context *c)
     115             : {
     116      137559 :         struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
     117      137559 :         struct composite_context *creq = NULL;
     118             : 
     119        3726 :         do {
     120      173875 :                 if (state->method) {
     121      168366 :                         creq = state->method->send_fn(c, c->event_ctx,
     122      164640 :                                                       state->method->privdata,
     123             :                                                       state->flags,
     124      168366 :                                                       state->port,
     125             :                                                       &state->name);
     126             :                 }
     127      173875 :                 if (creq == NULL && state->method) state->method = state->method->next;
     128             : 
     129      173875 :         } while (!creq && state->method);
     130             : 
     131      137559 :         if (creq) {
     132      132050 :                 creq->async.fn = resolve_handler;
     133      132050 :                 creq->async.private_data = c;
     134             :         }
     135             : 
     136      137559 :         return creq;
     137             : }
     138             : 
     139             : /*
     140             :   general name resolution - async send
     141             :  */
     142       62414 : struct composite_context *resolve_name_all_send(struct resolve_context *ctx,
     143             :                                                 TALLOC_CTX *mem_ctx,
     144             :                                                 uint32_t flags, /* RESOLVE_NAME_FLAG_* */
     145             :                                                 uint16_t port,
     146             :                                                 struct nbt_name *name,
     147             :                                                 struct tevent_context *event_ctx)
     148             : {
     149        1242 :         struct composite_context *c;
     150        1242 :         struct resolve_state *state;
     151             : 
     152       62414 :         if (event_ctx == NULL) {
     153           0 :                 return NULL;
     154             :         }
     155             : 
     156       62414 :         c = composite_create(mem_ctx, event_ctx);
     157       62414 :         if (c == NULL) return NULL;
     158             : 
     159       62414 :         if (composite_nomem(c->event_ctx, c)) return c;
     160             : 
     161       62414 :         state = talloc(c, struct resolve_state);
     162       62414 :         if (composite_nomem(state, c)) return c;
     163       62414 :         c->private_data = state;
     164             : 
     165       62414 :         state->flags = flags;
     166       62414 :         state->port = port;
     167             : 
     168       62414 :         c->status = nbt_name_dup(state, name, &state->name);
     169       62414 :         if (!composite_is_ok(c)) return c;
     170             :         
     171       62414 :         state->ctx = talloc_reference(state, ctx);
     172       62414 :         if (composite_nomem(state->ctx, c)) return c;
     173             : 
     174       62414 :         if (is_ipaddress(state->name.name) || 
     175       54292 :             strcasecmp(state->name.name, "localhost") == 0) {
     176        8122 :                 state->addrs = talloc_array(state, struct socket_address *, 2);
     177        8122 :                 if (composite_nomem(state->addrs, c)) return c;
     178        8122 :                 state->addrs[0] = socket_address_from_strings(state->addrs, "ip",
     179             :                                                               state->name.name, 0);
     180        8122 :                 if (composite_nomem(state->addrs[0], c)) return c;
     181        8122 :                 state->addrs[1] = NULL;
     182        8122 :                 state->names = talloc_array(state, char *, 2);
     183        8122 :                 if (composite_nomem(state->names, c)) return c;
     184        8122 :                 state->names[0] = talloc_strdup(state->names, state->name.name);
     185        8122 :                 if (composite_nomem(state->names[0], c)) return c;
     186        8122 :                 state->names[1] = NULL;
     187        8122 :                 composite_done(c);
     188        8122 :                 return c;
     189             :         }
     190             : 
     191       54292 :         state->method = ctx->methods;
     192       54292 :         if (state->method == NULL) {
     193           0 :                 composite_error(c, NT_STATUS_BAD_NETWORK_NAME);
     194           0 :                 return c;
     195             :         }
     196       54292 :         state->creq = setup_next_method(c);
     197       54292 :         if (composite_nomem(state->creq, c)) return c;
     198             :         
     199       53050 :         return c;
     200             : }
     201             : 
     202             : /*
     203             :   general name resolution method - recv side
     204             :  */
     205       62414 : NTSTATUS resolve_name_all_recv(struct composite_context *c,
     206             :                                TALLOC_CTX *mem_ctx,
     207             :                                struct socket_address ***addrs,
     208             :                                char ***names)
     209             : {
     210        1242 :         NTSTATUS status;
     211             : 
     212       62414 :         status = composite_wait(c);
     213             : 
     214       62414 :         if (NT_STATUS_IS_OK(status)) {
     215       56905 :                 struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
     216       56905 :                 *addrs = talloc_steal(mem_ctx, state->addrs);
     217       56905 :                 if (names) {
     218           0 :                         *names = talloc_steal(mem_ctx, state->names);
     219             :                 }
     220             :         }
     221             : 
     222       62414 :         talloc_free(c);
     223       62414 :         return status;
     224             : }
     225             : 
     226       20401 : struct composite_context *resolve_name_ex_send(struct resolve_context *ctx,
     227             :                                                TALLOC_CTX *mem_ctx,
     228             :                                                uint32_t flags, /* RESOLVE_NAME_FLAG_* */
     229             :                                                uint16_t port,
     230             :                                                struct nbt_name *name,
     231             :                                                struct tevent_context *event_ctx)
     232             : {
     233       20401 :         return resolve_name_all_send(ctx, mem_ctx, flags, port, name, event_ctx);
     234             : }
     235             : 
     236       16785 : struct composite_context *resolve_name_send(struct resolve_context *ctx,
     237             :                                             TALLOC_CTX *mem_ctx,
     238             :                                             struct nbt_name *name,
     239             :                                             struct tevent_context *event_ctx)
     240             : {
     241       16785 :         return resolve_name_ex_send(ctx, mem_ctx, 0, 0, name, event_ctx);
     242             : }
     243             : 
     244        3401 : NTSTATUS resolve_name_recv(struct composite_context *c,
     245             :                            TALLOC_CTX *mem_ctx,
     246             :                            const char **reply_addr)
     247             : {
     248          36 :         NTSTATUS status;
     249        3401 :         struct socket_address **addrs = NULL;
     250             : 
     251        3401 :         status = resolve_name_all_recv(c, mem_ctx, &addrs, NULL);
     252             : 
     253        3401 :         if (NT_STATUS_IS_OK(status)) {
     254        3389 :                 struct tsocket_address *t_addr = socket_address_to_tsocket_address(addrs, addrs[0]);
     255        3389 :                 if (!t_addr) {
     256           0 :                         return NT_STATUS_NO_MEMORY;
     257             :                 }
     258             : 
     259        3389 :                 *reply_addr = tsocket_address_inet_addr_string(t_addr, mem_ctx);
     260        3389 :                 talloc_free(addrs);
     261        3389 :                 if (!*reply_addr) {
     262           0 :                         return NT_STATUS_NO_MEMORY;
     263             :                 }
     264             :         }
     265             : 
     266        3401 :         return status;
     267             : }
     268             : 
     269             : /*
     270             :   receive multiple responses from resolve_name_send()
     271             :  */
     272       17000 : NTSTATUS resolve_name_multiple_recv(struct composite_context *c,
     273             :                                     TALLOC_CTX *mem_ctx,
     274             :                                     const char ***reply_addrs)
     275             : {
     276         242 :         NTSTATUS status;
     277       17000 :         struct socket_address **addrs = NULL;
     278         242 :         int i;
     279             : 
     280       17000 :         status = resolve_name_all_recv(c, mem_ctx, &addrs, NULL);
     281       17000 :         NT_STATUS_NOT_OK_RETURN(status);
     282             : 
     283             :         /* count the addresses */
     284       32598 :         for (i=0; addrs[i]; i++) ;
     285             : 
     286       11504 :         *reply_addrs = talloc_array(mem_ctx, const char *, i+1);
     287       11504 :         NT_STATUS_HAVE_NO_MEMORY(*reply_addrs);
     288             : 
     289       32598 :         for (i=0; addrs[i]; i++) {
     290       21094 :                 struct tsocket_address *t_addr = socket_address_to_tsocket_address(addrs, addrs[i]);
     291       21094 :                 NT_STATUS_HAVE_NO_MEMORY(t_addr);
     292             : 
     293       21094 :                 (*reply_addrs)[i] = tsocket_address_inet_addr_string(t_addr, *reply_addrs);
     294       21094 :                 NT_STATUS_HAVE_NO_MEMORY((*reply_addrs)[i]);
     295             :         }
     296       11504 :         (*reply_addrs)[i] = NULL;
     297             : 
     298       11504 :         talloc_free(addrs);
     299             : 
     300       11504 :         return status;
     301             : }
     302             : 
     303             : /*
     304             :   general name resolution - sync call
     305             :  */
     306         347 : NTSTATUS resolve_name_ex(struct resolve_context *ctx,
     307             :                          uint32_t flags, /* RESOLVE_NAME_FLAG_* */
     308             :                          uint16_t port,
     309             :                          struct nbt_name *name,
     310             :                          TALLOC_CTX *mem_ctx,
     311             :                          const char **reply_addr,
     312             :                          struct tevent_context *ev)
     313             : {
     314         347 :         struct composite_context *c = resolve_name_ex_send(ctx, mem_ctx, flags, port, name, ev);
     315         347 :         return resolve_name_recv(c, mem_ctx, reply_addr);
     316             : }
     317             : 
     318             : 
     319             : /* Initialise a struct nbt_name with a NULL scope */
     320             : 
     321       84619 : void make_nbt_name(struct nbt_name *nbt, const char *name, int type)
     322             : {
     323       84619 :         nbt->name = name;
     324       84619 :         nbt->scope = NULL;
     325       84619 :         nbt->type = type;
     326       84619 : }
     327             : 
     328             : /* Initialise a struct nbt_name with a NBT_NAME_CLIENT (0x00) name */
     329             : 
     330       22473 : void make_nbt_name_client(struct nbt_name *nbt, const char *name)
     331             : {
     332       22473 :         make_nbt_name(nbt, name, NBT_NAME_CLIENT);
     333       22473 : }
     334             : 
     335             : /* Initialise a struct nbt_name with a NBT_NAME_SERVER (0x20) name */
     336             : 
     337       58429 : void make_nbt_name_server(struct nbt_name *nbt, const char *name)
     338             : {
     339       58429 :         make_nbt_name(nbt, name, NBT_NAME_SERVER);
     340       58429 : }
     341             : 
     342             : 

Generated by: LCOV version 1.14