LCOV - code coverage report
Current view: top level - libcli/dns - dns.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 93 280 33.2 %
Date: 2024-04-21 15:09:00 Functions: 7 14 50.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Small async DNS library for Samba with socketwrapper support
       5             : 
       6             :    Copyright (C) 2010 Kai Blin  <kai@samba.org>
       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 "replace.h"
      23             : #include "system/network.h"
      24             : #include <tevent.h>
      25             : #include "lib/tsocket/tsocket.h"
      26             : #include "libcli/dns/libdns.h"
      27             : #include "lib/util/tevent_unix.h"
      28             : #include "lib/util/samba_util.h"
      29             : #include "lib/util/debug.h"
      30             : #include "libcli/util/error.h"
      31             : #include "librpc/ndr/libndr.h"
      32             : #include "librpc/gen_ndr/ndr_dns.h"
      33             : 
      34             : struct dns_udp_request_state {
      35             :         struct tevent_context *ev;
      36             :         struct tdgram_context *dgram;
      37             :         size_t query_len;
      38             :         uint8_t *reply;
      39             :         size_t reply_len;
      40             : };
      41             : 
      42             : #define DNS_REQUEST_TIMEOUT 10
      43             : 
      44             : /* Declare callback functions used below. */
      45             : static void dns_udp_request_get_reply(struct tevent_req *subreq);
      46             : static void dns_udp_request_done(struct tevent_req *subreq);
      47             : 
      48        1449 : static struct tevent_req *dns_udp_request_send(TALLOC_CTX *mem_ctx,
      49             :                                                struct tevent_context *ev,
      50             :                                                const char *server_addr_string,
      51             :                                                const uint8_t *query,
      52             :                                                size_t query_len)
      53             : {
      54           0 :         struct tevent_req *req, *subreq;
      55           0 :         struct dns_udp_request_state *state;
      56           0 :         struct tsocket_address *local_addr, *server_addr;
      57           0 :         struct tdgram_context *dgram;
      58           0 :         int ret;
      59             : 
      60        1449 :         req = tevent_req_create(mem_ctx, &state, struct dns_udp_request_state);
      61        1449 :         if (req == NULL) {
      62           0 :                 return NULL;
      63             :         }
      64             : 
      65        1449 :         state->ev = ev;
      66             : 
      67             :         /* Use connected UDP sockets */
      68        1449 :         ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0,
      69             :                                                 &local_addr);
      70        1449 :         if (ret != 0) {
      71           0 :                 tevent_req_error(req, errno);
      72           0 :                 return tevent_req_post(req, ev);
      73             :         }
      74             : 
      75        1449 :         ret = tsocket_address_inet_from_hostport_strings(
      76             :             state, "ip", server_addr_string, DNS_SERVICE_PORT, &server_addr);
      77        1449 :         if (ret != 0) {
      78           0 :                 tevent_req_error(req, errno);
      79           0 :                 return tevent_req_post(req, ev);
      80             :         }
      81             : 
      82        1449 :         ret = tdgram_inet_udp_socket(local_addr, server_addr, state, &dgram);
      83        1449 :         if (ret != 0) {
      84           0 :                 tevent_req_error(req, errno);
      85           0 :                 return tevent_req_post(req, ev);
      86             :         }
      87             : 
      88        1449 :         state->dgram = dgram;
      89        1449 :         state->query_len = query_len;
      90             : 
      91        1449 :         dump_data(10, query, query_len);
      92             : 
      93        1449 :         subreq = tdgram_sendto_send(state, ev, dgram, query, query_len, NULL);
      94        1449 :         if (tevent_req_nomem(subreq, req)) {
      95           0 :                 return tevent_req_post(req, ev);
      96             :         }
      97             : 
      98        1449 :         if (!tevent_req_set_endtime(req, ev,
      99             :                                 timeval_current_ofs(DNS_REQUEST_TIMEOUT, 0))) {
     100           0 :                 return tevent_req_post(req, ev);
     101             :         }
     102             : 
     103        1449 :         tevent_req_set_callback(subreq, dns_udp_request_get_reply, req);
     104        1449 :         return req;
     105             : }
     106             : 
     107        1449 : static void dns_udp_request_get_reply(struct tevent_req *subreq)
     108             : {
     109        1449 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     110             :                                                 struct tevent_req);
     111        1449 :         struct dns_udp_request_state *state = tevent_req_data(req,
     112             :                                                 struct dns_udp_request_state);
     113           0 :         ssize_t len;
     114        1449 :         int err = 0;
     115             : 
     116        1449 :         len = tdgram_sendto_recv(subreq, &err);
     117        1449 :         TALLOC_FREE(subreq);
     118             : 
     119        1449 :         if (len == -1 && err != 0) {
     120          10 :                 tevent_req_error(req, err);
     121          10 :                 return;
     122             :         }
     123             : 
     124        1439 :         if (len != state->query_len) {
     125           0 :                 tevent_req_error(req, EIO);
     126           0 :                 return;
     127             :         }
     128             : 
     129        1439 :         subreq = tdgram_recvfrom_send(state, state->ev, state->dgram);
     130        1439 :         if (tevent_req_nomem(subreq, req)) {
     131           0 :                 return;
     132             :         }
     133             : 
     134        1439 :         tevent_req_set_callback(subreq, dns_udp_request_done, req);
     135             : }
     136             : 
     137        1429 : static void dns_udp_request_done(struct tevent_req *subreq)
     138             : {
     139        1429 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     140             :                                                 struct tevent_req);
     141        1429 :         struct dns_udp_request_state *state = tevent_req_data(req,
     142             :                                                 struct dns_udp_request_state);
     143             : 
     144           0 :         ssize_t len;
     145        1429 :         int err = 0;
     146             : 
     147        1429 :         len = tdgram_recvfrom_recv(subreq, &err, state, &state->reply, NULL);
     148        1429 :         TALLOC_FREE(subreq);
     149             : 
     150        1429 :         if (len == -1 && err != 0) {
     151           0 :                 tevent_req_error(req, err);
     152           0 :                 return;
     153             :         }
     154             : 
     155        1429 :         state->reply_len = len;
     156        1429 :         dump_data(10, state->reply, state->reply_len);
     157        1429 :         tevent_req_done(req);
     158             : }
     159             : 
     160        1449 : static int dns_udp_request_recv(struct tevent_req *req,
     161             :                                 TALLOC_CTX *mem_ctx,
     162             :                                 uint8_t **reply,
     163             :                                 size_t *reply_len)
     164             : {
     165        1449 :         struct dns_udp_request_state *state = tevent_req_data(req,
     166             :                         struct dns_udp_request_state);
     167           0 :         int err;
     168             : 
     169        1449 :         if (tevent_req_is_unix_error(req, &err)) {
     170          20 :                 tevent_req_received(req);
     171          20 :                 return err;
     172             :         }
     173             : 
     174        1429 :         *reply = talloc_move(mem_ctx, &state->reply);
     175        1429 :         *reply_len = state->reply_len;
     176        1429 :         tevent_req_received(req);
     177             : 
     178        1429 :         return 0;
     179             : }
     180             : 
     181             : struct dns_tcp_request_state {
     182             :         struct tevent_context *ev;
     183             :         struct tstream_context *stream;
     184             :         const uint8_t *query;
     185             :         size_t query_len;
     186             : 
     187             :         uint8_t dns_msglen_hdr[2];
     188             :         struct iovec iov[2];
     189             : 
     190             :         size_t nread;
     191             :         uint8_t *reply;
     192             : };
     193             : 
     194             : static void dns_tcp_request_connected(struct tevent_req *subreq);
     195             : static void dns_tcp_request_sent(struct tevent_req *subreq);
     196             : static int dns_tcp_request_next_vector(struct tstream_context *stream,
     197             :                                        void *private_data,
     198             :                                        TALLOC_CTX *mem_ctx,
     199             :                                        struct iovec **_vector,
     200             :                                        size_t *_count);
     201             : static void dns_tcp_request_received(struct tevent_req *subreq);
     202             : 
     203           0 : static struct tevent_req *dns_tcp_request_send(TALLOC_CTX *mem_ctx,
     204             :                                                struct tevent_context *ev,
     205             :                                                const char *server_addr_string,
     206             :                                                const uint8_t *query,
     207             :                                                size_t query_len)
     208             : {
     209           0 :         struct tevent_req *req, *subreq;
     210           0 :         struct dns_tcp_request_state *state;
     211           0 :         struct tsocket_address *local, *remote;
     212           0 :         int ret;
     213             : 
     214           0 :         req = tevent_req_create(mem_ctx, &state,
     215             :                                 struct dns_tcp_request_state);
     216           0 :         if (req == NULL) {
     217           0 :                 return NULL;
     218             :         }
     219           0 :         state->ev = ev;
     220           0 :         state->query = query;
     221           0 :         state->query_len = query_len;
     222             : 
     223           0 :         if (query_len > UINT16_MAX) {
     224           0 :                 tevent_req_error(req, EMSGSIZE);
     225           0 :                 return tevent_req_post(req, ev);
     226             :         }
     227             : 
     228           0 :         ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0, &local);
     229           0 :         if (ret != 0) {
     230           0 :                 tevent_req_error(req, errno);
     231           0 :                 return tevent_req_post(req, ev);
     232             :         }
     233             : 
     234           0 :         ret = tsocket_address_inet_from_hostport_strings(
     235             :             state, "ip", server_addr_string, DNS_SERVICE_PORT, &remote);
     236           0 :         if (ret != 0) {
     237           0 :                 tevent_req_error(req, errno);
     238           0 :                 return tevent_req_post(req, ev);
     239             :         }
     240             : 
     241           0 :         subreq = tstream_inet_tcp_connect_send(state, state->ev,
     242             :                                                local, remote);
     243           0 :         if (tevent_req_nomem(subreq, req)) {
     244           0 :                 return tevent_req_post(req, ev);
     245             :         }
     246           0 :         tevent_req_set_callback(subreq, dns_tcp_request_connected, req);
     247             : 
     248           0 :         return req;
     249             : }
     250             : 
     251           0 : static void dns_tcp_request_connected(struct tevent_req *subreq)
     252             : {
     253           0 :         struct tevent_req *req = tevent_req_callback_data(
     254             :                 subreq, struct tevent_req);
     255           0 :         struct dns_tcp_request_state *state = tevent_req_data(
     256             :                 req, struct dns_tcp_request_state);
     257           0 :         int ret, err;
     258             : 
     259           0 :         ret = tstream_inet_tcp_connect_recv(subreq, &err, state,
     260             :                                             &state->stream, NULL);
     261           0 :         TALLOC_FREE(subreq);
     262           0 :         if (ret == -1) {
     263           0 :                 tevent_req_error(req, err);
     264           0 :                 return;
     265             :         }
     266             : 
     267           0 :         RSSVAL(state->dns_msglen_hdr, 0, state->query_len);
     268           0 :         state->iov[0] = (struct iovec) {
     269           0 :                 .iov_base = state->dns_msglen_hdr,
     270             :                 .iov_len = sizeof(state->dns_msglen_hdr)
     271             :         };
     272           0 :         state->iov[1] = (struct iovec) {
     273           0 :                 .iov_base = discard_const_p(void, state->query),
     274           0 :                 .iov_len = state->query_len
     275             :         };
     276             : 
     277           0 :         subreq = tstream_writev_send(state, state->ev, state->stream,
     278           0 :                                      state->iov, ARRAY_SIZE(state->iov));
     279           0 :         if (tevent_req_nomem(subreq, req)) {
     280           0 :                 return;
     281             :         }
     282           0 :         tevent_req_set_callback(subreq, dns_tcp_request_sent, req);
     283             : }
     284             : 
     285           0 : static void dns_tcp_request_sent(struct tevent_req *subreq)
     286             : {
     287           0 :         struct tevent_req *req = tevent_req_callback_data(
     288             :                 subreq, struct tevent_req);
     289           0 :         struct dns_tcp_request_state *state = tevent_req_data(
     290             :                 req, struct dns_tcp_request_state);
     291           0 :         int ret, err;
     292             : 
     293           0 :         ret = tstream_writev_recv(subreq, &err);
     294           0 :         TALLOC_FREE(subreq);
     295           0 :         if (ret == -1) {
     296           0 :                 tevent_req_error(req, err);
     297           0 :                 return;
     298             :         }
     299             : 
     300           0 :         subreq = tstream_readv_pdu_send(state, state->ev, state->stream,
     301             :                                         dns_tcp_request_next_vector, state);
     302           0 :         if (tevent_req_nomem(subreq, req)) {
     303           0 :                 return;
     304             :         }
     305           0 :         tevent_req_set_callback(subreq, dns_tcp_request_received, req);
     306             : }
     307             : 
     308           0 : static int dns_tcp_request_next_vector(struct tstream_context *stream,
     309             :                                        void *private_data,
     310             :                                        TALLOC_CTX *mem_ctx,
     311             :                                        struct iovec **_vector,
     312             :                                        size_t *_count)
     313             : {
     314           0 :         struct dns_tcp_request_state *state = talloc_get_type_abort(
     315             :                 private_data, struct dns_tcp_request_state);
     316           0 :         struct iovec *vector;
     317           0 :         uint16_t msglen;
     318             : 
     319           0 :         if (state->nread == 0) {
     320           0 :                 vector = talloc_array(mem_ctx, struct iovec, 1);
     321           0 :                 if (vector == NULL) {
     322           0 :                         return -1;
     323             :                 }
     324           0 :                 vector[0] = (struct iovec) {
     325           0 :                         .iov_base = state->dns_msglen_hdr,
     326             :                         .iov_len = sizeof(state->dns_msglen_hdr)
     327             :                 };
     328           0 :                 state->nread = sizeof(state->dns_msglen_hdr);
     329             : 
     330           0 :                 *_vector = vector;
     331           0 :                 *_count = 1;
     332           0 :                 return 0;
     333             :         }
     334             : 
     335           0 :         if (state->nread == sizeof(state->dns_msglen_hdr)) {
     336           0 :                 msglen = RSVAL(state->dns_msglen_hdr, 0);
     337             : 
     338           0 :                 state->reply = talloc_array(state, uint8_t, msglen);
     339           0 :                 if (state->reply == NULL) {
     340           0 :                         return -1;
     341             :                 }
     342             : 
     343           0 :                 vector = talloc_array(mem_ctx, struct iovec, 1);
     344           0 :                 if (vector == NULL) {
     345           0 :                         return -1;
     346             :                 }
     347           0 :                 vector[0] = (struct iovec) {
     348           0 :                         .iov_base = state->reply,
     349             :                         .iov_len = msglen
     350             :                 };
     351           0 :                 state->nread += msglen;
     352             : 
     353           0 :                 *_vector = vector;
     354           0 :                 *_count = 1;
     355           0 :                 return 0;
     356             :         }
     357             : 
     358           0 :         *_vector = NULL;
     359           0 :         *_count = 0;
     360           0 :         return 0;
     361             : }
     362             : 
     363           0 : static void dns_tcp_request_received(struct tevent_req *subreq)
     364             : {
     365           0 :         struct tevent_req *req = tevent_req_callback_data(
     366             :                 subreq, struct tevent_req);
     367           0 :         int ret, err;
     368             : 
     369           0 :         ret = tstream_readv_pdu_recv(subreq, &err);
     370           0 :         TALLOC_FREE(subreq);
     371           0 :         if (ret == -1) {
     372           0 :                 tevent_req_error(req, err);
     373           0 :                 return;
     374             :         }
     375             : 
     376           0 :         tevent_req_done(req);
     377             : }
     378             : 
     379           0 : static int dns_tcp_request_recv(struct tevent_req *req,
     380             :                                 TALLOC_CTX *mem_ctx,
     381             :                                 uint8_t **reply,
     382             :                                 size_t *reply_len)
     383             : {
     384           0 :         struct dns_tcp_request_state *state = tevent_req_data(
     385             :                 req, struct dns_tcp_request_state);
     386           0 :         int err;
     387             : 
     388           0 :         if (tevent_req_is_unix_error(req, &err)) {
     389           0 :                 tevent_req_received(req);
     390           0 :                 return err;
     391             :         }
     392             : 
     393           0 :         *reply_len = talloc_array_length(state->reply);
     394           0 :         *reply = talloc_move(mem_ctx, &state->reply);
     395           0 :         tevent_req_received(req);
     396             : 
     397           0 :         return 0;
     398             : }
     399             : 
     400             : struct dns_cli_request_state {
     401             :         struct tevent_context *ev;
     402             :         const char *nameserver;
     403             : 
     404             :         uint16_t req_id;
     405             : 
     406             :         DATA_BLOB query;
     407             : 
     408             :         struct dns_name_packet *reply;
     409             : };
     410             : 
     411             : static void dns_cli_request_udp_done(struct tevent_req *subreq);
     412             : static void dns_cli_request_tcp_done(struct tevent_req *subreq);
     413             : 
     414        1449 : struct tevent_req *dns_cli_request_send(TALLOC_CTX *mem_ctx,
     415             :                                         struct tevent_context *ev,
     416             :                                         const char *nameserver,
     417             :                                         const char *name,
     418             :                                         enum dns_qclass qclass,
     419             :                                         enum dns_qtype qtype)
     420             : {
     421           0 :         struct tevent_req *req, *subreq;
     422           0 :         struct dns_cli_request_state *state;
     423           0 :         struct dns_name_question question;
     424           0 :         struct dns_name_packet out_packet;
     425           0 :         enum ndr_err_code ndr_err;
     426             : 
     427        1449 :         req = tevent_req_create(mem_ctx, &state,
     428             :                                 struct dns_cli_request_state);
     429        1449 :         if (req == NULL) {
     430           0 :                 return NULL;
     431             :         }
     432        1449 :         state->ev = ev;
     433        1449 :         state->nameserver = nameserver;
     434             : 
     435        1449 :         DBG_DEBUG("Asking %s for %s/%d/%d via UDP\n", nameserver,
     436             :                   name, (int)qclass, (int)qtype);
     437             : 
     438        1449 :         generate_random_buffer((uint8_t *)&state->req_id,
     439             :                                sizeof(state->req_id));
     440             : 
     441        1449 :         question = (struct dns_name_question) {
     442             :                 .name = discard_const_p(char, name),
     443             :                 .question_type = qtype, .question_class = qclass
     444             :         };
     445             : 
     446        1449 :         out_packet = (struct dns_name_packet) {
     447        1449 :                 .id = state->req_id,
     448             :                 .operation = DNS_OPCODE_QUERY | DNS_FLAG_RECURSION_DESIRED,
     449             :                 .qdcount = 1,
     450             :                 .questions = &question
     451             :         };
     452             : 
     453        1449 :         ndr_err = ndr_push_struct_blob(
     454        1449 :                 &state->query, state, &out_packet,
     455             :                 (ndr_push_flags_fn_t)ndr_push_dns_name_packet);
     456        1449 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     457           0 :                 tevent_req_error(req, ndr_map_error2errno(ndr_err));
     458           0 :                 return tevent_req_post(req, ev);
     459             :         }
     460             : 
     461        1449 :         subreq = dns_udp_request_send(state, state->ev, state->nameserver,
     462        1449 :                                       state->query.data, state->query.length);
     463        1449 :         if (tevent_req_nomem(subreq, req)) {
     464           0 :                 return tevent_req_post(req, ev);
     465             :         }
     466        1449 :         tevent_req_set_callback(subreq, dns_cli_request_udp_done, req);
     467        1449 :         return req;
     468             : }
     469             : 
     470        1449 : static void dns_cli_request_udp_done(struct tevent_req *subreq)
     471             : {
     472        1449 :         struct tevent_req *req = tevent_req_callback_data(
     473             :                 subreq, struct tevent_req);
     474        1449 :         struct dns_cli_request_state *state = tevent_req_data(
     475             :                 req, struct dns_cli_request_state);
     476           0 :         DATA_BLOB reply;
     477           0 :         enum ndr_err_code ndr_err;
     478           0 :         uint16_t reply_id, operation;
     479           0 :         int ret;
     480             : 
     481        1449 :         ret = dns_udp_request_recv(subreq, state, &reply.data, &reply.length);
     482        1449 :         TALLOC_FREE(subreq);
     483        1449 :         if (tevent_req_error(req, ret)) {
     484          20 :                 return;
     485             :         }
     486             : 
     487        1429 :         if (reply.length < 4) {
     488           0 :                 DBG_DEBUG("Short DNS packet: length=%zu\n", reply.length);
     489           0 :                 tevent_req_error(req, EINVAL);
     490           0 :                 return;
     491             :         }
     492             : 
     493        1429 :         reply_id = PULL_BE_U16(reply.data, 0);
     494        1429 :         if (reply_id != state->req_id) {
     495           0 :                 DBG_DEBUG("Got id %"PRIu16", expected %"PRIu16"\n",
     496             :                           state->reply->id, state->req_id);
     497           0 :                 tevent_req_error(req, ENOMSG);
     498           0 :                 return;
     499             :         }
     500             : 
     501        1429 :         operation = PULL_BE_U16(reply.data, 2);
     502        1429 :         if ((operation & DNS_FLAG_TRUNCATION) != 0) {
     503           0 :                 DBG_DEBUG("Reply was truncated, retrying TCP\n");
     504           0 :                 subreq = dns_tcp_request_send(
     505             :                         state,
     506             :                         state->ev,
     507             :                         state->nameserver,
     508           0 :                         state->query.data,
     509             :                         state->query.length);
     510           0 :                 if (tevent_req_nomem(subreq, req)) {
     511           0 :                         return;
     512             :                 }
     513           0 :                 tevent_req_set_callback(subreq, dns_cli_request_tcp_done, req);
     514           0 :                 return;
     515             :         }
     516             : 
     517        1429 :         state->reply = talloc(state, struct dns_name_packet);
     518        1429 :         if (tevent_req_nomem(state->reply, req)) {
     519           0 :                 return;
     520             :         }
     521             : 
     522        1429 :         ndr_err = ndr_pull_struct_blob(
     523        1429 :                 &reply, state->reply, state->reply,
     524             :                 (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
     525        1429 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     526           0 :                 tevent_req_error(req, ndr_map_error2errno(ndr_err));
     527           0 :                 return;
     528             :         }
     529        1429 :         TALLOC_FREE(reply.data);
     530             : 
     531        1429 :         tevent_req_done(req);
     532             : }
     533             : 
     534           0 : static void dns_cli_request_tcp_done(struct tevent_req *subreq)
     535             : {
     536           0 :         struct tevent_req *req = tevent_req_callback_data(
     537             :                 subreq, struct tevent_req);
     538           0 :         struct dns_cli_request_state *state = tevent_req_data(
     539             :                 req, struct dns_cli_request_state);
     540           0 :         DATA_BLOB reply;
     541           0 :         enum ndr_err_code ndr_err;
     542           0 :         int ret;
     543             : 
     544           0 :         ret = dns_tcp_request_recv(subreq, state, &reply.data, &reply.length);
     545           0 :         TALLOC_FREE(subreq);
     546           0 :         if (tevent_req_error(req, ret)) {
     547           0 :                 return;
     548             :         }
     549             : 
     550           0 :         state->reply = talloc(state, struct dns_name_packet);
     551           0 :         if (tevent_req_nomem(state->reply, req)) {
     552           0 :                 return;
     553             :         }
     554             : 
     555           0 :         ndr_err = ndr_pull_struct_blob(
     556           0 :                 &reply, state->reply, state->reply,
     557             :                 (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
     558           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     559           0 :                 tevent_req_error(req, ndr_map_error2errno(ndr_err));
     560           0 :                 return;
     561             :         }
     562           0 :         TALLOC_FREE(reply.data);
     563             : 
     564           0 :         if (state->reply->id != state->req_id) {
     565           0 :                 DBG_DEBUG("Got id %"PRIu16", expected %"PRIu16"\n",
     566             :                           state->reply->id, state->req_id);
     567           0 :                 tevent_req_error(req, ENOMSG);
     568           0 :                 return;
     569             :         }
     570             : 
     571           0 :         DBG_DEBUG("Got op=%x %"PRIu16"/%"PRIu16"/%"PRIu16"/%"PRIu16
     572             :                   " recs\n", (int)state->reply->operation,
     573             :                   state->reply->qdcount, state->reply->ancount,
     574             :                   state->reply->nscount, state->reply->nscount);
     575             : 
     576           0 :         tevent_req_done(req);
     577             : }
     578             : 
     579        1449 : int dns_cli_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     580             :                          struct dns_name_packet **reply)
     581             : {
     582        1449 :         struct dns_cli_request_state *state = tevent_req_data(
     583             :                 req, struct dns_cli_request_state);
     584           0 :         int err;
     585             : 
     586        1449 :         if (tevent_req_is_unix_error(req, &err)) {
     587          20 :                 return err;
     588             :         }
     589        1429 :         *reply = talloc_move(mem_ctx, &state->reply);
     590        1429 :         return 0;
     591             : }

Generated by: LCOV version 1.14