summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2008-11-21 23:17:31 +0100
committerVolker Lendecke <vl@samba.org>2009-01-16 13:00:44 +0100
commitddaa65ef6e049a185281c4d5deca4045e3b085e2 (patch)
treef44b5ea5130fb4de174fa505957d748767be40ce
parentba981128ac0ba5b6b6f865d72a26509fb52a4a3e (diff)
downloadsamba-ddaa65ef6e049a185281c4d5deca4045e3b085e2.tar.gz
samba-ddaa65ef6e049a185281c4d5deca4045e3b085e2.tar.bz2
samba-ddaa65ef6e049a185281c4d5deca4045e3b085e2.zip
Correctly calculate the offset for read&x
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/smbd/pipes.c8
-rw-r--r--source3/smbd/process.c19
-rw-r--r--source3/smbd/reply.c17
4 files changed, 37 insertions, 8 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 5d82ef090d..d644b09a6a 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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);
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index faabdd795b..4841882cc3 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -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));
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 3547bfcc3a..1701cd33da 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1823,6 +1823,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.
*/
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index d7704965f8..28836144c2 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -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 ) );