Based on metze's fix for Bug 8407 - SMB2 server can return requests out-of-order...
authorJeremy Allison <jra@samba.org>
Fri, 26 Aug 2011 21:23:26 +0000 (14:23 -0700)
committerJeremy Allison <jra@samba.org>
Wed, 31 Aug 2011 17:49:31 +0000 (19:49 +0200)
source3/smbd/globals.h
source3/smbd/smb2_server.c

index 0baf159dd9a0b00f2c972659653cb9377de92024..35c44eebb573104fcddc2c1c8b18ca5e63d4446d 100644 (file)
@@ -606,6 +606,7 @@ struct smbd_server_connection {
                uint32_t credits_granted;
                uint32_t max_credits;
                struct bitmap *credits_bitmap;
+               bool compound_related_in_progress;
        } smb2;
 };
 
index 0310cb1baa039bf7acf0f6a91f67ec6767d9d421..d29b055b29612638e4c0d1794d2fc00496b9e925 100644 (file)
@@ -886,6 +886,20 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
+
+               /*
+                * We're splitting off the last SMB2
+                * request in a compound set, and the
+                * smb2_send_async_interim_response()
+                * call above just sent all the replies
+                * for the previous SMB2 requests in
+                * this compound set. So we're no longer
+                * in the "compound_related_in_progress"
+                * state, and this is no longer a compound
+                * request.
+                */
+               req->compound_related = false;
+               req->sconn->smb2.compound_related_in_progress = false;
        }
 
        /* Don't return an intermediate packet on a pipe read/write. */
@@ -1305,6 +1319,10 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                req->compat_chain_fsp = NULL;
        }
 
+       if (req->compound_related) {
+               req->sconn->smb2.compound_related_in_progress = true;
+       }
+
        switch (opcode) {
        case SMB2_OP_NEGPROT:
                /* This call needs to be run as root */
@@ -1751,6 +1769,10 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
                return NT_STATUS_OK;
        }
 
+       if (req->compound_related) {
+               req->sconn->smb2.compound_related_in_progress = false;
+       }
+
        smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
 
        /* Set credit for this operation (zero credits if this
@@ -1801,6 +1823,8 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
        return NT_STATUS_OK;
 }
 
+static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
+
 void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
                                        struct tevent_immediate *im,
                                        void *private_data)
@@ -1823,9 +1847,13 @@ void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
                smbd_server_connection_terminate(sconn, nt_errstr(status));
                return;
        }
-}
 
-static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
+       status = smbd_smb2_request_next_incoming(sconn);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(sconn, nt_errstr(status));
+               return;
+       }
+}
 
 static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
 {
@@ -2464,6 +2492,14 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s
        size_t cur_send_queue_len;
        struct tevent_req *subreq;
 
+       if (sconn->smb2.compound_related_in_progress) {
+               /*
+                * Can't read another until the related
+                * compound is done.
+                */
+               return NT_STATUS_OK;
+       }
+
        if (tevent_queue_length(sconn->smb2.recv_queue) > 0) {
                /*
                 * if there is already a smbd_smb2_request_read