STEP01: librpc/rpc/dcerpc_connection.c
authorStefan Metzmacher <metze@samba.org>
Mon, 13 Jan 2014 09:07:16 +0000 (10:07 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 10:45:39 +0000 (12:45 +0200)
librpc/rpc/dcerpc_connection.c

index 4819c887991d4efaa6c786a3071631e1267ed90c..fc4fc5c085384528c9ba50be55524bd5f5a31c20 100644 (file)
@@ -67,6 +67,7 @@ struct dcerpc_connection {
                struct tevent_queue *out_queue;
                struct dcerpc_call *list;
                struct dcerpc_call *active;
+               struct dcerpc_call *new_call;
        } calls;
 
        struct {
@@ -806,12 +807,27 @@ static void dcerpc_connection_loop(struct tevent_req *subreq)
                return;
        }
 
+       if (conn->calls.active != NULL) {
+               if (pkt->call_id != conn->calls.active->call_id) {
+                       TALLOC_FREE(subreq);
+                       // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
+                       return;
+               }
+               call = conn->calls.active;
+       } else {
+               call = conn->calls.list;
+       }
+
        for (call = conn->calls.list; call; call = call->next) {
                if (call->call_id == pkt->call_id) {
                        break;
                }
        }
 
+       if (call == NULL) {
+               call = conn->calls.new_call;
+       }
+
        if (call == NULL) {
                TALLOC_FREE(subreq);
                // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
@@ -831,6 +847,11 @@ static void dcerpc_connection_loop(struct tevent_req *subreq)
                return;
        }
 
+       if (conn->calls.new_call == NULL) {
+               conn->loop.ev = NULL;
+               return;
+       }
+
        error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
        if (!NT_STATUS_IS_OK(error)) {
                // disconnect and notify pending calls
@@ -908,6 +929,7 @@ struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
        DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
 
        tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
+       tevent_req_defer_callback(req, ev);
 
        if (state->sec != NULL && state->sec->gensec != NULL) {
                subreq = gensec_update_send(state, ev,
@@ -1370,8 +1392,6 @@ static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
        NTSTATUS status;
        size_t i;
 
-       DLIST_REMOVE(state->conn->calls.list, state->call);
-
        /* Ensure we have the correct type. */
        switch (pkt->ptype) {
        case DCERPC_PKT_BIND_ACK:
@@ -1669,6 +1689,7 @@ struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
        DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
 
        tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
+       tevent_req_defer_callback(req, ev);
 
        ok = tevent_queue_add(state->conn->calls.out_queue,
                              state->ev,