LCOV - code coverage report
Current view: top level - source3/rpc_client - rpc_transport_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 177 287 61.7 %
Date: 2024-04-21 15:09:00 Functions: 16 18 88.9 %

          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           0 : static void rpc_tstream_disconnect(struct rpc_tstream_state *s)
      38             : {
      39           0 :         TALLOC_FREE(s->stream);
      40           0 : }
      41             : 
      42     2200648 : static bool rpc_tstream_is_connected(void *priv)
      43             : {
      44           0 :         struct rpc_tstream_state *transp =
      45     2200648 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
      46           0 :         ssize_t ret;
      47             : 
      48     2200648 :         if (!transp->stream) {
      49           0 :                 return false;
      50             :         }
      51             : 
      52     2200648 :         if (!tstream_is_smbXcli_np(transp->stream)) {
      53     1869334 :                 return true;
      54             :         }
      55             : 
      56      331314 :         ret = tstream_pending_bytes(transp->stream);
      57      331314 :         if (ret == -1) {
      58           0 :                 return false;
      59             :         }
      60             : 
      61      331314 :         return true;
      62             : }
      63             : 
      64         716 : static unsigned int rpc_tstream_set_timeout(void *priv, unsigned int timeout)
      65             : {
      66           0 :         struct rpc_tstream_state *transp =
      67         716 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
      68           0 :         int orig_timeout;
      69           0 :         bool ok;
      70             : 
      71         716 :         ok = rpc_tstream_is_connected(transp);
      72         716 :         if (!ok) {
      73           0 :                 return 0;
      74             :         }
      75             : 
      76         716 :         if (tstream_is_smbXcli_np(transp->stream)) {
      77         482 :                 transp->timeout = timeout;
      78         482 :                 return tstream_smbXcli_np_set_timeout(transp->stream, timeout);
      79             :         }
      80             : 
      81         234 :         orig_timeout = transp->timeout;
      82             : 
      83         234 :         transp->timeout = timeout;
      84             : 
      85         234 :         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     1064156 : static void rpc_tstream_next_vector_init(
      95             :                                 struct rpc_tstream_next_vector_state *s,
      96             :                                 uint8_t *buf, size_t len)
      97             : {
      98     1064156 :         *s = (struct rpc_tstream_next_vector_state) {
      99     1064156 :                 .buf = buf, .len = MIN(len, UINT16_MAX),
     100             :         };
     101     1064156 : }
     102             : 
     103     2128312 : 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     2128312 :         struct rpc_tstream_next_vector_state *state =
     110             :                 (struct rpc_tstream_next_vector_state *)private_data;
     111           0 :         struct iovec *vector;
     112             : 
     113     2128312 :         if (state->ofs == state->len) {
     114     1064156 :                 *_vector = NULL;
     115     1064156 :                 *count = 0;
     116     1064156 :                 return 0;
     117             :         }
     118             : 
     119     1064156 :         vector = talloc_array(mem_ctx, struct iovec, 1);
     120     1064156 :         if (!vector) {
     121           0 :                 return -1;
     122             :         }
     123             : 
     124     1064156 :         vector[0].iov_base = state->buf;
     125     1064156 :         vector[0].iov_len = state->len;
     126             : 
     127     1064156 :         state->ofs = state->len;
     128             : 
     129     1064156 :         *_vector = vector;
     130     1064156 :         *count = 1;
     131     1064156 :         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     1064156 : 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           0 :         struct rpc_tstream_state *transp =
     148     1064156 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
     149           0 :         struct tevent_req *req, *subreq;
     150           0 :         struct rpc_tstream_read_state *state;
     151           0 :         struct timeval endtime;
     152             : 
     153     1064156 :         req = tevent_req_create(mem_ctx, &state, struct rpc_tstream_read_state);
     154     1064156 :         if (req == NULL) {
     155           0 :                 return NULL;
     156             :         }
     157     1064156 :         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     1064156 :         state->transp = transp;
     166     1064156 :         rpc_tstream_next_vector_init(&state->next_vector, data, size);
     167             : 
     168     1064156 :         subreq = tstream_readv_pdu_queue_send(state, ev,
     169             :                                               transp->stream,
     170             :                                               transp->read_queue,
     171             :                                               rpc_tstream_next_vector,
     172     1064156 :                                               &state->next_vector);
     173     1064156 :         if (subreq == NULL) {
     174           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     175           0 :                 return tevent_req_post(req, ev);
     176             :         }
     177             : 
     178     1064156 :         endtime = timeval_current_ofs_msec(transp->timeout);
     179     1064156 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     180           0 :                 goto fail;
     181             :         }
     182             : 
     183     1064156 :         tevent_req_set_callback(subreq, rpc_tstream_read_done, req);
     184     1064156 :         return req;
     185           0 :  fail:
     186           0 :         TALLOC_FREE(req);
     187           0 :         return NULL;
     188             : }
     189             : 
     190     1064156 : static void rpc_tstream_read_done(struct tevent_req *subreq)
     191             : {
     192           0 :         struct tevent_req *req =
     193     1064156 :                 tevent_req_callback_data(subreq, struct tevent_req);
     194           0 :         struct rpc_tstream_read_state *state =
     195     1064156 :                 tevent_req_data(req, struct rpc_tstream_read_state);
     196           0 :         int err;
     197             : 
     198     1064156 :         state->nread = tstream_readv_pdu_queue_recv(subreq, &err);
     199     1064156 :         TALLOC_FREE(subreq);
     200     1064156 :         if (state->nread < 0) {
     201           0 :                 rpc_tstream_disconnect(state->transp);
     202           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     203           0 :                 return;
     204             :         }
     205     1064156 :         tevent_req_done(req);
     206             : }
     207             : 
     208     1064156 : static NTSTATUS rpc_tstream_read_recv(struct tevent_req *req, ssize_t *size)
     209             : {
     210     1064156 :         struct rpc_tstream_read_state *state = tevent_req_data(
     211             :                 req, struct rpc_tstream_read_state);
     212           0 :         NTSTATUS status;
     213             : 
     214     1064156 :         if (tevent_req_is_nterror(req, &status)) {
     215           0 :                 return status;
     216             :         }
     217     1064156 :         *size = state->nread;
     218     1064156 :         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      475086 : 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           0 :         struct rpc_tstream_state *transp =
     236      475086 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
     237           0 :         struct tevent_req *req, *subreq;
     238           0 :         struct rpc_tstream_write_state *state;
     239           0 :         struct timeval endtime;
     240             : 
     241      475086 :         req = tevent_req_create(mem_ctx, &state, struct rpc_tstream_write_state);
     242      475086 :         if (req == NULL) {
     243           0 :                 return NULL;
     244             :         }
     245      475086 :         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      475086 :         state->ev = ev;
     254      475086 :         state->transp = transp;
     255      475086 :         state->iov.iov_base = discard_const_p(void *, data);
     256      475086 :         state->iov.iov_len = size;
     257             : 
     258      475086 :         subreq = tstream_writev_queue_send(state, ev,
     259             :                                            transp->stream,
     260             :                                            transp->write_queue,
     261      475086 :                                            &state->iov, 1);
     262      475086 :         if (subreq == NULL) {
     263           0 :                 goto fail;
     264             :         }
     265             : 
     266      475086 :         endtime = timeval_current_ofs_msec(transp->timeout);
     267      475086 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     268           0 :                 goto fail;
     269             :         }
     270             : 
     271      475086 :         tevent_req_set_callback(subreq, rpc_tstream_write_done, req);
     272      475086 :         return req;
     273           0 :  fail:
     274           0 :         TALLOC_FREE(req);
     275           0 :         return NULL;
     276             : }
     277             : 
     278      475086 : static void rpc_tstream_write_done(struct tevent_req *subreq)
     279             : {
     280           0 :         struct tevent_req *req =
     281      475086 :                 tevent_req_callback_data(subreq, struct tevent_req);
     282           0 :         struct rpc_tstream_write_state *state =
     283      475086 :                 tevent_req_data(req, struct rpc_tstream_write_state);
     284           0 :         int err;
     285             : 
     286      475086 :         state->nwritten = tstream_writev_queue_recv(subreq, &err);
     287      475086 :         TALLOC_FREE(subreq);
     288      475086 :         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      475086 :         tevent_req_done(req);
     294             : }
     295             : 
     296      475086 : static NTSTATUS rpc_tstream_write_recv(struct tevent_req *req, ssize_t *sent)
     297             : {
     298           0 :         struct rpc_tstream_write_state *state =
     299      475086 :                 tevent_req_data(req, struct rpc_tstream_write_state);
     300           0 :         NTSTATUS status;
     301             : 
     302      475086 :         if (tevent_req_is_nterror(req, &status)) {
     303           0 :                 return status;
     304             :         }
     305      475086 :         *sent = state->nwritten;
     306      475086 :         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      113360 : 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           0 :         struct rpc_tstream_state *transp =
     333      113360 :                 talloc_get_type_abort(priv, struct rpc_tstream_state);
     334           0 :         struct tevent_req *req, *subreq;
     335           0 :         struct rpc_tstream_trans_state *state;
     336           0 :         struct timeval endtime;
     337      113360 :         bool use_trans = false;
     338             : 
     339      113360 :         req = tevent_req_create(mem_ctx, &state,
     340             :                                 struct rpc_tstream_trans_state);
     341      113360 :         if (req == NULL) {
     342           0 :                 return NULL;
     343             :         }
     344             : 
     345      113360 :         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      113360 :         state->ev = ev;
     354      113360 :         state->transp = transp;
     355      113360 :         state->req.iov_len = data_len;
     356      113360 :         state->req.iov_base = discard_const_p(void *, data);
     357      113360 :         state->max_rdata_len = max_rdata_len;
     358             : 
     359      113360 :         endtime = timeval_current_ofs_msec(transp->timeout);
     360             : 
     361      113360 :         if (tstream_is_smbXcli_np(transp->stream)) {
     362      113360 :                 use_trans = true;
     363             :         }
     364      113360 :         if (tevent_queue_length(transp->write_queue) > 0) {
     365           0 :                 use_trans = false;
     366             :         }
     367      113360 :         if (tevent_queue_length(transp->read_queue) > 0) {
     368           0 :                 use_trans = false;
     369             :         }
     370             : 
     371      113360 :         if (use_trans) {
     372      113360 :                 tstream_smbXcli_np_use_trans(transp->stream);
     373             :         }
     374             : 
     375      113360 :         subreq = tstream_writev_queue_send(state, ev,
     376             :                                            transp->stream,
     377             :                                            transp->write_queue,
     378      113360 :                                            &state->req, 1);
     379      113360 :         if (tevent_req_nomem(subreq, req)) {
     380           0 :                 return tevent_req_post(req, ev);
     381             :         }
     382      113360 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     383           0 :                 return tevent_req_post(req, ev);
     384             :         }
     385      113360 :         tevent_req_set_callback(subreq, rpc_tstream_trans_writev, req);
     386             : 
     387      113360 :         subreq = tstream_readv_pdu_queue_send(state, ev,
     388             :                                               transp->stream,
     389             :                                               transp->read_queue,
     390             :                                               rpc_tstream_trans_next_vector,
     391             :                                               state);
     392      113360 :         if (tevent_req_nomem(subreq, req)) {
     393           0 :                 return tevent_req_post(req, ev);
     394             :         }
     395      113360 :         if (!tevent_req_set_endtime(subreq, ev, endtime)) {
     396           0 :                 return tevent_req_post(req, ev);
     397             :         }
     398      113360 :         tevent_req_set_callback(subreq, rpc_tstream_trans_readv_pdu, req);
     399             : 
     400      113360 :         return req;
     401             : }
     402             : 
     403      113360 : static void rpc_tstream_trans_writev(struct tevent_req *subreq)
     404             : {
     405           0 :         struct tevent_req *req =
     406      113360 :                 tevent_req_callback_data(subreq,
     407             :                 struct tevent_req);
     408           0 :         struct rpc_tstream_trans_state *state =
     409      113360 :                 tevent_req_data(req,
     410             :                 struct rpc_tstream_trans_state);
     411           0 :         int ret;
     412           0 :         int err;
     413             : 
     414      113360 :         ret = tstream_writev_queue_recv(subreq, &err);
     415      113360 :         TALLOC_FREE(subreq);
     416      113360 :         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      226720 : 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           0 :         struct rpc_tstream_trans_state *state =
     430      226720 :                 talloc_get_type_abort(private_data,
     431             :                 struct rpc_tstream_trans_state);
     432           0 :         struct iovec *vector;
     433             : 
     434      226720 :         if (state->max_rdata_len == state->rep.iov_len) {
     435      113360 :                 *_vector = NULL;
     436      113360 :                 *count = 0;
     437      113360 :                 return 0;
     438             :         }
     439             : 
     440      113360 :         state->rep.iov_base = talloc_array(state, uint8_t,
     441             :                                            state->max_rdata_len);
     442      113360 :         if (state->rep.iov_base == NULL) {
     443           0 :                 return -1;
     444             :         }
     445      113360 :         state->rep.iov_len = state->max_rdata_len;
     446             : 
     447      113360 :         vector = talloc_array(mem_ctx, struct iovec, 1);
     448      113360 :         if (!vector) {
     449           0 :                 return -1;
     450             :         }
     451             : 
     452      113360 :         vector[0] = state->rep;
     453             : 
     454      113360 :         *_vector = vector;
     455      113360 :         *count = 1;
     456      113360 :         return 0;
     457             : }
     458             : 
     459      113360 : static void rpc_tstream_trans_readv_pdu(struct tevent_req *subreq)
     460             : {
     461           0 :         struct tevent_req *req =
     462      113360 :                 tevent_req_callback_data(subreq,
     463             :                 struct tevent_req);
     464           0 :         struct rpc_tstream_trans_state *state =
     465      113360 :                 tevent_req_data(req,
     466             :                 struct rpc_tstream_trans_state);
     467           0 :         int ret;
     468           0 :         int err;
     469             : 
     470      113360 :         ret = tstream_readv_pdu_queue_recv(subreq, &err);
     471      113360 :         TALLOC_FREE(subreq);
     472      113360 :         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      113360 :         tevent_req_done(req);
     479             : }
     480             : 
     481      113360 : static NTSTATUS rpc_tstream_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     482             :                                        uint8_t **prdata, uint32_t *prdata_len)
     483             : {
     484           0 :         struct rpc_tstream_trans_state *state =
     485      113360 :                 tevent_req_data(req,
     486             :                 struct rpc_tstream_trans_state);
     487           0 :         NTSTATUS status;
     488             : 
     489      113360 :         if (tevent_req_is_nterror(req, &status)) {
     490           0 :                 return status;
     491             :         }
     492             : 
     493      113360 :         *prdata = (uint8_t *)talloc_move(mem_ctx, &state->rep.iov_base);
     494      113360 :         *prdata_len = state->rep.iov_len;
     495      113360 :         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       40968 : NTSTATUS rpc_transport_tstream_init(TALLOC_CTX *mem_ctx,
     509             :                                 struct tstream_context **stream,
     510             :                                 struct rpc_cli_transport **presult)
     511             : {
     512           0 :         struct rpc_cli_transport *result;
     513           0 :         struct rpc_tstream_state *state;
     514             : 
     515       40968 :         result = talloc(mem_ctx, struct rpc_cli_transport);
     516       40968 :         if (result == NULL) {
     517           0 :                 return NT_STATUS_NO_MEMORY;
     518             :         }
     519       40968 :         state = talloc(result, struct rpc_tstream_state);
     520       40968 :         if (state == NULL) {
     521           0 :                 TALLOC_FREE(result);
     522           0 :                 return NT_STATUS_NO_MEMORY;
     523             :         }
     524       40968 :         result->priv = state;
     525             : 
     526       40968 :         state->read_queue = tevent_queue_create(state, "read_queue");
     527       40968 :         if (state->read_queue == NULL) {
     528           0 :                 TALLOC_FREE(result);
     529           0 :                 return NT_STATUS_NO_MEMORY;
     530             :         }
     531       40968 :         state->write_queue = tevent_queue_create(state, "write_queue");
     532       40968 :         if (state->write_queue == NULL) {
     533           0 :                 TALLOC_FREE(result);
     534           0 :                 return NT_STATUS_NO_MEMORY;
     535             :         }
     536             : 
     537       40968 :         state->stream = talloc_move(state, stream);
     538       40968 :         state->timeout = 10000; /* 10 seconds. */
     539             : 
     540       40968 :         if (tstream_is_smbXcli_np(state->stream)) {
     541       10060 :                 result->trans_send = rpc_tstream_trans_send;
     542       10060 :                 result->trans_recv = rpc_tstream_trans_recv;
     543             :         } else {
     544       30908 :                 result->trans_send = NULL;
     545       30908 :                 result->trans_recv = NULL;
     546             :         }
     547       40968 :         result->write_send = rpc_tstream_write_send;
     548       40968 :         result->write_recv = rpc_tstream_write_recv;
     549       40968 :         result->read_send = rpc_tstream_read_send;
     550       40968 :         result->read_recv = rpc_tstream_read_recv;
     551       40968 :         result->is_connected = rpc_tstream_is_connected;
     552       40968 :         result->set_timeout = rpc_tstream_set_timeout;
     553             : 
     554       40968 :         *presult = result;
     555       40968 :         return NT_STATUS_OK;
     556             : }
     557             : 
     558           0 : struct tstream_context *rpc_transport_get_tstream(
     559             :                 struct rpc_cli_transport *transport)
     560             : {
     561           0 :         struct rpc_tstream_state *state = talloc_get_type_abort(
     562             :                         transport->priv, struct rpc_tstream_state);
     563           0 :         return state->stream;
     564             : }

Generated by: LCOV version 1.14