LCOV - code coverage report
Current view: top level - source4/libcli/resolve - nbtlist.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 83 91 91.2 %
Date: 2024-04-21 15:09:00 Functions: 3 3 100.0 %

          Line data    Source code
       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        8677 : static void nbtlist_handler(struct nbt_name_request *req)
      53             : {
      54        8677 :         struct composite_context *c = talloc_get_type(req->async.private_data,
      55             :                                                       struct composite_context);
      56        8677 :         struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
      57           2 :         struct nbt_name_query *q;
      58           2 :         int i;
      59             : 
      60        8679 :         for (i=0;i<state->num_queries;i++) {
      61        8677 :                 if (req == state->queries[i]) break;
      62             :         }
      63             : 
      64        8677 :         if (i == state->num_queries) {
      65             :                 /* not for us?! */
      66           0 :                 composite_error(c, NT_STATUS_INTERNAL_ERROR);
      67           0 :                 return;
      68             :         }
      69             : 
      70        8677 :         q = &state->io_queries[i];
      71             : 
      72        8677 :         c->status = nbt_name_query_recv(req, state, q);
      73             : 
      74             :         /* free the network resource directly */
      75        8677 :         talloc_free(state->nbtsock);
      76        8677 :         if (!composite_is_ok(c)) return;
      77             : 
      78          17 :         if (q->out.num_addrs < 1) {
      79           0 :                 composite_error(c, NT_STATUS_UNEXPECTED_NETWORK_ERROR);
      80           0 :                 return;
      81             :         }
      82             : 
      83          17 :         state->addrs = talloc_array(state, struct socket_address *,
      84             :                                     q->out.num_addrs + 1);
      85          17 :         if (composite_nomem(state->addrs, c)) return;
      86             : 
      87          17 :         state->names = talloc_array(state, char *, q->out.num_addrs + 1);
      88          17 :         if (composite_nomem(state->names, c)) return;
      89             : 
      90          34 :         for (i=0;i<q->out.num_addrs;i++) {
      91          34 :                 state->addrs[i] = socket_address_from_strings(state->addrs,
      92             :                                                               "ipv4",
      93          17 :                                                               q->out.reply_addrs[i],
      94          17 :                                                               state->port);
      95          17 :                 if (composite_nomem(state->addrs[i], c)) return;
      96             : 
      97          17 :                 state->names[i] = talloc_strdup(state->names, state->name.name);
      98          17 :                 if (composite_nomem(state->names[i], c)) return;
      99             :         }
     100          17 :         state->addrs[i] = NULL;
     101          17 :         state->names[i] = NULL;
     102             : 
     103          17 :         composite_done(c);
     104             : }
     105             : 
     106             : /*
     107             :   nbtlist name resolution method - async send
     108             :  */
     109       21605 : struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx,
     110             :                                                     struct tevent_context *event_ctx,
     111             :                                                     uint32_t flags,
     112             :                                                     uint16_t port,
     113             :                                                     struct nbt_name *name, 
     114             :                                                     const char * const *address_list,
     115             :                                                     struct interface *ifaces,
     116             :                                                     uint16_t nbt_port,
     117             :                                                     int nbt_timeout,
     118             :                                                     bool broadcast,
     119             :                                                     bool wins_lookup)
     120             : {
     121           2 :         struct composite_context *c;
     122           2 :         struct nbtlist_state *state;
     123           2 :         int i;
     124             : 
     125       21605 :         c = composite_create(mem_ctx, event_ctx);
     126       21605 :         if (c == NULL) return NULL;
     127             : 
     128       21605 :         if (flags & RESOLVE_NAME_FLAG_FORCE_DNS) {
     129        3102 :                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     130        3102 :                 return c;
     131             :         }
     132             : 
     133       18503 :         if (strlen(name->name) > 15) {
     134        9826 :                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     135        9826 :                 return c;
     136             :         }
     137             : 
     138        8677 :         state = talloc(c, struct nbtlist_state);
     139        8677 :         if (composite_nomem(state, c)) return c;
     140        8677 :         c->private_data = state;
     141             : 
     142        8677 :         state->flags = flags;
     143        8677 :         state->port = port;
     144             : 
     145        8677 :         c->status = nbt_name_dup(state, name, &state->name);
     146        8677 :         if (!composite_is_ok(c)) return c;
     147             : 
     148        8677 :         state->name.name = strupper_talloc(state, state->name.name);
     149        8677 :         if (composite_nomem(state->name.name, c)) return c;
     150        8677 :         if (state->name.scope) {
     151           0 :                 state->name.scope = strupper_talloc(state, state->name.scope);
     152           0 :                 if (composite_nomem(state->name.scope, c)) return c;
     153             :         }
     154             : 
     155        8677 :         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        8677 :         if (strlen(state->name.name) > 15) {
     162           0 :                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     163           0 :                 return c;
     164             :         }
     165             : 
     166        8677 :         state->nbtsock = nbt_name_socket_init(state, event_ctx);
     167        8677 :         if (composite_nomem(state->nbtsock, c)) return c;
     168             : 
     169             :         /* count the address_list size */
     170       17439 :         for (i=0;address_list[i];i++) /* noop */ ;
     171             : 
     172        8677 :         state->num_queries = i;
     173        8677 :         state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
     174        8677 :         if (composite_nomem(state->io_queries, c)) return c;
     175             : 
     176        8677 :         state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
     177        8677 :         if (composite_nomem(state->queries, c)) return c;
     178             : 
     179       17439 :         for (i=0;i<state->num_queries;i++) {
     180        8762 :                 state->io_queries[i].in.name        = state->name;
     181        8762 :                 state->io_queries[i].in.dest_addr   = talloc_strdup(state->io_queries, address_list[i]);
     182        8762 :                 state->io_queries[i].in.dest_port   = nbt_port;
     183        8762 :                 if (composite_nomem(state->io_queries[i].in.dest_addr, c)) return c;
     184             : 
     185        8762 :                 state->io_queries[i].in.broadcast   = broadcast;
     186        8762 :                 state->io_queries[i].in.wins_lookup = wins_lookup;
     187        8762 :                 state->io_queries[i].in.timeout     = nbt_timeout;
     188        8762 :                 state->io_queries[i].in.retries     = 2;
     189             : 
     190        8762 :                 state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
     191        8762 :                 if (composite_nomem(state->queries[i], c)) return c;
     192             : 
     193        8762 :                 state->queries[i]->async.fn      = nbtlist_handler;
     194        8762 :                 state->queries[i]->async.private_data = c;
     195             :         }
     196             : 
     197        8675 :         return c;
     198             : }
     199             : 
     200             : /*
     201             :   nbt list of addresses name resolution method - recv side
     202             :  */
     203       21605 : NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c, 
     204             :                                    TALLOC_CTX *mem_ctx,
     205             :                                    struct socket_address ***addrs,
     206             :                                    char ***names)
     207             : {
     208           2 :         NTSTATUS status;
     209             : 
     210       21605 :         status = composite_wait(c);
     211             : 
     212       21605 :         if (NT_STATUS_IS_OK(status)) {
     213          17 :                 struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
     214          17 :                 *addrs = talloc_steal(mem_ctx, state->addrs);
     215          17 :                 if (names) {
     216          17 :                         *names = talloc_steal(mem_ctx, state->names);
     217             :                 }
     218             :         }
     219             : 
     220       21605 :         talloc_free(c);
     221       21605 :         return status;
     222             : }
     223             : 

Generated by: LCOV version 1.14