[SCM] Samba Shared Repository - branch v3-6-test updated

Karolin Seeger kseeger at samba.org
Fri Jun 17 12:58:34 MDT 2011


The branch, v3-6-test has been updated
       via  4a9a11c s3:libsmb/clireadwrite: calculate cli_write_max_bufsize() correct based on max_xmit
       via  0144836 s3:libsmb/clireadwrite: calculate cli_read_max_bufsize() correct based on max_xmit
       via  ed31c08 s3:libsmb/clitrans: correctly transfer the seqnum between secondary and primary requests
       via  fa1ff15 s3:libsmb/clitrans: fix handling of multi pdu [nt]trans[s][2] calls
       via  09da3b1 s3:libsmb/clitrans: use subreq2 as variable for the secondary requests
       via  036c8b7 s3:libsmb/clitrans: move MID handling to the end of cli_trans_send() and add a comment
       via  da5870b s3:libsmb/clitrans: correctly marshall [nt]trans[s][2] requests
       via  6e3eefa s3:libsmb/clitrans: marshall SMBnttrans[2] as the others
       via  0440d3c s3:libsmb/clitrans: use uint32_t for param and data variables
       via  c5434b5 s3:libsmb/clitrans: remove unused secondary_request_ctx
       via  bad85df s3:libsmb/async_smb: add helpers to get and set the seqnum for signing
       via  60932bc s3:libsmb/async_smb: don't remove pending requests if the mid is set
       via  43f383b s3:libsmb/async_smb: call cli_smb_req_unset_pending() instead of destructor directly
       via  956bbf7 s3:libsmb/async_smb: let cli_smb_recv() initialize output values for one way requests
      from  2dec07d s3:libsmb/cli_np_tstream: s/TSTREAM_CLI_NP_BUF_SIZE/TSTREAM_CLI_NP_MAX_BUF_SIZE

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 4a9a11c0398692fe103597c8694867d6b6184134
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 19:01:13 2011 +0200

    s3:libsmb/clireadwrite: calculate cli_write_max_bufsize() correct based on max_xmit
    
    This is important in order to support DCERPC over ncacn_np against NT4 servers,
    where max_xmit is just 4356.
    
    metze
    (cherry picked from commit f0ba1afe5f7dbafaf22c3028864de0f3910f675f)
    
    The last 14 patches address the generic part of bug #8195
    (rpc client code doesn't work against NT4, when we need to fragment requests).

commit 01448363c55ea890c7c6733213681cb3c4165fc3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 18:59:39 2011 +0200

    s3:libsmb/clireadwrite: calculate cli_read_max_bufsize() correct based on max_xmit
    
    This is important in order to support DCERPC over ncacn_np against NT4 servers,
    where max_xmit is just 4356.
    
    metze
    (cherry picked from commit 73128b7cc7f536f80072a19cb69527c53d9a6c2f)

commit ed31c08d2aa59ec81dbcc747cfe7f0d42f9d9e3b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 9 11:57:55 2011 +0200

    s3:libsmb/clitrans: correctly transfer the seqnum between secondary and primary requests
    
    This is needed to implement SMB signing correct.
    
    metze
    (cherry picked from commit 5d06b2197b5fd95aaf0394d1bdba957bac6c3570)

commit fa1ff15b19df1e0cf2a2616bdcb28554a8e2458b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 10:31:23 2011 +0200

    s3:libsmb/clitrans: fix handling of multi pdu [nt]trans[s][2] calls
    
    We now keep the primary request open for the whole logical request.
    The primary request is the one that gets all incoming replies.
    While secondary requests are handled as separate one-way requests.
    
    metze
    (cherry picked from commit 1dd24ac06a7472f53b06bc0aaa54cb22c8da0f78)

commit 09da3b1fa685973619c833cc14e375abf859b5c1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 16:41:11 2011 +0200

    s3:libsmb/clitrans: use subreq2 as variable for the secondary requests
    
    metze
    (cherry picked from commit 10bb088cf1e005fd047c09afcf6b5b8999d416fe)

commit 036c8b736852d002e0806f5c36b698c19b42ec98
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 16:11:00 2011 +0200

    s3:libsmb/clitrans: move MID handling to the end of cli_trans_send() and add a comment
    
    metze
    (cherry picked from commit 5146c9ba9df063d6611abe356f9262adb027b091)

commit da5870b0073ad2a8b3f1bd3957551283a5f0da33
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 00:44:34 2011 +0200

    s3:libsmb/clitrans: correctly marshall [nt]trans[s][2] requests
    
    We need to align params and data to 4 byte offsets.
    
    This also correctly recalculates the useable space after each step.
    
    metze
    (cherry picked from commit 0a8fd50bd806e925a915c74cb86733481b2144f6)

commit 6e3eefad3a265e7417ab9393fe8fc276523efd8a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 9 12:22:59 2011 +0200

    s3:libsmb/clitrans: marshall SMBnttrans[2] as the others
    
    This is just to make the code more readable
    and easier to notice how many words we're using in vwv.
    
    metze
    (cherry picked from commit 6f7af1b0388d30c8a06c495713066b90ded00780)

commit 0440d3cb3585ceb636d7945c10d1a2b269401312
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 17:08:00 2011 +0200

    s3:libsmb/clitrans: use uint32_t for param and data variables
    
    SMBnttrans uses 32-bit values there.
    
    metze
    (cherry picked from commit 428a86c92b5b35e28c7d6921f2999616cdc1bc20)

commit c5434b570d44c8292792c8c4874414bf33c25c4d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 00:37:24 2011 +0200

    s3:libsmb/clitrans: remove unused secondary_request_ctx
    
    metze
    (cherry picked from commit 2ae565b681a6307886b888ee5b576c12916eb0db)

commit bad85df320f05215d85f5f25c15a5ddda84755f3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 9 11:49:48 2011 +0200

    s3:libsmb/async_smb: add helpers to get and set the seqnum for signing
    
    This will be used for correct signing in [nt]trans[2][s] requests.
    
    metze
    (cherry picked from commit 3dd1ebd21ee99d130f6dd30326ddafe3f00a50d0)

commit 60932bc009aa1ed0a8895fc1f62a6e461765a7da
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 10:20:25 2011 +0200

    s3:libsmb/async_smb: don't remove pending requests if the mid is set
    
    If the mid was set explicitly, it means the request expects more than
    one reply, so leave it in the pending array.
    
    metze
    (cherry picked from commit a25936f1b1300a76b08a6bd435bd7ccc388279d5)

commit 43f383b60b5581f7e4e5b547ed1a67afe48f4df0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 14:14:24 2011 +0200

    s3:libsmb/async_smb: call cli_smb_req_unset_pending() instead of destructor directly
    
    metze
    (cherry picked from commit 173fc258e443d97e4ea37f2bee99c21ad15ab484)

commit 956bbf76ce5b251d7ea07a7d2ee58c90e174db1b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 8 00:40:54 2011 +0200

    s3:libsmb/async_smb: let cli_smb_recv() initialize output values for one way requests
    
    metze
    (cherry picked from commit 49cdf171a5198495aead9ace43963e805331e20b)

-----------------------------------------------------------------------

Summary of changes:
 source3/include/async_smb.h   |    2 +
 source3/libsmb/async_smb.c    |   51 +++++++++-
 source3/libsmb/clireadwrite.c |   33 +++++--
 source3/libsmb/clitrans.c     |  227 +++++++++++++++++++++++++++++++----------
 4 files changed, 246 insertions(+), 67 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/async_smb.h b/source3/include/async_smb.h
index a8852b2..1685d49 100644
--- a/source3/include/async_smb.h
+++ b/source3/include/async_smb.h
@@ -51,6 +51,8 @@ void cli_smb_req_unset_pending(struct tevent_req *req);
 bool cli_smb_req_set_pending(struct tevent_req *req);
 uint16_t cli_smb_req_mid(struct tevent_req *req);
 void cli_smb_req_set_mid(struct tevent_req *req, uint16_t mid);
+uint32_t cli_smb_req_seqnum(struct tevent_req *req);
+void cli_smb_req_set_seqnum(struct tevent_req *req, uint32_t seqnum);
 struct tevent_req *cli_smb_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 				struct cli_state *cli,
 				uint8_t smb_command, uint8_t additional_flags,
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
index 8c5627d..7b4cf01 100644
--- a/source3/libsmb/async_smb.c
+++ b/source3/libsmb/async_smb.c
@@ -239,6 +239,14 @@ void cli_smb_req_unset_pending(struct tevent_req *req)
 	int num_pending = talloc_array_length(cli->pending);
 	int i;
 
+	if (state->mid != 0) {
+		/*
+		 * This is a [nt]trans[2] request which waits
+		 * for more than one reply.
+		 */
+		return;
+	}
+
 	if (num_pending == 1) {
 		/*
 		 * The pending read_smb tevent_req is a child of
@@ -281,6 +289,13 @@ void cli_smb_req_unset_pending(struct tevent_req *req)
 
 static int cli_smb_req_destructor(struct tevent_req *req)
 {
+	struct cli_smb_state *state = tevent_req_data(
+		req, struct cli_smb_state);
+	/*
+	 * Make sure we really remove it from
+	 * the pending array on destruction.
+	 */
+	state->mid = 0;
 	cli_smb_req_unset_pending(req);
 	return 0;
 }
@@ -343,6 +358,20 @@ void cli_smb_req_set_mid(struct tevent_req *req, uint16_t mid)
 	state->mid = mid;
 }
 
+uint32_t cli_smb_req_seqnum(struct tevent_req *req)
+{
+	struct cli_smb_state *state = tevent_req_data(
+		req, struct cli_smb_state);
+	return state->seqnum;
+}
+
+void cli_smb_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
+{
+	struct cli_smb_state *state = tevent_req_data(
+		req, struct cli_smb_state);
+	state->seqnum = seqnum;
+}
+
 static size_t iov_len(const struct iovec *iov, int count)
 {
 	size_t result = 0;
@@ -716,7 +745,7 @@ static void cli_smb_received(struct tevent_req *subreq)
 	if (state->chained_requests == NULL) {
 		state->inbuf = talloc_move(state, &inbuf);
 		talloc_set_destructor(req, NULL);
-		cli_smb_req_destructor(req);
+		cli_smb_req_unset_pending(req);
 		state->chain_num = 0;
 		state->chain_length = 1;
 		tevent_req_done(req);
@@ -760,7 +789,7 @@ static void cli_smb_received(struct tevent_req *subreq)
 	while (talloc_array_length(cli->pending) > 0) {
 		req = cli->pending[0];
 		talloc_set_destructor(req, NULL);
-		cli_smb_req_destructor(req);
+		cli_smb_req_unset_pending(req);
 		tevent_req_nterror(req, status);
 	}
 }
@@ -783,6 +812,24 @@ NTSTATUS cli_smb_recv(struct tevent_req *req,
 	}
 
 	if (state->inbuf == NULL) {
+		if (min_wct != 0) {
+			return NT_STATUS_INVALID_NETWORK_RESPONSE;
+		}
+		if (pinbuf) {
+			*pinbuf = NULL;
+		}
+		if (pwct) {
+			*pwct = 0;
+		}
+		if (pvwv) {
+			*pvwv = NULL;
+		}
+		if (pnum_bytes) {
+			*pnum_bytes = 0;
+		}
+		if (pbytes) {
+			*pbytes = NULL;
+		}
 		/* This was a request without a reply */
 		return NT_STATUS_OK;
 	}
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 9900d34..b8af9e5 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -28,6 +28,11 @@
 ****************************************************************************/
 static size_t cli_read_max_bufsize(struct cli_state *cli)
 {
+	size_t data_offset = smb_size - 4;
+	size_t wct = 12;
+
+	size_t useable_space;
+
 	if (!client_is_signing_on(cli) && !cli_encryption_on(cli)
 	    && (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
 		return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
@@ -37,13 +42,21 @@ static size_t cli_read_max_bufsize(struct cli_state *cli)
 			? CLI_SAMBA_MAX_LARGE_READX_SIZE
 			: CLI_WINDOWS_MAX_LARGE_READX_SIZE;
 	}
-	return (cli->max_xmit - (smb_size+32)) & ~1023;
+
+	data_offset += wct * sizeof(uint16_t);
+	data_offset += 1; /* pad */
+
+	useable_space = cli->max_xmit - data_offset;
+
+	return useable_space;
 }
 
 /****************************************************************************
   Calculate the recommended write buffer size
 ****************************************************************************/
-static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode)
+static size_t cli_write_max_bufsize(struct cli_state *cli,
+				    uint16_t write_mode,
+				    uint8_t wct)
 {
         if (write_mode == 0 &&
 	    !client_is_signing_on(cli) &&
@@ -62,13 +75,15 @@ static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode)
 	if (((cli->capabilities & CAP_LARGE_WRITEX) == 0)
 	    || client_is_signing_on(cli)
 	    || strequal(cli->dev, "LPT1:")) {
+		size_t data_offset = smb_size - 4;
+		size_t useable_space;
 
-		/*
-		 * Printer devices are restricted to max_xmit writesize in
-		 * Vista and XPSP3 as are signing connections.
-		 */
+		data_offset += wct * sizeof(uint16_t);
+		data_offset += 1; /* pad */
+
+		useable_space = cli->max_xmit - data_offset;
 
-		return (cli->max_xmit - (smb_size+32)) & ~1023;
+		return useable_space;
 	}
 
 	return CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE;
@@ -788,7 +803,7 @@ struct tevent_req *cli_write_andx_create(TALLOC_CTX *mem_ctx,
 	struct cli_write_andx_state *state;
 	bool bigoffset = ((cli->capabilities & CAP_LARGE_FILES) != 0);
 	uint8_t wct = bigoffset ? 14 : 12;
-	size_t max_write = cli_write_max_bufsize(cli, mode);
+	size_t max_write = cli_write_max_bufsize(cli, mode, wct);
 	uint16_t *vwv;
 
 	req = tevent_req_create(mem_ctx, &state, struct cli_write_andx_state);
@@ -1144,7 +1159,7 @@ struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 	state->pending = 0;
 	state->next_offset = start_offset;
 
-	state->chunk_size = cli_write_max_bufsize(cli, mode);
+	state->chunk_size = cli_write_max_bufsize(cli, mode, 14);
 
 	if (window_size == 0) {
 		window_size = cli->max_mux * state->chunk_size;
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index 090ed11..3cdb90b 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -32,7 +32,6 @@ struct cli_trans_state {
 	struct event_context *ev;
 	uint8_t cmd;
 	uint16_t mid;
-	uint32_t seqnum;
 	const char *pipe_name;
 	uint8_t *pipe_name_conv;
 	size_t pipe_name_conv_len;
@@ -52,13 +51,29 @@ struct cli_trans_state {
 	struct trans_recvblob rdata;
 	uint16_t recv_flags2;
 
-	TALLOC_CTX *secondary_request_ctx;
-
-	struct iovec iov[4];
+	struct iovec iov[6];
 	uint8_t pad[4];
+	uint8_t zero_pad[4];
 	uint16_t vwv[32];
+
+	struct tevent_req *primary_subreq;
 };
 
+static void cli_trans_cleanup_primary(struct cli_trans_state *state)
+{
+	if (state->primary_subreq) {
+		cli_smb_req_set_mid(state->primary_subreq, 0);
+		cli_smb_req_unset_pending(state->primary_subreq);
+		TALLOC_FREE(state->primary_subreq);
+	}
+}
+
+static int cli_trans_state_destructor(struct cli_trans_state *state)
+{
+	cli_trans_cleanup_primary(state);
+	return 0;
+}
+
 static NTSTATUS cli_pull_trans(uint8_t *inbuf,
 			       uint8_t wct, uint16_t *vwv,
 			       uint16_t num_bytes, uint8_t *bytes,
@@ -173,9 +188,12 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
 	struct iovec *iov = state->iov;
 	uint8_t *pad = state->pad;
 	uint16_t *vwv = state->vwv;
-	uint16_t param_offset;
-	uint16_t this_param = 0;
-	uint16_t this_data = 0;
+	uint32_t param_offset;
+	uint32_t this_param = 0;
+	uint32_t param_pad;
+	uint32_t data_offset;
+	uint32_t this_data = 0;
+	uint32_t data_pad;
 	uint32_t useable_space;
 	uint8_t cmd;
 
@@ -223,7 +241,18 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
 		break;
 	}
 
-	useable_space = state->cli->max_xmit - smb_size - sizeof(uint16_t)*wct;
+	param_offset += wct * sizeof(uint16_t);
+	useable_space = state->cli->max_xmit - param_offset;
+
+	param_pad = param_offset % 4;
+	if (param_pad > 0) {
+		param_pad = MIN(param_pad, useable_space);
+		iov[0].iov_base = (void *)state->zero_pad;
+		iov[0].iov_len = param_pad;
+		iov += 1;
+		param_offset += param_pad;
+	}
+	useable_space = state->cli->max_xmit - param_offset;
 
 	if (state->param_sent < state->num_param) {
 		this_param = MIN(state->num_param - state->param_sent,
@@ -233,27 +262,41 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
 		iov += 1;
 	}
 
+	data_offset = param_offset + this_param;
+	useable_space = state->cli->max_xmit - data_offset;
+
+	data_pad = data_offset % 4;
+	if (data_pad > 0) {
+		data_pad = MIN(data_pad, useable_space);
+		iov[0].iov_base = (void *)state->zero_pad;
+		iov[0].iov_len = data_pad;
+		iov += 1;
+		data_offset += data_pad;
+	}
+	useable_space = state->cli->max_xmit - data_offset;
+
 	if (state->data_sent < state->num_data) {
 		this_data = MIN(state->num_data - state->data_sent,
-				useable_space - this_param);
+				useable_space);
 		iov[0].iov_base = (void *)(state->data + state->data_sent);
 		iov[0].iov_len = this_data;
 		iov += 1;
 	}
 
-	param_offset += wct * sizeof(uint16_t);
-
 	DEBUG(10, ("num_setup=%u, max_setup=%u, "
 		   "param_total=%u, this_param=%u, max_param=%u, "
 		   "data_total=%u, this_data=%u, max_data=%u, "
-		   "param_offset=%u, param_disp=%u, data_disp=%u\n",
+		   "param_offset=%u, param_pad=%u, param_disp=%u, "
+		   "data_offset=%u, data_pad=%u, data_disp=%u\n",
 		   (unsigned)state->num_setup, (unsigned)state->max_setup,
 		   (unsigned)state->num_param, (unsigned)this_param,
 		   (unsigned)state->rparam.max,
 		   (unsigned)state->num_data, (unsigned)this_data,
 		   (unsigned)state->rdata.max,
-		   (unsigned)param_offset,
-		   (unsigned)state->param_sent, (unsigned)state->data_sent));
+		   (unsigned)param_offset, (unsigned)param_pad,
+		   (unsigned)state->param_sent,
+		   (unsigned)data_offset, (unsigned)data_pad,
+		   (unsigned)state->data_sent));
 
 	switch (cmd) {
 	case SMBtrans:
@@ -270,7 +313,7 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
 		SSVAL(vwv + 9, 0, this_param);
 		SSVAL(vwv +10, 0, param_offset);
 		SSVAL(vwv +11, 0, this_data);
-		SSVAL(vwv +12, 0, param_offset + this_param);
+		SSVAL(vwv +12, 0, data_offset);
 		SCVAL(vwv +13, 0, state->num_setup);
 		SCVAL(vwv +13, 1, 0);	/* reserved */
 		memcpy(vwv + 14, state->setup,
@@ -284,40 +327,40 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
 		SSVAL(vwv + 3, 0, param_offset);
 		SSVAL(vwv + 4, 0, state->param_sent);
 		SSVAL(vwv + 5, 0, this_data);
-		SSVAL(vwv + 6, 0, param_offset + this_param);
+		SSVAL(vwv + 6, 0, data_offset);
 		SSVAL(vwv + 7, 0, state->data_sent);
 		if (cmd == SMBtranss2) {
 			SSVAL(vwv + 8, 0, state->fid);
 		}
 		break;
 	case SMBnttrans:
-		SCVAL(vwv,  0, state->max_setup);
-		SSVAL(vwv,  1, 0); /* reserved */
-		SIVAL(vwv,  3, state->num_param);
-		SIVAL(vwv,  7, state->num_data);
-		SIVAL(vwv, 11, state->rparam.max);
-		SIVAL(vwv, 15, state->rdata.max);
-		SIVAL(vwv, 19, this_param);
-		SIVAL(vwv, 23, param_offset);
-		SIVAL(vwv, 27, this_data);
-		SIVAL(vwv, 31, param_offset + this_param);
-		SCVAL(vwv, 35, state->num_setup);
-		SSVAL(vwv, 36, state->function);
+		SCVAL(vwv + 0, 0, state->max_setup);
+		SSVAL(vwv + 0, 1, 0); /* reserved */
+		SIVAL(vwv + 1, 1, state->num_param);
+		SIVAL(vwv + 3, 1, state->num_data);
+		SIVAL(vwv + 5, 1, state->rparam.max);
+		SIVAL(vwv + 7, 1, state->rdata.max);
+		SIVAL(vwv + 9, 1, this_param);
+		SIVAL(vwv +11, 1, param_offset);
+		SIVAL(vwv +13, 1, this_data);
+		SIVAL(vwv +15, 1, data_offset);
+		SCVAL(vwv +17, 1, state->num_setup);
+		SSVAL(vwv +18, 0, state->function);
 		memcpy(vwv + 19, state->setup,
 		       sizeof(uint16_t) * state->num_setup);
 		break;
 	case SMBnttranss:
-		SSVAL(vwv,  0, 0); /* reserved */
-		SCVAL(vwv,  2, 0); /* reserved */
-		SIVAL(vwv,  3, state->num_param);
-		SIVAL(vwv,  7, state->num_data);
-		SIVAL(vwv, 11, this_param);
-		SIVAL(vwv, 15, param_offset);
-		SIVAL(vwv, 19, state->param_sent);
-		SIVAL(vwv, 23, this_data);
-		SIVAL(vwv, 27, param_offset + this_param);
-		SIVAL(vwv, 31, state->data_sent);
-		SCVAL(vwv, 35, 0); /* reserved */
+		SSVAL(vwv + 0, 0, 0); /* reserved */
+		SCVAL(vwv + 1, 0, 0); /* reserved */
+		SIVAL(vwv + 1, 1, state->num_param);
+		SIVAL(vwv + 3, 1, state->num_data);
+		SIVAL(vwv + 5, 1, this_param);
+		SIVAL(vwv + 7, 1, param_offset);
+		SIVAL(vwv + 9, 1, state->param_sent);
+		SIVAL(vwv +11, 1, this_data);
+		SIVAL(vwv +13, 1, data_offset);
+		SIVAL(vwv +15, 1, state->data_sent);
+		SCVAL(vwv +17, 1, 0); /* reserved */
 		break;
 	}
 
@@ -414,17 +457,30 @@ struct tevent_req *cli_trans_send(
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
-	state->mid = cli_smb_req_mid(subreq);
 	status = cli_smb_req_send(subreq);
 	if (!NT_STATUS_IS_OK(status)) {
 		tevent_req_nterror(req, status);
 		return tevent_req_post(req, state->ev);
 	}
-	cli_state_seqnum_persistent(cli, state->mid);
 	tevent_req_set_callback(subreq, cli_trans_done, req);
+
+	/*
+	 * Now get the MID of the primary request
+	 * and mark it as persistent. This means
+	 * we will able to send and receive multiple
+	 * SMB pdus using this MID in both directions
+	 * (including correct SMB signing).
+	 */
+	state->mid = cli_smb_req_mid(subreq);
+	cli_smb_req_set_mid(subreq, state->mid);
+	state->primary_subreq = subreq;
+	talloc_set_destructor(state, cli_trans_state_destructor);
+
 	return req;
 }
 
+static void cli_trans_done2(struct tevent_req *subreq);
+
 static void cli_trans_done(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
@@ -480,25 +536,25 @@ static void cli_trans_done(struct tevent_req *subreq)
 
 	if (!sent_all) {
 		int iov_count;
-
-		TALLOC_FREE(subreq);
+		struct tevent_req *subreq2;
 
 		cli_trans_format(state, &wct, &iov_count);
 
-		subreq = cli_smb_req_create(state, state->ev, state->cli,
-					    state->cmd + 1, 0, wct, state->vwv,
-					    iov_count, state->iov);
-		if (tevent_req_nomem(subreq, req)) {
+		subreq2 = cli_smb_req_create(state, state->ev, state->cli,
+					     state->cmd + 1, 0, wct, state->vwv,
+					     iov_count, state->iov);
+		if (tevent_req_nomem(subreq2, req)) {
 			return;
 		}
-		cli_smb_req_set_mid(subreq, state->mid);
+		cli_smb_req_set_mid(subreq2, state->mid);
 
-		status = cli_smb_req_send(subreq);
+		status = cli_smb_req_send(subreq2);
 
 		if (!NT_STATUS_IS_OK(status)) {
 			goto fail;
 		}
-		tevent_req_set_callback(subreq, cli_trans_done, req);
+		tevent_req_set_callback(subreq2, cli_trans_done2, req);
+
 		return;
 	}
 
@@ -523,23 +579,80 @@ static void cli_trans_done(struct tevent_req *subreq)
 	if ((state->rparam.total == state->rparam.received)
 	    && (state->rdata.total == state->rdata.received)) {
 		state->recv_flags2 = SVAL(inbuf, smb_flg2);
-		TALLOC_FREE(subreq);
-		cli_state_seqnum_remove(state->cli, state->mid);
+		cli_trans_cleanup_primary(state);
 		tevent_req_done(req);
 		return;
 	}
 
 	TALLOC_FREE(inbuf);
 
-	if (!cli_smb_req_set_pending(subreq)) {
-		status = NT_STATUS_NO_MEMORY;
+	return;
+
+ fail:
+	cli_trans_cleanup_primary(state);
+	tevent_req_nterror(req, status);
+}
+
+static void cli_trans_done2(struct tevent_req *subreq2)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq2, struct tevent_req);
+	struct cli_trans_state *state = tevent_req_data(
+		req, struct cli_trans_state);
+	NTSTATUS status;
+	bool sent_all;
+	uint8_t wct;
+	uint32_t seqnum;
+
+	/*
+	 * First backup the seqnum of the secondary request
+	 * and attach it to the primary request.
+	 */
+	seqnum = cli_smb_req_seqnum(subreq2);
+	cli_smb_req_set_seqnum(state->primary_subreq, seqnum);
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list