librpc/rpc/binding_handle.c
authorStefan Metzmacher <metze@samba.org>
Sat, 21 Sep 2013 08:19:14 +0000 (10:19 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 11:14:55 +0000 (13:14 +0200)
librpc/rpc/binding_handle.c

index 78760635f85046896c9d01a74e4f192fd6598531..6e8373b6f13258ec54f3eb880a90b4b6b1d0fa56 100644 (file)
@@ -453,6 +453,7 @@ NTSTATUS dcerpc_binding_handle_disconnect_recv(struct tevent_req *req)
 }
 
 struct dcerpc_binding_handle_call_params_state {
+       struct tevent_context *ev;
        struct dcerpc_binding_handle *h;
        const struct ndr_interface_call *call;
        struct dcerpc_binding_handle_call_params *params;
@@ -470,6 +471,7 @@ struct dcerpc_binding_handle_call_params_state {
        uint32_t out_pipe_idx;
 };
 
+static void dcerpc_binding_handle_call_params_cleanup(struct tevent_req *req);
 static void dcerpc_binding_handle_call_params_in_done(struct tevent_req *subreq);
 static void dcerpc_binding_handle_call_params_next_pipe(struct tevent_req *req);
 static void dcerpc_binding_handle_call_params_done(struct tevent_req *subreq);
@@ -505,6 +507,7 @@ struct tevent_req *dcerpc_binding_handle_call_params_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
+       state->ev = ev;
        state->h = h;
        state->call = &table->calls[opnum];
        state->params = params;
@@ -519,6 +522,8 @@ struct tevent_req *dcerpc_binding_handle_call_params_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
+       tevent_req_defer_callback(req, ev);
+
        /* setup for a ndr_push_* call */
        state->push = ndr_push_init_ctx(state);
        if (tevent_req_nomem(state->push, req)) {
@@ -595,7 +600,6 @@ struct tevent_req *dcerpc_binding_handle_call_params_send(TALLOC_CTX *mem_ctx,
        }
 
        if (state->in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
-               tevent_req_defer_callback(req, ev);
                dcerpc_binding_handle_call_params_pipe_setup(req);
                if (!tevent_req_is_in_progress(req)) {
                        return tevent_req_post(req, ev);
@@ -667,6 +671,19 @@ struct tevent_req *dcerpc_binding_handle_call_params_send(TALLOC_CTX *mem_ctx,
        return req;
 }
 
+static void dcerpc_binding_handle_call_params_cleanup(struct tevent_req *req)
+{
+       struct dcerpc_binding_handle_call_params_state *state =
+               tevent_req_data(req,
+               struct dcerpc_binding_handle_call_params_state);
+
+       dcerpc_pipe_handle_connection_disconnect(state->pc);
+       state->pc = NULL;
+       state->call_pipe = NULL;
+
+       tevent_req_post(req, state->ev);
+}
+
 static void dcerpc_binding_handle_call_params_in_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -676,6 +693,7 @@ static void dcerpc_binding_handle_call_params_in_done(struct tevent_req *subreq)
        error = dcerpc_binding_handle_raw_call_in_recv(subreq);
        TALLOC_FREE(subreq);
        if (tevent_req_nterror(req, error)) {
+               dcerpc_binding_handle_call_params_cleanup(req);
                return;
        }
 
@@ -708,6 +726,7 @@ static void dcerpc_binding_handle_call_params_next_pipe(struct tevent_req *req)
                                        state->ph);
                if (!ok) {
                        tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+                       dcerpc_binding_handle_call_params_cleanup(req);
                        return;
                }
 
@@ -727,6 +746,7 @@ static void dcerpc_binding_handle_call_params_next_pipe(struct tevent_req *req)
                                        state->ph);
                if (!ok) {
                        tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+                       dcerpc_binding_handle_call_params_cleanup(req);
                        return;
                }
 
@@ -764,10 +784,8 @@ static void dcerpc_binding_handle_call_params_done(struct tevent_req *subreq)
        subreq = NULL;
        if (!NT_STATUS_IS_OK(error)) {
                TALLOC_FREE(state->subreq);
-               dcerpc_pipe_handle_connection_disconnect(state->pc);
-               state->pc = NULL;
-               state->call_pipe = NULL;
                tevent_req_nterror(req, error);
+               dcerpc_binding_handle_call_params_cleanup(req);
                return;
        }
 
@@ -781,12 +799,14 @@ static void dcerpc_binding_handle_call_params_done(struct tevent_req *subreq)
                 * this is a protocol error
                 */
                tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
+               dcerpc_binding_handle_call_params_cleanup(req);
                return;
        }
 
        if (state->pull == NULL) {
                state->pull = ndr_pull_init_blob(&state->response, state);
                if (tevent_req_nomem(state->pull, req)) {
+                       dcerpc_binding_handle_call_params_cleanup(req);
                        return;
                }
                state->pull->flags = state->push->flags;
@@ -815,6 +835,7 @@ static void dcerpc_binding_handle_call_params_done(struct tevent_req *subreq)
                                                        state->call);
                        }
                        tevent_req_nterror(req, error);
+                       dcerpc_binding_handle_call_params_cleanup(req);
                        return;
                }
        }
@@ -849,6 +870,7 @@ static void dcerpc_binding_handle_call_params_response(struct tevent_req *req)
                                                state->call);
                }
                tevent_req_nterror(req, error);
+               dcerpc_binding_handle_call_params_cleanup(req);
                return;
        }
 
@@ -864,6 +886,7 @@ static void dcerpc_binding_handle_call_params_response(struct tevent_req *req)
                                                 state->call);
                if (!NT_STATUS_IS_OK(error)) {
                        tevent_req_nterror(req, error);
+                       dcerpc_binding_handle_call_params_cleanup(req);
                        return;
                }
        }
@@ -1167,7 +1190,7 @@ static void dcerpc_binding_handle_call_params_pull_notify(struct tevent_req *req
        //      }
        //}
 
-       //ndr_err = ndr_pull_pop(call_state->pull);
+       ndr_err = ndr_pull_pop(call_state->pull);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                NTSTATUS error;
                error = ndr_map_error2ntstatus(ndr_err);