diff options
author | Stefan Metzmacher <metze@samba.org> | 2011-06-08 00:44:34 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2011-06-10 19:27:05 +0200 |
commit | 0a8fd50bd806e925a915c74cb86733481b2144f6 (patch) | |
tree | e26ea27a5d20291bfbbefadfa4b2d746f2d7b381 /source3 | |
parent | 6f7af1b0388d30c8a06c495713066b90ded00780 (diff) | |
download | samba-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')
-rw-r--r-- | source3/libsmb/clitrans.c | 53 |
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; |