Ensure we correctly calculate reply credits over all returned
authorJeremy Allison <jra@samba.org>
Tue, 15 Nov 2011 19:27:56 +0000 (11:27 -0800)
committerJeremy Allison <jra@samba.org>
Tue, 15 Nov 2011 21:44:25 +0000 (22:44 +0100)
SMB2 replies, and do as Windows does and return the total in the
last SMB2 reply. Fixes an issue found by Christian M Ambach <christian.ambach@de.ibm.com>
(and thanks to Christian for the initial patch this was based on).

source3/smbd/smb2_server.c

index dbb0089d70a40a4e36a9cf44bda856874491ca81..851e2fd7ef4a6cce56ef248205bde9735d101b30 100644 (file)
@@ -517,13 +517,24 @@ static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
                                struct smbd_smb2_request *outreq)
 {
        int count, idx;
+       uint16_t total_credits = 0;
 
        count = outreq->out.vector_count;
 
        for (idx=1; idx < count; idx += 3) {
+               uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
                smb2_set_operation_credit(outreq->sconn,
                        &inreq->in.vector[idx],
                        &outreq->out.vector[idx]);
+               /* To match Windows, count up what we
+                  just granted. */
+               total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
+               /* Set to zero in all but the last reply. */
+               if (idx + 3 < count) {
+                       SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
+               } else {
+                       SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
+               }
        }
 }
 
@@ -1851,11 +1862,9 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 
        smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
 
-       /* Set credit for this operation (zero credits if this
+       /* Set credit for these operations (zero credits if this
           is a final reply for an async operation). */
-       smb2_set_operation_credit(req->sconn,
-                       &req->in.vector[i],
-                       &req->out.vector[i]);
+       smb2_calculate_credits(req, req);
 
        if (req->do_signing) {
                NTSTATUS status;