LCOV - code coverage report
Current view: top level - librpc/rpc - binding_handle.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 182 251 72.5 %
Date: 2024-05-31 13:13:24 Functions: 15 18 83.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    dcerpc binding handle functions
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include <tevent.h>
      24             : #include "../lib/util/tevent_ntstatus.h"
      25             : #include "librpc/rpc/dcerpc.h"
      26             : #include "rpc_common.h"
      27             : 
      28             : struct dcerpc_binding_handle {
      29             :         void *private_data;
      30             :         const struct dcerpc_binding_handle_ops *ops;
      31             :         const char *location;
      32             :         const struct GUID *object;
      33             :         const struct ndr_interface_table *table;
      34             :         struct tevent_context *sync_ev;
      35             : };
      36             : 
      37       70601 : static int dcerpc_binding_handle_destructor(struct dcerpc_binding_handle *b)
      38             : {
      39       70601 :         return 0;
      40             : }
      41             : 
      42       71217 : struct dcerpc_binding_handle *_dcerpc_binding_handle_create(TALLOC_CTX *mem_ctx,
      43             :                                         const struct dcerpc_binding_handle_ops *ops,
      44             :                                         const struct GUID *object,
      45             :                                         const struct ndr_interface_table *table,
      46             :                                         void *pstate,
      47             :                                         size_t psize,
      48             :                                         const char *type,
      49             :                                         const char *location)
      50             : {
      51         905 :         struct dcerpc_binding_handle *h;
      52       71217 :         void **ppstate = (void **)pstate;
      53         905 :         void *state;
      54             : 
      55       71217 :         h = talloc_zero(mem_ctx, struct dcerpc_binding_handle);
      56       71217 :         if (h == NULL) {
      57           0 :                 return NULL;
      58             :         }
      59       71217 :         h->ops               = ops;
      60       71217 :         h->location  = location;
      61       71217 :         h->object    = object;
      62       71217 :         h->table     = table;
      63             : 
      64       71217 :         state = talloc_zero_size(h, psize);
      65       71217 :         if (state == NULL) {
      66           0 :                 talloc_free(h);
      67           0 :                 return NULL;
      68             :         }
      69       71217 :         talloc_set_name_const(state, type);
      70             : 
      71       71217 :         h->private_data = state;
      72             : 
      73       71217 :         talloc_set_destructor(h, dcerpc_binding_handle_destructor);
      74             : 
      75       71217 :         *ppstate = state;
      76       71217 :         return h;
      77             : }
      78             : 
      79     4261784 : void *_dcerpc_binding_handle_data(struct dcerpc_binding_handle *h)
      80             : {
      81     4261784 :         return h->private_data;
      82             : }
      83             : 
      84       20019 : void dcerpc_binding_handle_set_sync_ev(struct dcerpc_binding_handle *h,
      85             :                                        struct tevent_context *ev)
      86             : {
      87       20019 :         h->sync_ev = ev;
      88       20019 : }
      89             : 
      90        5283 : bool dcerpc_binding_handle_is_connected(struct dcerpc_binding_handle *h)
      91             : {
      92        5283 :         return h->ops->is_connected(h);
      93             : }
      94             : 
      95        6059 : uint32_t dcerpc_binding_handle_set_timeout(struct dcerpc_binding_handle *h,
      96             :                                            uint32_t timeout)
      97             : {
      98        6059 :         return h->ops->set_timeout(h, timeout);
      99             : }
     100             : 
     101        1788 : void dcerpc_binding_handle_auth_info(struct dcerpc_binding_handle *h,
     102             :                                      enum dcerpc_AuthType *auth_type,
     103             :                                      enum dcerpc_AuthLevel *auth_level)
     104             : {
     105         256 :         enum dcerpc_AuthType _auth_type;
     106         256 :         enum dcerpc_AuthLevel _auth_level;
     107             : 
     108        1788 :         if (auth_type == NULL) {
     109        1196 :                 auth_type = &_auth_type;
     110             :         }
     111             : 
     112        1788 :         if (auth_level == NULL) {
     113           0 :                 auth_level = &_auth_level;
     114             :         }
     115             : 
     116        1788 :         *auth_type = DCERPC_AUTH_TYPE_NONE;
     117        1788 :         *auth_level = DCERPC_AUTH_LEVEL_NONE;
     118             : 
     119        1788 :         if (h->ops->auth_info == NULL) {
     120           0 :                 return;
     121             :         }
     122             : 
     123        1788 :         h->ops->auth_info(h, auth_type, auth_level);
     124             : }
     125             : 
     126             : struct dcerpc_binding_handle_raw_call_state {
     127             :         const struct dcerpc_binding_handle_ops *ops;
     128             :         uint8_t *out_data;
     129             :         size_t out_length;
     130             :         uint32_t out_flags;
     131             : };
     132             : 
     133             : static void dcerpc_binding_handle_raw_call_done(struct tevent_req *subreq);
     134             : 
     135     1084007 : struct tevent_req *dcerpc_binding_handle_raw_call_send(TALLOC_CTX *mem_ctx,
     136             :                                                 struct tevent_context *ev,
     137             :                                                 struct dcerpc_binding_handle *h,
     138             :                                                 const struct GUID *object,
     139             :                                                 uint32_t opnum,
     140             :                                                 uint32_t in_flags,
     141             :                                                 const uint8_t *in_data,
     142             :                                                 size_t in_length)
     143             : {
     144       19990 :         struct tevent_req *req;
     145       19990 :         struct dcerpc_binding_handle_raw_call_state *state;
     146       19990 :         struct tevent_req *subreq;
     147             : 
     148     1084007 :         req = tevent_req_create(mem_ctx, &state,
     149             :                                 struct dcerpc_binding_handle_raw_call_state);
     150     1084007 :         if (req == NULL) {
     151           0 :                 return NULL;
     152             :         }
     153     1084007 :         state->ops = h->ops;
     154     1084007 :         state->out_data = NULL;
     155     1084007 :         state->out_length = 0;
     156     1084007 :         state->out_flags = 0;
     157             : 
     158     1084007 :         if (h->object != NULL) {
     159             :                 /*
     160             :                  * If an object is set on the binding handle,
     161             :                  * per request object passing is not allowed.
     162             :                  */
     163         256 :                 if (object != NULL) {
     164           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
     165           0 :                         return tevent_req_post(req, ev);
     166             :                 }
     167             : 
     168             :                 /*
     169             :                  * We use the object from the binding handle
     170             :                  */
     171         200 :                 object = h->object;
     172             :         }
     173             : 
     174     1084007 :         subreq = state->ops->raw_call_send(state, ev, h,
     175             :                                            object, opnum,
     176             :                                            in_flags, in_data, in_length);
     177     1084007 :         if (tevent_req_nomem(subreq, req)) {
     178           0 :                 return tevent_req_post(req, ev);
     179             :         }
     180     1084007 :         tevent_req_set_callback(subreq, dcerpc_binding_handle_raw_call_done, req);
     181             : 
     182     1084007 :         return req;
     183             : }
     184             : 
     185     1079257 : static void dcerpc_binding_handle_raw_call_done(struct tevent_req *subreq)
     186             : {
     187     1079257 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     188             :                                  struct tevent_req);
     189       19990 :         struct dcerpc_binding_handle_raw_call_state *state =
     190     1079257 :                 tevent_req_data(req,
     191             :                 struct dcerpc_binding_handle_raw_call_state);
     192       19990 :         NTSTATUS error;
     193             : 
     194     1079257 :         error = state->ops->raw_call_recv(subreq, state,
     195             :                                           &state->out_data,
     196             :                                           &state->out_length,
     197             :                                           &state->out_flags);
     198     1079257 :         TALLOC_FREE(subreq);
     199     1079257 :         if (tevent_req_nterror(req, error)) {
     200        3044 :                 return;
     201             :         }
     202             : 
     203     1076213 :         tevent_req_done(req);
     204             : }
     205             : 
     206     1079257 : NTSTATUS dcerpc_binding_handle_raw_call_recv(struct tevent_req *req,
     207             :                                              TALLOC_CTX *mem_ctx,
     208             :                                              uint8_t **out_data,
     209             :                                              size_t *out_length,
     210             :                                              uint32_t *out_flags)
     211             : {
     212       19990 :         struct dcerpc_binding_handle_raw_call_state *state =
     213     1079257 :                 tevent_req_data(req,
     214             :                 struct dcerpc_binding_handle_raw_call_state);
     215       19990 :         NTSTATUS error;
     216             : 
     217     1079257 :         if (tevent_req_is_nterror(req, &error)) {
     218        3044 :                 tevent_req_received(req);
     219        3044 :                 return error;
     220             :         }
     221             : 
     222     1076213 :         *out_data = talloc_move(mem_ctx, &state->out_data);
     223     1076213 :         *out_length = state->out_length;
     224     1076213 :         *out_flags = state->out_flags;
     225     1076213 :         tevent_req_received(req);
     226     1076213 :         return NT_STATUS_OK;
     227             : }
     228             : 
     229           7 : NTSTATUS dcerpc_binding_handle_raw_call(struct dcerpc_binding_handle *h,
     230             :                                         const struct GUID *object,
     231             :                                         uint32_t opnum,
     232             :                                         uint32_t in_flags,
     233             :                                         const uint8_t *in_data,
     234             :                                         size_t in_length,
     235             :                                         TALLOC_CTX *mem_ctx,
     236             :                                         uint8_t **out_data,
     237             :                                         size_t *out_length,
     238             :                                         uint32_t *out_flags)
     239             : {
     240           7 :         TALLOC_CTX *frame = talloc_stackframe();
     241           0 :         struct tevent_context *ev;
     242           0 :         struct tevent_req *subreq;
     243           7 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     244             : 
     245             :         /*
     246             :          * TODO: allow only one sync call
     247             :          */
     248             : 
     249           7 :         if (h->sync_ev) {
     250           7 :                 ev = h->sync_ev;
     251             :         } else {
     252           0 :                 ev = samba_tevent_context_init(frame);
     253             :         }
     254           7 :         if (ev == NULL) {
     255           0 :                 goto fail;
     256             :         }
     257             : 
     258           7 :         subreq = dcerpc_binding_handle_raw_call_send(frame, ev,
     259             :                                                      h, object, opnum,
     260             :                                                      in_flags,
     261             :                                                      in_data,
     262             :                                                      in_length);
     263           7 :         if (subreq == NULL) {
     264           0 :                 goto fail;
     265             :         }
     266             : 
     267           7 :         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
     268           0 :                 goto fail;
     269             :         }
     270             : 
     271           7 :         status = dcerpc_binding_handle_raw_call_recv(subreq,
     272             :                                                      mem_ctx,
     273             :                                                      out_data,
     274             :                                                      out_length,
     275             :                                                      out_flags);
     276           7 : fail:
     277           7 :         TALLOC_FREE(frame);
     278           7 :         return status;
     279             : }
     280             : 
     281             : struct dcerpc_binding_handle_disconnect_state {
     282             :         const struct dcerpc_binding_handle_ops *ops;
     283             : };
     284             : 
     285             : static void dcerpc_binding_handle_disconnect_done(struct tevent_req *subreq);
     286             : 
     287           0 : struct tevent_req *dcerpc_binding_handle_disconnect_send(TALLOC_CTX *mem_ctx,
     288             :                                                 struct tevent_context *ev,
     289             :                                                 struct dcerpc_binding_handle *h)
     290             : {
     291           0 :         struct tevent_req *req;
     292           0 :         struct dcerpc_binding_handle_disconnect_state *state;
     293           0 :         struct tevent_req *subreq;
     294             : 
     295           0 :         req = tevent_req_create(mem_ctx, &state,
     296             :                                 struct dcerpc_binding_handle_disconnect_state);
     297           0 :         if (req == NULL) {
     298           0 :                 return NULL;
     299             :         }
     300             : 
     301           0 :         state->ops = h->ops;
     302             : 
     303           0 :         subreq = state->ops->disconnect_send(state, ev, h);
     304           0 :         if (tevent_req_nomem(subreq, req)) {
     305           0 :                 return tevent_req_post(req, ev);
     306             :         }
     307           0 :         tevent_req_set_callback(subreq, dcerpc_binding_handle_disconnect_done, req);
     308             : 
     309           0 :         return req;
     310             : }
     311             : 
     312           0 : static void dcerpc_binding_handle_disconnect_done(struct tevent_req *subreq)
     313             : {
     314           0 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     315             :                                  struct tevent_req);
     316           0 :         struct dcerpc_binding_handle_disconnect_state *state =
     317           0 :                 tevent_req_data(req,
     318             :                 struct dcerpc_binding_handle_disconnect_state);
     319           0 :         NTSTATUS error;
     320             : 
     321           0 :         error = state->ops->disconnect_recv(subreq);
     322           0 :         TALLOC_FREE(subreq);
     323           0 :         if (tevent_req_nterror(req, error)) {
     324           0 :                 return;
     325             :         }
     326             : 
     327           0 :         tevent_req_done(req);
     328             : }
     329             : 
     330           0 : NTSTATUS dcerpc_binding_handle_disconnect_recv(struct tevent_req *req)
     331             : {
     332           0 :         NTSTATUS error;
     333             : 
     334           0 :         if (tevent_req_is_nterror(req, &error)) {
     335           0 :                 tevent_req_received(req);
     336           0 :                 return error;
     337             :         }
     338             : 
     339           0 :         tevent_req_received(req);
     340           0 :         return NT_STATUS_OK;
     341             : }
     342             : 
     343             : struct dcerpc_binding_handle_call_state {
     344             :         struct dcerpc_binding_handle *h;
     345             :         const struct ndr_interface_call *call;
     346             :         TALLOC_CTX *r_mem;
     347             :         void *r_ptr;
     348             :         struct ndr_push *push;
     349             :         DATA_BLOB request;
     350             :         DATA_BLOB response;
     351             :         struct ndr_pull *pull;
     352             : };
     353             : 
     354             : static void dcerpc_binding_handle_call_done(struct tevent_req *subreq);
     355             : 
     356     1084090 : struct tevent_req *dcerpc_binding_handle_call_send(TALLOC_CTX *mem_ctx,
     357             :                                         struct tevent_context *ev,
     358             :                                         struct dcerpc_binding_handle *h,
     359             :                                         const struct GUID *object,
     360             :                                         const struct ndr_interface_table *table,
     361             :                                         uint32_t opnum,
     362             :                                         TALLOC_CTX *r_mem,
     363             :                                         void *r_ptr)
     364             : {
     365       19990 :         struct tevent_req *req;
     366       19990 :         struct dcerpc_binding_handle_call_state *state;
     367       19990 :         struct tevent_req *subreq;
     368       19990 :         enum ndr_err_code ndr_err;
     369             : 
     370     1084090 :         req = tevent_req_create(mem_ctx, &state,
     371             :                                 struct dcerpc_binding_handle_call_state);
     372     1084090 :         if (req == NULL) {
     373           0 :                 return NULL;
     374             :         }
     375             : 
     376     1084090 :         if (table != h->table) {
     377           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
     378           0 :                 return tevent_req_post(req, ev);
     379             :         }
     380             : 
     381     1084090 :         if (opnum >= table->num_calls) {
     382           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     383           0 :                 return tevent_req_post(req, ev);
     384             :         }
     385             : 
     386     1084090 :         state->h = h;
     387     1084090 :         state->call = &table->calls[opnum];
     388             : 
     389     1084090 :         state->r_mem = r_mem;
     390     1084090 :         state->r_ptr = r_ptr;
     391             : 
     392             :         /* setup for a ndr_push_* call */
     393     1084090 :         state->push = ndr_push_init_ctx(state);
     394     1084090 :         if (tevent_req_nomem(state->push, req)) {
     395           0 :                 return tevent_req_post(req, ev);
     396             :         }
     397             : 
     398     1084090 :         if (h->ops->ref_alloc && h->ops->ref_alloc(h)) {
     399      810230 :                 state->push->flags |= LIBNDR_FLAG_REF_ALLOC;
     400             :         }
     401             : 
     402     1084090 :         if (h->ops->push_bigendian && h->ops->push_bigendian(h)) {
     403       29121 :                 state->push->flags |= LIBNDR_FLAG_BIGENDIAN;
     404             :         }
     405             : 
     406     1084090 :         if (h->ops->use_ndr64 && h->ops->use_ndr64(h)) {
     407           0 :                 state->push->flags |= LIBNDR_FLAG_NDR64;
     408             :         }
     409             : 
     410     1084090 :         if (h->ops->do_ndr_print) {
     411     1084090 :                 h->ops->do_ndr_print(h, NDR_IN | NDR_SET_VALUES,
     412     1084090 :                                      state->r_ptr, state->call);
     413             :         }
     414             : 
     415             :         /* push the structure into a blob */
     416     1084090 :         ndr_err = state->call->ndr_push(state->push, NDR_IN, state->r_ptr);
     417     1084090 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     418           0 :                 NTSTATUS error;
     419          90 :                 error = ndr_map_error2ntstatus(ndr_err);
     420          90 :                 if (h->ops->ndr_push_failed) {
     421          90 :                         h->ops->ndr_push_failed(h, error,
     422          90 :                                                 state->r_ptr,
     423          90 :                                                 state->call);
     424             :                 }
     425          90 :                 tevent_req_nterror(req, error);
     426          90 :                 return tevent_req_post(req, ev);
     427             :         }
     428             : 
     429             :         /* retrieve the blob */
     430     1084000 :         state->request = ndr_push_blob(state->push);
     431             : 
     432     1084000 :         if (h->ops->ndr_validate_in) {
     433        7005 :                 NTSTATUS error;
     434      297608 :                 error = h->ops->ndr_validate_in(h, state,
     435      297608 :                                                 &state->request,
     436      297608 :                                                 state->call);
     437      297608 :                 if (!NT_STATUS_IS_OK(error)) {
     438           0 :                         tevent_req_nterror(req, error);
     439           0 :                         return tevent_req_post(req, ev);
     440             :                 }
     441             :         }
     442             : 
     443     1103990 :         subreq = dcerpc_binding_handle_raw_call_send(state, ev,
     444             :                                                      h, object, opnum,
     445     1084000 :                                                      state->push->flags,
     446     1084000 :                                                      state->request.data,
     447     1084000 :                                                      state->request.length);
     448     1084000 :         if (tevent_req_nomem(subreq, req)) {
     449           0 :                 return tevent_req_post(req, ev);
     450             :         }
     451     1084000 :         tevent_req_set_callback(subreq, dcerpc_binding_handle_call_done, req);
     452             : 
     453     1084000 :         return req;
     454             : }
     455             : 
     456     1079250 : static void dcerpc_binding_handle_call_done(struct tevent_req *subreq)
     457             : {
     458     1079250 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     459             :                                  struct tevent_req);
     460       19990 :         struct dcerpc_binding_handle_call_state *state =
     461     1079250 :                 tevent_req_data(req,
     462             :                 struct dcerpc_binding_handle_call_state);
     463     1079250 :         struct dcerpc_binding_handle *h = state->h;
     464       19990 :         NTSTATUS error;
     465     1079250 :         uint32_t out_flags = 0;
     466       19990 :         enum ndr_err_code ndr_err;
     467             : 
     468     1079250 :         error = dcerpc_binding_handle_raw_call_recv(subreq, state,
     469             :                                                     &state->response.data,
     470             :                                                     &state->response.length,
     471             :                                                     &out_flags);
     472     1079250 :         TALLOC_FREE(subreq);
     473     1079250 :         if (tevent_req_nterror(req, error)) {
     474        3044 :                 return;
     475             :         }
     476             : 
     477     1076206 :         state->pull = ndr_pull_init_blob(&state->response, state);
     478     1076206 :         if (tevent_req_nomem(state->pull, req)) {
     479           0 :                 return;
     480             :         }
     481     1076206 :         state->pull->flags = state->push->flags;
     482             : 
     483     1076206 :         if (out_flags & LIBNDR_FLAG_BIGENDIAN) {
     484           0 :                 state->pull->flags |= LIBNDR_FLAG_BIGENDIAN;
     485             :         } else {
     486     1076206 :                 state->pull->flags &= ~LIBNDR_FLAG_BIGENDIAN;
     487             :         }
     488             : 
     489     1076206 :         state->pull->current_mem_ctx = state->r_mem;
     490             : 
     491             :         /* pull the structure from the blob */
     492     1076206 :         ndr_err = state->call->ndr_pull(state->pull, NDR_OUT, state->r_ptr);
     493     1076206 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     494           0 :                 error = ndr_map_error2ntstatus(ndr_err);
     495           0 :                 if (h->ops->ndr_pull_failed) {
     496           0 :                         h->ops->ndr_pull_failed(h, error,
     497           0 :                                                 &state->response,
     498             :                                                 state->call);
     499             :                 }
     500           0 :                 tevent_req_nterror(req, error);
     501           0 :                 return;
     502             :         }
     503             : 
     504     1076206 :         if (h->ops->do_ndr_print) {
     505     1076206 :                 h->ops->do_ndr_print(h, NDR_OUT,
     506     1076206 :                                      state->r_ptr, state->call);
     507             :         }
     508             : 
     509     1076206 :         if (h->ops->ndr_validate_out) {
     510      295010 :                 error = h->ops->ndr_validate_out(h,
     511             :                                                  state->pull,
     512      295010 :                                                  state->r_ptr,
     513             :                                                  state->call);
     514      295010 :                 if (!NT_STATUS_IS_OK(error)) {
     515           0 :                         tevent_req_nterror(req, error);
     516           0 :                         return;
     517             :                 }
     518             :         }
     519             : 
     520     1076206 :         tevent_req_done(req);
     521             : }
     522             : 
     523     1079340 : NTSTATUS dcerpc_binding_handle_call_recv(struct tevent_req *req)
     524             : {
     525     1079340 :         return tevent_req_simple_recv_ntstatus(req);
     526             : }
     527             : 
     528      828537 : NTSTATUS dcerpc_binding_handle_call(struct dcerpc_binding_handle *h,
     529             :                                     const struct GUID *object,
     530             :                                     const struct ndr_interface_table *table,
     531             :                                     uint32_t opnum,
     532             :                                     TALLOC_CTX *r_mem,
     533             :                                     void *r_ptr)
     534             : {
     535      828537 :         TALLOC_CTX *frame = talloc_stackframe();
     536        6550 :         struct tevent_context *ev;
     537        6550 :         struct tevent_req *subreq;
     538      828537 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     539             : 
     540             :         /*
     541             :          * TODO: allow only one sync call
     542             :          */
     543             : 
     544      828537 :         if (h->sync_ev) {
     545      273549 :                 ev = h->sync_ev;
     546             :         } else {
     547      548438 :                 ev = samba_tevent_context_init(frame);
     548             :         }
     549      828537 :         if (ev == NULL) {
     550           0 :                 goto fail;
     551             :         }
     552             : 
     553      828537 :         subreq = dcerpc_binding_handle_call_send(frame, ev,
     554             :                                                  h, object, table,
     555             :                                                  opnum, r_mem, r_ptr);
     556      828537 :         if (subreq == NULL) {
     557           0 :                 goto fail;
     558             :         }
     559             : 
     560      828537 :         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
     561           0 :                 goto fail;
     562             :         }
     563             : 
     564      828537 :         status = dcerpc_binding_handle_call_recv(subreq);
     565      828537 : fail:
     566      828537 :         TALLOC_FREE(frame);
     567      828537 :         return status;
     568             : }

Generated by: LCOV version 1.14