summaryrefslogtreecommitdiff
path: root/source3/libsmb/clitrans.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-06-08 00:44:34 +0200
committerJeremy Allison <jra@samba.org>2011-06-10 19:27:05 +0200
commit0a8fd50bd806e925a915c74cb86733481b2144f6 (patch)
treee26ea27a5d20291bfbbefadfa4b2d746f2d7b381 /source3/libsmb/clitrans.c
parent6f7af1b0388d30c8a06c495713066b90ded00780 (diff)
downloadsamba-0a8fd50bd806e925a915c74cb86733481b2144f6.tar.gz
samba-0a8fd50bd806e925a915c74cb86733481b2144f6.tar.bz2
samba-0a8fd50bd806e925a915c74cb86733481b2144f6.zip
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
Diffstat (limited to 'source3/libsmb/clitrans.c')
-rw-r--r--source3/libsmb/clitrans.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index d8cd8e8cbd..cf6809b4c0 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -52,8 +52,9 @@ struct cli_trans_state {
struct trans_recvblob rdata;
uint16_t recv_flags2;
- struct iovec iov[4];
+ struct iovec iov[6];
uint8_t pad[4];
+ uint8_t zero_pad[4];
uint16_t vwv[32];
};
@@ -173,7 +174,10 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
uint16_t *vwv = state->vwv;
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;
@@ -221,7 +225,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,
@@ -231,27 +246,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:
@@ -268,7 +297,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,
@@ -282,7 +311,7 @@ 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);
@@ -298,7 +327,7 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
SIVAL(vwv + 9, 1, this_param);
SIVAL(vwv +11, 1, param_offset);
SIVAL(vwv +13, 1, this_data);
- SIVAL(vwv +15, 1, param_offset + this_param);
+ SIVAL(vwv +15, 1, data_offset);
SCVAL(vwv +17, 1, state->num_setup);
SSVAL(vwv +18, 0, state->function);
memcpy(vwv + 19, state->setup,
@@ -313,7 +342,7 @@ static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
SIVAL(vwv + 7, 1, param_offset);
SIVAL(vwv + 9, 1, state->param_sent);
SIVAL(vwv +11, 1, this_data);
- SIVAL(vwv +13, 1, param_offset + this_param);
+ SIVAL(vwv +13, 1, data_offset);
SIVAL(vwv +15, 1, state->data_sent);
SCVAL(vwv +17, 1, 0); /* reserved */
break;