LCOV - code coverage report
Current view: top level - libcli/nbt - namequery.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 95 118 80.5 %
Date: 2024-02-28 12:06:22 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    make nbt name query requests
       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             : #include "includes.h"
      23             : #include "../libcli/nbt/libnbt.h"
      24             : #include "../libcli/nbt/nbt_proto.h"
      25             : #include "lib/socket/socket.h"
      26             : 
      27             : /**
      28             :   send a nbt name query
      29             : */
      30        9635 : _PUBLIC_ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock,
      31             :                                              struct nbt_name_query *io)
      32             : {
      33          30 :         struct nbt_name_request *req;
      34          30 :         struct nbt_name_packet *packet;
      35          30 :         struct socket_address *dest;
      36             : 
      37        9635 :         packet = talloc_zero(nbtsock, struct nbt_name_packet);
      38        9635 :         if (packet == NULL) return NULL;
      39             : 
      40        9635 :         packet->qdcount = 1;
      41        9635 :         packet->operation = NBT_OPCODE_QUERY;
      42        9635 :         if (io->in.broadcast) {
      43         628 :                 packet->operation |= NBT_FLAG_BROADCAST;
      44             :         }
      45        9635 :         if (io->in.wins_lookup) {
      46        8612 :                 packet->operation |= NBT_FLAG_RECURSION_DESIRED;
      47             :         }
      48             : 
      49        9635 :         packet->questions = talloc_array(packet, struct nbt_name_question, 1);
      50        9635 :         if (packet->questions == NULL) goto failed;
      51             : 
      52        9635 :         packet->questions[0].name = io->in.name;
      53        9635 :         packet->questions[0].question_type = NBT_QTYPE_NETBIOS;
      54        9635 :         packet->questions[0].question_class = NBT_QCLASS_IP;
      55             : 
      56        9665 :         dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
      57        9635 :                                            io->in.dest_addr, io->in.dest_port);
      58        9635 :         if (dest == NULL) goto failed;
      59        9635 :         req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
      60             :                                     io->in.timeout, io->in.retries, false);
      61        9635 :         if (req == NULL) goto failed;
      62             : 
      63        9635 :         talloc_free(packet);
      64        9635 :         return req;
      65             : 
      66           0 : failed:
      67           0 :         talloc_free(packet);
      68           0 :         return NULL;
      69             : }
      70             : 
      71             : /**
      72             :   wait for a name query reply
      73             : */
      74        9550 : _PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
      75             :                              TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
      76             : {
      77          30 :         NTSTATUS status;
      78          30 :         struct nbt_name_packet *packet;
      79          30 :         int i;
      80             : 
      81        9550 :         status = nbt_name_request_recv(req);
      82        9550 :         if (!NT_STATUS_IS_OK(status) ||
      83         876 :             req->num_replies == 0) {
      84        8674 :                 talloc_free(req);
      85        8674 :                 return status;
      86             :         }
      87             : 
      88         876 :         packet = req->replies[0].packet;
      89         876 :         io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
      90             : 
      91         876 :         if ((packet->operation & NBT_RCODE) != 0) {
      92          30 :                 status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE);
      93          30 :                 talloc_free(req);
      94          30 :                 return status;
      95             :         }
      96             : 
      97         846 :         if (packet->ancount != 1 ||
      98         846 :             packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
      99         822 :             packet->answers[0].rr_class != NBT_QCLASS_IP) {
     100           0 :                 talloc_free(req);
     101           0 :                 return status;
     102             :         }
     103             : 
     104         846 :         io->out.name = packet->answers[0].name;
     105         846 :         io->out.num_addrs = packet->answers[0].rdata.netbios.length / 6;
     106         846 :         io->out.reply_addrs = talloc_array(mem_ctx, const char *, io->out.num_addrs+1);
     107         846 :         if (io->out.reply_addrs == NULL) {
     108           0 :                 talloc_free(req);
     109           0 :                 return NT_STATUS_NO_MEMORY;
     110             :         }
     111             : 
     112        1722 :         for (i=0;i<io->out.num_addrs;i++) {
     113         876 :                 io->out.reply_addrs[i] = talloc_steal(io->out.reply_addrs,
     114             :                                                       packet->answers[0].rdata.netbios.addresses[i].ipaddr);
     115             :         }
     116         846 :         io->out.reply_addrs[i] = NULL;
     117             : 
     118         846 :         talloc_steal(mem_ctx, io->out.name.name);
     119         846 :         talloc_steal(mem_ctx, io->out.name.scope);
     120             : 
     121         846 :         talloc_free(req);
     122             : 
     123         846 :         return NT_STATUS_OK;
     124             : }
     125             : 
     126             : /**
     127             :   wait for a name query reply
     128             : */
     129         960 : _PUBLIC_ NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock,
     130             :                         TALLOC_CTX *mem_ctx, struct nbt_name_query *io)
     131             : {
     132         960 :         struct nbt_name_request *req = nbt_name_query_send(nbtsock, io);
     133         960 :         return nbt_name_query_recv(req, mem_ctx, io);
     134             : }
     135             : 
     136             : 
     137             : /**
     138             :   send a nbt name status
     139             : */
     140           2 : _PUBLIC_ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock,
     141             :                                               struct nbt_name_status *io)
     142             : {
     143           0 :         struct nbt_name_request *req;
     144           0 :         struct nbt_name_packet *packet;
     145           0 :         struct socket_address *dest;
     146             : 
     147           2 :         packet = talloc_zero(nbtsock, struct nbt_name_packet);
     148           2 :         if (packet == NULL) return NULL;
     149             : 
     150           2 :         packet->qdcount = 1;
     151           2 :         packet->operation = NBT_OPCODE_QUERY;
     152             : 
     153           2 :         packet->questions = talloc_array(packet, struct nbt_name_question, 1);
     154           2 :         if (packet->questions == NULL) goto failed;
     155             : 
     156           2 :         packet->questions[0].name = io->in.name;
     157           2 :         packet->questions[0].question_type = NBT_QTYPE_STATUS;
     158           2 :         packet->questions[0].question_class = NBT_QCLASS_IP;
     159             : 
     160           2 :         dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
     161           2 :                                            io->in.dest_addr, io->in.dest_port);
     162           2 :         if (dest == NULL) goto failed;
     163           2 :         req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
     164             :                                     io->in.timeout, io->in.retries, false);
     165           2 :         if (req == NULL) goto failed;
     166             : 
     167           2 :         talloc_free(packet);
     168           2 :         return req;
     169             : 
     170           0 : failed:
     171           0 :         talloc_free(packet);
     172           0 :         return NULL;
     173             : }
     174             : 
     175             : /**
     176             :   wait for a name status reply
     177             : */
     178           2 : _PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
     179             :                              TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
     180             : {
     181           0 :         NTSTATUS status;
     182           0 :         struct nbt_name_packet *packet;
     183           0 :         int i;
     184             : 
     185           2 :         status = nbt_name_request_recv(req);
     186           2 :         if (!NT_STATUS_IS_OK(status) ||
     187           2 :             req->num_replies == 0) {
     188           0 :                 talloc_free(req);
     189           0 :                 return status;
     190             :         }
     191             : 
     192           2 :         packet = req->replies[0].packet;
     193           2 :         io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
     194             : 
     195           2 :         if ((packet->operation & NBT_RCODE) != 0) {
     196           0 :                 status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE);
     197           0 :                 talloc_free(req);
     198           0 :                 return status;
     199             :         }
     200             : 
     201           2 :         if (packet->ancount != 1 ||
     202           2 :             packet->answers[0].rr_type != NBT_QTYPE_STATUS ||
     203           2 :             packet->answers[0].rr_class != NBT_QCLASS_IP) {
     204           0 :                 talloc_free(req);
     205           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     206             :         }
     207             : 
     208           2 :         io->out.name = packet->answers[0].name;
     209           2 :         talloc_steal(mem_ctx, io->out.name.name);
     210           2 :         talloc_steal(mem_ctx, io->out.name.scope);
     211             : 
     212           2 :         io->out.status = packet->answers[0].rdata.status;
     213           2 :         talloc_steal(mem_ctx, io->out.status.names);
     214          20 :         for (i=0;i<io->out.status.num_names;i++) {
     215          18 :                 talloc_steal(io->out.status.names, io->out.status.names[i].name);
     216             :         }
     217             : 
     218             : 
     219           2 :         talloc_free(req);
     220             : 
     221           2 :         return NT_STATUS_OK;
     222             : }
     223             : 
     224             : /**
     225             :   wait for a name status reply
     226             : */
     227           2 : _PUBLIC_ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock,
     228             :                         TALLOC_CTX *mem_ctx, struct nbt_name_status *io)
     229             : {
     230           2 :         struct nbt_name_request *req = nbt_name_status_send(nbtsock, io);
     231           2 :         return nbt_name_status_recv(req, mem_ctx, io);
     232             : }
     233             : 
     234             : 

Generated by: LCOV version 1.14