Correctly calculate the offset for read&x
authorVolker Lendecke <vl@samba.org>
Fri, 21 Nov 2008 22:17:31 +0000 (23:17 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 16 Jan 2009 12:00:44 +0000 (13:00 +0100)
source3/include/proto.h
source3/smbd/pipes.c
source3/smbd/process.c
source3/smbd/reply.c

index 5d82ef090d6ef2205517a94a8080a36d65b5bd4f..d644b09a6acaed5965c14ecbceccf8ea60213a6b 100644 (file)
@@ -7120,6 +7120,7 @@ const char *smb_fn_name(int type);
 void add_to_common_flags2(uint32 v);
 void remove_from_common_flags2(uint32 v);
 void construct_reply_common_req(struct smb_request *req, char *outbuf);
+size_t req_wct_ofs(struct smb_request *req);
 void chain_reply(struct smb_request *req);
 void check_reload(time_t t);
 void smbd_process(void);
index faabdd795bf820ca954c8a232431dacd4a647064..4841882cc37e297765a88b028efff9572a0f3793 100644 (file)
@@ -278,8 +278,12 @@ void reply_pipe_read_and_X(struct smb_request *req)
        srv_set_message((char *)req->outbuf, 12, nread, False);
   
        SSVAL(req->outbuf,smb_vwv5,nread);
-       SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf));
-       SSVAL(smb_buf(req->outbuf),-2,nread);
+       SSVAL(req->outbuf,smb_vwv6,
+             req_wct_ofs(req)
+             + 1               /* the wct field */
+             + 12 * sizeof(uint16_t) /* vwv */
+             + 2);             /* the buflen field */
+       SSVAL(req->outbuf,smb_vwv11,smb_maxcnt);
   
        DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n",
                 fsp->fnum, smb_mincnt, smb_maxcnt, (int)nread));
index 3547bfcc3a78487e01f090448acbacb16e32b2d6..1701cd33da68b658943c97a85da192c6d93c7ddc 100644 (file)
@@ -1822,6 +1822,25 @@ void chain_reply(struct smb_request *req)
 
 #else
 
+/*
+ * How many bytes have we already accumulated up to the current wct field
+ * offset?
+ */
+
+size_t req_wct_ofs(struct smb_request *req)
+{
+       size_t buf_size;
+
+       if (req->chain_outbuf == NULL) {
+               return smb_wct - 4;
+       }
+       buf_size = talloc_get_size(req->chain_outbuf);
+       if ((buf_size % 4) != 0) {
+               buf_size += (4 - (buf_size % 4));
+       }
+       return buf_size - 4;
+}
+
 /*
  * Hack around reply_nterror & friends not being aware of chained requests,
  * generating illegal (i.e. wct==0) chain replies.
index d7704965f8c98a331195e363c8b37916e28363e9..28836144c20c2e0a86e943b27deeceaa968498e2 100644 (file)
@@ -3169,7 +3169,8 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
  Setup readX header.
 ****************************************************************************/
 
-static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
+static int setup_readX_header(struct smb_request *req, char *outbuf,
+                             size_t smb_maxcnt)
 {
        int outsize;
        char *data;
@@ -3182,9 +3183,13 @@ static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
        SCVAL(outbuf,smb_vwv0,0xFF);
        SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
        SSVAL(outbuf,smb_vwv5,smb_maxcnt);
-       SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+       SSVAL(outbuf,smb_vwv6,
+             req_wct_ofs(req)
+             + 1               /* the wct field */
+             + 12 * sizeof(uint16_t) /* vwv */
+             + 2);             /* the buflen field */
        SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
-       SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
+       SSVAL(outbuf,smb_vwv11,smb_maxcnt);
        /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
        _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
        return outsize;
@@ -3238,7 +3243,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                header = data_blob_const(headerbuf, sizeof(headerbuf));
 
                construct_reply_common_req(req, (char *)headerbuf);
-               setup_readX_header((char *)headerbuf, smb_maxcnt);
+               setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
 
                if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
                        /* Returning ENOSYS means no data at all was sent.
@@ -3296,7 +3301,7 @@ normal_read:
                uint8 headerbuf[smb_size + 2*12];
 
                construct_reply_common_req(req, (char *)headerbuf);
-               setup_readX_header((char *)headerbuf, smb_maxcnt);
+               setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
 
                /* Send out the header. */
                if (write_data(smbd_server_fd(), (char *)headerbuf,
@@ -3323,7 +3328,7 @@ normal_read:
                return;
        }
 
-       setup_readX_header((char *)req->outbuf, nread);
+       setup_readX_header(req, (char *)req->outbuf, nread);
 
        DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
                    fsp->fnum, (int)smb_maxcnt, (int)nread ) );