LCOV - code coverage report
Current view: top level - source3/rpc_client - rpc_transport_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 200 259 77.2 %
Date: 2021-09-23 10:06:22 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC client transport over tstream
       4             :  *  Copyright (C) Simo Sorce 2010
       5             :  *
       6             :  *  This program is free software; you can redistribute it and/or modify
       7             :  *  it under the terms of the GNU General Public License as published by
       8             :  *  the Free Software Foundation; either version 3 of the License, or
       9             :  *  (at your option) any later version.
      10             :  *
      11             :  *  This program is distributed in the hope that it will be useful,
      12             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  *  GNU General Public License for more details.
      15             :  *
      16             :  *  You should have received a copy of the GNU General Public License
      17             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "includes.h"
      21             : #include "../lib/util/tevent_ntstatus.h"
      22             : #include "rpc_client/rpc_transport.h"
      23             : #include "lib/tsocket/tsocket.h"
      24             : #include "libcli/smb/tstream_smbXcli_np.h"
      25             : #include "cli_pipe.h"
      26             : 
      27             : #undef DBGC_CLASS
      28             : #define DBGC_CLASS DBGC_RPC_CLI
      29             : 
      30             : struct rpc_tstream_state {
      31             :         struct tstream_context *stream;
      32             :         struct tevent_queue *read_queue;
      33             :         struct tevent_queue *write_queue;
      34             :         unsigned int timeout;
      35             : };
      36             : 
      37          26 : static void rpc_tstream_disconnect(struct rpc_tstream_state *s)
      38             : {
      39          26 :         TALLOC_FREE(s->stream);
      40          26 : }
      41             : 
      42      561733 : static bool rpc_tstream_is_connected(void *priv)
      43             : {
      44      556054 :         struct rpc_tstream_state *transp =
      45        5679 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
      46             :         ssize_t ret;
      47             : 
      48      561733 :         if (!transp->stream) {
      49           0 :                 return false;
      50             :         }
      51             : 
      52      561733 :         if (!tstream_is_smbXcli_np(transp->stream)) {
      53      234613 :                 return true;
      54             :         }
      55             : 
      56      327120 :         ret = tstream_pending_bytes(transp->stream);
      57      327120 :         if (ret == -1) {
      58           0 :                 return false;
      59             :         }
      60             : 
      61      327120 :         return true;
      62             : }
      63             : 
      64         578 : static unsigned int rpc_tstream_set_timeout(void *priv, unsigned int timeout)
      65             : {
      66         487 :         struct rpc_tstream_state *transp =
      67          91 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
      68             :         int orig_timeout;
      69             :         bool ok;
      70             : 
      71         578 :         ok = rpc_tstream_is_connected(transp);
      72         578 :         if (!ok) {
      73           0 :                 return 0;
      74             :         }
      75             : 
      76         578 :         if (tstream_is_smbXcli_np(transp->stream)) {
      77         456 :                 transp->timeout = timeout;
      78         456 :                 return tstream_smbXcli_np_set_timeout(transp->stream, timeout);
      79             :         }
      80             : 
      81         122 :         orig_timeout = transp->timeout;
      82             : 
      83         122 :         transp->timeout = timeout;
      84             : 
      85         122 :         return orig_timeout;
      86             : }
      87             : 
      88             : struct rpc_tstream_next_vector_state {
      89             :         uint8_t *buf;
      90             :         size_t len;
      91             :         off_t ofs;
      92             : };
      93             : 
      94      229966 : static void rpc_tstream_next_vector_init(
      95             :                                 struct rpc_tstream_next_vector_state *s,
      96             :                                 uint8_t *buf, size_t len)
      97             : {
      98      229966 :         *s = (struct rpc_tstream_next_vector_state) {
      99      229966 :                 .buf = buf, .len = MIN(len, UINT16_MAX),
     100             :         };
     101      229966 : }
     102             : 
     103      459906 : static int rpc_tstream_next_vector(struct tstream_context *stream,
     104             :                                    void *private_data,
     105             :                                    TALLOC_CTX *mem_ctx,
     106             :                                    struct iovec **_vector,
     107             :                                    size_t *count)
     108             : {
     109      459906 :         struct rpc_tstream_next_vector_state *state =
     110             :                 (struct rpc_tstream_next_vector_state *)private_data;
     111             :         struct iovec *vector;
     112             : 
     113      459906 :         if (state->ofs == state->len) {
     114      229940 :                 *_vector = NULL;
     115      229940 :                 *count = 0;
     116      229940 :                 return 0;
     117             :         }
     118             : 
     119      229966 :         vector = talloc_array(mem_ctx, struct iovec, 1);
     120      229966 :         if (!vector) {
     121           0 :                 return -1;
     122             :         }
     123             : 
     124      229966 :         vector[0].iov_base = state->buf;
     125      229966 :         vector[0].iov_len = state->len;
     126             : 
     127      229966 :         state->ofs = state->len;
     128             : 
     129      229966 :         *_vector = vector;
     130      229966 :         *count = 1;
     131      229966 :         return 0;
     132             : }
     133             : 
     134             : struct rpc_tstream_read_state {
     135             :         struct rpc_tstream_state *transp;
     136             :         struct rpc_tstream_next_vector_state next_vector;
     137             :         ssize_t nread;
     138             : };
     139             : 
     140             : static void rpc_tstream_read_done(struct tevent_req *subreq);
     141             : 
     142      229966 : static struct tevent_req *rpc_tstream_read_send(TALLOC_CTX *mem_ctx,
     143             :                                              struct tevent_context *ev,
     144             :                                              uint8_t *data, size_t size,
     145             :                                              void *priv)
     146             : {
     147      227913 :         struct rpc_tstream_state *transp =
     148        2053 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
     149             :         struct tevent_req *req, *subreq;
     150             :         struct rpc_tstream_read_state *state;
     151             :         struct timeval endtime;
     152             : 
     153      229966 :         req = tevent_req_create(mem_ctx, &state, struct rpc_tstream_read_state);
     154      229966 :         if (req == NULL) {
     155           0 :                 return NULL;
     156             :         }
     157      229966 :         if (!rpc_tstream_is_connected(transp)) {
     158           0 :                 NTSTATUS status = NT_STATUS_CONNECTION_DISCONNECTED;
     159           0 :                 if (tstream_is_smbXcli_np(transp->stream)) {
     160           0 :                         status = NT_STATUS_PIPE_DISCONNECTED;
     161             :                 }
     162           0 :                 tevent_req_nterror(req, status);
     163           0 :                 return tevent_req_post(req, ev);
     164             :         }
     165      229966 :         state->transp = transp;
     166      229966 :         rpc_tstream_next_vector_init(&state->next_vector, data, size);
     167             : 
     168      229966 :         subreq = tstream_readv_pdu_queue_send(state, ev,
     169             :                                               transp->stream,
     170             :                                               transp->read_queue,
     171             :                                               rpc_tstream_next_vector,
     172      229966 :                                               &state->next_vector);
     173      229966 :         if (subreq == NULL) {
     174           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     175           0 :                 return tevent_req_post(req, ev);
     176             :         }
     177             : 
     178      229966 :         endtime = timeval_current_ofs_msec(transp->timeout);
     179      229966 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     180           0 :                 goto fail;
     181             :         }
     182             : 
     183      229966 :         tevent_req_set_callback(subreq, rpc_tstream_read_done, req);
     184      229966 :         return req;
     185           0 :  fail:
     186           0 :         TALLOC_FREE(req);
     187           0 :         return NULL;
     188             : }
     189             : 
     190      229966 : static void rpc_tstream_read_done(struct tevent_req *subreq)
     191             : {
     192      227913 :         struct tevent_req *req =
     193      229966 :                 tevent_req_callback_data(subreq, struct tevent_req);
     194      227913 :         struct rpc_tstream_read_state *state =
     195      229966 :                 tevent_req_data(req, struct rpc_tstream_read_state);
     196             :         int err;
     197             : 
     198      229966 :         state->nread = tstream_readv_pdu_queue_recv(subreq, &err);
     199      229966 :         TALLOC_FREE(subreq);
     200      229966 :         if (state->nread < 0) {
     201          26 :                 rpc_tstream_disconnect(state->transp);
     202          26 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     203          26 :                 return;
     204             :         }
     205      229940 :         tevent_req_done(req);
     206             : }
     207             : 
     208      229966 : static NTSTATUS rpc_tstream_read_recv(struct tevent_req *req, ssize_t *size)
     209             : {
     210      229966 :         struct rpc_tstream_read_state *state = tevent_req_data(
     211             :                 req, struct rpc_tstream_read_state);
     212             :         NTSTATUS status;
     213             : 
     214      229966 :         if (tevent_req_is_nterror(req, &status)) {
     215          26 :                 return status;
     216             :         }
     217      229940 :         *size = state->nread;
     218      229940 :         return NT_STATUS_OK;
     219             : }
     220             : 
     221             : struct rpc_tstream_write_state {
     222             :         struct tevent_context *ev;
     223             :         struct rpc_tstream_state *transp;
     224             :         struct iovec iov;
     225             :         ssize_t nwritten;
     226             : };
     227             : 
     228             : static void rpc_tstream_write_done(struct tevent_req *subreq);
     229             : 
     230       58825 : static struct tevent_req *rpc_tstream_write_send(TALLOC_CTX *mem_ctx,
     231             :                                               struct tevent_context *ev,
     232             :                                               const uint8_t *data, size_t size,
     233             :                                               void *priv)
     234             : {
     235       58763 :         struct rpc_tstream_state *transp =
     236          62 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
     237             :         struct tevent_req *req, *subreq;
     238             :         struct rpc_tstream_write_state *state;
     239             :         struct timeval endtime;
     240             : 
     241       58825 :         req = tevent_req_create(mem_ctx, &state, struct rpc_tstream_write_state);
     242       58825 :         if (req == NULL) {
     243           0 :                 return NULL;
     244             :         }
     245       58825 :         if (!rpc_tstream_is_connected(transp)) {
     246           0 :                 NTSTATUS status = NT_STATUS_CONNECTION_DISCONNECTED;
     247           0 :                 if (tstream_is_smbXcli_np(transp->stream)) {
     248           0 :                         status = NT_STATUS_PIPE_DISCONNECTED;
     249             :                 }
     250           0 :                 tevent_req_nterror(req, status);
     251           0 :                 return tevent_req_post(req, ev);
     252             :         }
     253       58825 :         state->ev = ev;
     254       58825 :         state->transp = transp;
     255       58825 :         state->iov.iov_base = discard_const_p(void *, data);
     256       58825 :         state->iov.iov_len = size;
     257             : 
     258       58825 :         subreq = tstream_writev_queue_send(state, ev,
     259             :                                            transp->stream,
     260             :                                            transp->write_queue,
     261       58825 :                                            &state->iov, 1);
     262       58825 :         if (subreq == NULL) {
     263           0 :                 goto fail;
     264             :         }
     265             : 
     266       58825 :         endtime = timeval_current_ofs_msec(transp->timeout);
     267       58825 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     268           0 :                 goto fail;
     269             :         }
     270             : 
     271       58825 :         tevent_req_set_callback(subreq, rpc_tstream_write_done, req);
     272       58825 :         return req;
     273           0 :  fail:
     274           0 :         TALLOC_FREE(req);
     275           0 :         return NULL;
     276             : }
     277             : 
     278       58825 : static void rpc_tstream_write_done(struct tevent_req *subreq)
     279             : {
     280       58763 :         struct tevent_req *req =
     281       58825 :                 tevent_req_callback_data(subreq, struct tevent_req);
     282       58763 :         struct rpc_tstream_write_state *state =
     283       58825 :                 tevent_req_data(req, struct rpc_tstream_write_state);
     284             :         int err;
     285             : 
     286       58825 :         state->nwritten = tstream_writev_queue_recv(subreq, &err);
     287       58825 :         TALLOC_FREE(subreq);
     288       58825 :         if (state->nwritten < 0) {
     289           0 :                 rpc_tstream_disconnect(state->transp);
     290           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     291           0 :                 return;
     292             :         }
     293       58825 :         tevent_req_done(req);
     294             : }
     295             : 
     296       58825 : static NTSTATUS rpc_tstream_write_recv(struct tevent_req *req, ssize_t *sent)
     297             : {
     298       58763 :         struct rpc_tstream_write_state *state =
     299       58825 :                 tevent_req_data(req, struct rpc_tstream_write_state);
     300             :         NTSTATUS status;
     301             : 
     302       58825 :         if (tevent_req_is_nterror(req, &status)) {
     303           0 :                 return status;
     304             :         }
     305       58825 :         *sent = state->nwritten;
     306       58825 :         return NT_STATUS_OK;
     307             : }
     308             : 
     309             : struct rpc_tstream_trans_state {
     310             :         struct tevent_context *ev;
     311             :         struct rpc_tstream_state *transp;
     312             :         struct iovec req;
     313             :         uint32_t max_rdata_len;
     314             :         struct iovec rep;
     315             : };
     316             : 
     317             : static void rpc_tstream_trans_writev(struct tevent_req *subreq);
     318             : static void rpc_tstream_trans_readv_pdu(struct tevent_req *subreq);
     319             : 
     320             : static int rpc_tstream_trans_next_vector(struct tstream_context *stream,
     321             :                                          void *private_data,
     322             :                                          TALLOC_CTX *mem_ctx,
     323             :                                          struct iovec **_vector,
     324             :                                          size_t *count);
     325             : 
     326      111932 : static struct tevent_req *rpc_tstream_trans_send(TALLOC_CTX *mem_ctx,
     327             :                                                  struct tevent_context *ev,
     328             :                                                  const uint8_t *data, size_t data_len,
     329             :                                                  uint32_t max_rdata_len,
     330             :                                                  void *priv)
     331             : {
     332      110029 :         struct rpc_tstream_state *transp =
     333        1903 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
     334             :         struct tevent_req *req, *subreq;
     335             :         struct rpc_tstream_trans_state *state;
     336             :         struct timeval endtime;
     337      111932 :         bool use_trans = false;
     338             : 
     339      111932 :         req = tevent_req_create(mem_ctx, &state,
     340             :                                 struct rpc_tstream_trans_state);
     341      111932 :         if (req == NULL) {
     342           0 :                 return NULL;
     343             :         }
     344             : 
     345      111932 :         if (!rpc_tstream_is_connected(transp)) {
     346           0 :                 NTSTATUS status = NT_STATUS_CONNECTION_DISCONNECTED;
     347           0 :                 if (tstream_is_smbXcli_np(transp->stream)) {
     348           0 :                         status = NT_STATUS_PIPE_DISCONNECTED;
     349             :                 }
     350           0 :                 tevent_req_nterror(req, status);
     351           0 :                 return tevent_req_post(req, ev);
     352             :         }
     353      111932 :         state->ev = ev;
     354      111932 :         state->transp = transp;
     355      111932 :         state->req.iov_len = data_len;
     356      111932 :         state->req.iov_base = discard_const_p(void *, data);
     357      111932 :         state->max_rdata_len = max_rdata_len;
     358             : 
     359      111932 :         endtime = timeval_current_ofs_msec(transp->timeout);
     360             : 
     361      111932 :         if (tstream_is_smbXcli_np(transp->stream)) {
     362      111932 :                 use_trans = true;
     363             :         }
     364      111932 :         if (tevent_queue_length(transp->write_queue) > 0) {
     365           0 :                 use_trans = false;
     366             :         }
     367      111932 :         if (tevent_queue_length(transp->read_queue) > 0) {
     368           0 :                 use_trans = false;
     369             :         }
     370             : 
     371      111932 :         if (use_trans) {
     372      111932 :                 tstream_smbXcli_np_use_trans(transp->stream);
     373             :         }
     374             : 
     375      111932 :         subreq = tstream_writev_queue_send(state, ev,
     376             :                                            transp->stream,
     377             :                                            transp->write_queue,
     378      111932 :                                            &state->req, 1);
     379      111932 :         if (tevent_req_nomem(subreq, req)) {
     380           0 :                 return tevent_req_post(req, ev);
     381             :         }
     382      111932 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     383           0 :                 return tevent_req_post(req, ev);
     384             :         }
     385      111932 :         tevent_req_set_callback(subreq, rpc_tstream_trans_writev, req);
     386             : 
     387      111932 :         subreq = tstream_readv_pdu_queue_send(state, ev,
     388             :                                               transp->stream,
     389             :                                               transp->read_queue,
     390             :                                               rpc_tstream_trans_next_vector,
     391             :                                               state);
     392      111932 :         if (tevent_req_nomem(subreq, req)) {
     393           0 :                 return tevent_req_post(req, ev);
     394             :         }
     395      111932 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     396           0 :                 return tevent_req_post(req, ev);
     397             :         }
     398      111932 :         tevent_req_set_callback(subreq, rpc_tstream_trans_readv_pdu, req);
     399             : 
     400      111932 :         return req;
     401             : }
     402             : 
     403      111932 : static void rpc_tstream_trans_writev(struct tevent_req *subreq)
     404             : {
     405      110029 :         struct tevent_req *req =
     406      111932 :                 tevent_req_callback_data(subreq,
     407             :                 struct tevent_req);
     408      110029 :         struct rpc_tstream_trans_state *state =
     409      111932 :                 tevent_req_data(req,
     410             :                 struct rpc_tstream_trans_state);
     411             :         int ret;
     412             :         int err;
     413             : 
     414      111932 :         ret = tstream_writev_queue_recv(subreq, &err);
     415      111932 :         TALLOC_FREE(subreq);
     416      111932 :         if (ret == -1) {
     417           0 :                 rpc_tstream_disconnect(state->transp);
     418           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     419           0 :                 return;
     420             :         }
     421             : }
     422             : 
     423      223864 : static int rpc_tstream_trans_next_vector(struct tstream_context *stream,
     424             :                                          void *private_data,
     425             :                                          TALLOC_CTX *mem_ctx,
     426             :                                          struct iovec **_vector,
     427             :                                          size_t *count)
     428             : {
     429      220058 :         struct rpc_tstream_trans_state *state =
     430        3806 :                 talloc_get_type_abort(private_data,
     431             :                 struct rpc_tstream_trans_state);
     432             :         struct iovec *vector;
     433             : 
     434      223864 :         if (state->max_rdata_len == state->rep.iov_len) {
     435      111932 :                 *_vector = NULL;
     436      111932 :                 *count = 0;
     437      111932 :                 return 0;
     438             :         }
     439             : 
     440      111932 :         state->rep.iov_base = talloc_array(state, uint8_t,
     441             :                                            state->max_rdata_len);
     442      111932 :         if (state->rep.iov_base == NULL) {
     443           0 :                 return -1;
     444             :         }
     445      111932 :         state->rep.iov_len = state->max_rdata_len;
     446             : 
     447      111932 :         vector = talloc_array(mem_ctx, struct iovec, 1);
     448      111932 :         if (!vector) {
     449           0 :                 return -1;
     450             :         }
     451             : 
     452      111932 :         vector[0] = state->rep;
     453             : 
     454      111932 :         *_vector = vector;
     455      111932 :         *count = 1;
     456      111932 :         return 0;
     457             : }
     458             : 
     459      111932 : static void rpc_tstream_trans_readv_pdu(struct tevent_req *subreq)
     460             : {
     461      110029 :         struct tevent_req *req =
     462      111932 :                 tevent_req_callback_data(subreq,
     463             :                 struct tevent_req);
     464      110029 :         struct rpc_tstream_trans_state *state =
     465      111932 :                 tevent_req_data(req,
     466             :                 struct rpc_tstream_trans_state);
     467             :         int ret;
     468             :         int err;
     469             : 
     470      111932 :         ret = tstream_readv_pdu_queue_recv(subreq, &err);
     471      111932 :         TALLOC_FREE(subreq);
     472      111932 :         if (ret == -1) {
     473           0 :                 rpc_tstream_disconnect(state->transp);
     474           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     475           0 :                 return;
     476             :         }
     477             : 
     478      111932 :         tevent_req_done(req);
     479             : }
     480             : 
     481      111932 : static NTSTATUS rpc_tstream_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     482             :                                        uint8_t **prdata, uint32_t *prdata_len)
     483             : {
     484      110029 :         struct rpc_tstream_trans_state *state =
     485      111932 :                 tevent_req_data(req,
     486             :                 struct rpc_tstream_trans_state);
     487             :         NTSTATUS status;
     488             : 
     489      111932 :         if (tevent_req_is_nterror(req, &status)) {
     490           0 :                 return status;
     491             :         }
     492             : 
     493      111932 :         *prdata = (uint8_t *)talloc_move(mem_ctx, &state->rep.iov_base);
     494      111932 :         *prdata_len = state->rep.iov_len;
     495      111932 :         return NT_STATUS_OK;
     496             : }
     497             : 
     498             : /**
     499             : * @brief Initialize a tstream transport facility
     500             : *        NOTE: this function will talloc_steal, the stream and the queues.
     501             : *
     502             : * @param mem_ctx        - memory context used to allocate the transport
     503             : * @param stream         - a ready to use tstream
     504             : * @param presult        - the transport structure
     505             : *
     506             : * @return               - a NT Status error code.
     507             : */
     508       10268 : NTSTATUS rpc_transport_tstream_init(TALLOC_CTX *mem_ctx,
     509             :                                 struct tstream_context **stream,
     510             :                                 struct rpc_cli_transport **presult)
     511             : {
     512             :         struct rpc_cli_transport *result;
     513             :         struct rpc_tstream_state *state;
     514             : 
     515       10268 :         result = talloc(mem_ctx, struct rpc_cli_transport);
     516       10268 :         if (result == NULL) {
     517           0 :                 return NT_STATUS_NO_MEMORY;
     518             :         }
     519       10268 :         state = talloc(result, struct rpc_tstream_state);
     520       10268 :         if (state == NULL) {
     521           0 :                 TALLOC_FREE(result);
     522           0 :                 return NT_STATUS_NO_MEMORY;
     523             :         }
     524       10268 :         result->priv = state;
     525             : 
     526       10268 :         state->read_queue = tevent_queue_create(state, "read_queue");
     527       10268 :         if (state->read_queue == NULL) {
     528           0 :                 TALLOC_FREE(result);
     529           0 :                 return NT_STATUS_NO_MEMORY;
     530             :         }
     531       10268 :         state->write_queue = tevent_queue_create(state, "write_queue");
     532       10268 :         if (state->write_queue == NULL) {
     533           0 :                 TALLOC_FREE(result);
     534           0 :                 return NT_STATUS_NO_MEMORY;
     535             :         }
     536             : 
     537       10268 :         state->stream = talloc_move(state, stream);
     538       10268 :         state->timeout = 10000; /* 10 seconds. */
     539             : 
     540       10268 :         if (tstream_is_smbXcli_np(state->stream)) {
     541        9679 :                 result->trans_send = rpc_tstream_trans_send;
     542        9679 :                 result->trans_recv = rpc_tstream_trans_recv;
     543             :         } else {
     544         589 :                 result->trans_send = NULL;
     545         589 :                 result->trans_recv = NULL;
     546             :         }
     547       10268 :         result->write_send = rpc_tstream_write_send;
     548       10268 :         result->write_recv = rpc_tstream_write_recv;
     549       10268 :         result->read_send = rpc_tstream_read_send;
     550       10268 :         result->read_recv = rpc_tstream_read_recv;
     551       10268 :         result->is_connected = rpc_tstream_is_connected;
     552       10268 :         result->set_timeout = rpc_tstream_set_timeout;
     553             : 
     554       10268 :         *presult = result;
     555       10268 :         return NT_STATUS_OK;
     556             : }

Generated by: LCOV version 1.13