diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/async_smb.c | 177 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 4 | ||||
-rw-r--r-- | source3/libsmb/clireadwrite.c | 469 | ||||
-rw-r--r-- | source3/libsmb/clitrans.c | 6 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 8 |
7 files changed, 575 insertions, 93 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index fd2fe930f8..82a919455a 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -127,7 +127,7 @@ static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) static int cli_request_destructor(struct cli_request *req) { if (req->enc_state != NULL) { - common_free_enc_buffer(req->enc_state, req->outbuf); + common_free_enc_buffer(req->enc_state, (char *)req->outbuf); } DLIST_REMOVE(req->cli->outstanding_requests, req); if (req->cli->outstanding_requests == NULL) { @@ -187,7 +187,7 @@ static bool is_andx_req(uint8_t cmd) * to the chain. Find the offset to the place where we have to put our cmd. */ -static bool find_andx_cmd_ofs(char *buf, size_t *pofs) +static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs) { uint8_t cmd; size_t ofs; @@ -231,12 +231,12 @@ static bool find_andx_cmd_ofs(char *buf, size_t *pofs) * *poutbuf. */ -bool smb_splice_chain(char **poutbuf, uint8_t smb_command, +bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command, uint8_t wct, const uint16_t *vwv, size_t bytes_alignment, - uint16_t num_bytes, const uint8_t *bytes) + uint32_t num_bytes, const uint8_t *bytes) { - char *outbuf; + uint8_t *outbuf; size_t old_size, new_size; size_t ofs; size_t chain_padding = 0; @@ -269,18 +269,18 @@ bool smb_splice_chain(char **poutbuf, uint8_t smb_command, new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2; if ((bytes_alignment != 0) && ((new_size % bytes_alignment) != 0)) { - bytes_padding = bytes_alignment + (new_size % bytes_alignment); + bytes_padding = bytes_alignment - (new_size % bytes_alignment); } new_size += bytes_padding + num_bytes; - if (new_size > 0xffff) { + if ((smb_command != SMBwriteX) && (new_size > 0xffff)) { DEBUG(1, ("splice_chain: %u bytes won't fit\n", (unsigned)new_size)); return false; } - outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, char, new_size); + outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, uint8_t, new_size); if (outbuf == NULL) { DEBUG(0, ("talloc failed\n")); return false; @@ -295,7 +295,7 @@ bool smb_splice_chain(char **poutbuf, uint8_t smb_command, if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) { DEBUG(1, ("invalid command chain\n")); *poutbuf = TALLOC_REALLOC_ARRAY( - NULL, *poutbuf, char, old_size); + NULL, *poutbuf, uint8_t, old_size); return false; } @@ -310,20 +310,42 @@ bool smb_splice_chain(char **poutbuf, uint8_t smb_command, ofs = old_size; + /* + * Push the chained request: + * + * wct field + */ + SCVAL(outbuf, ofs, wct); ofs += 1; + /* + * vwv array + */ + memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct); ofs += sizeof(uint16_t) * wct; + /* + * bcc (byte count) + */ + SSVAL(outbuf, ofs, num_bytes + bytes_padding); ofs += sizeof(uint16_t); + /* + * padding + */ + if (bytes_padding != 0) { memset(outbuf + ofs, 0, bytes_padding); ofs += bytes_padding; } + /* + * The bytes field + */ + memcpy(outbuf + ofs, bytes, num_bytes); return true; @@ -379,6 +401,7 @@ static int cli_async_req_destructor(struct async_req *req) * @param[in] additional_flags open_and_x wants to add oplock header flags * @param[in] wct How many words? * @param[in] vwv The words, already in network order + * @param[in] bytes_alignment How shall we align "bytes"? * @param[in] num_bytes How many bytes? * @param[in] bytes The data the request ships * @@ -394,7 +417,8 @@ static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx, uint8_t smb_command, uint8_t additional_flags, uint8_t wct, const uint16_t *vwv, - uint16_t num_bytes, + size_t bytes_alignment, + uint32_t num_bytes, const uint8_t *bytes) { struct async_req **tmp_reqs; @@ -423,7 +447,7 @@ static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx, cli_async_req_destructor); if (!smb_splice_chain(&req->outbuf, smb_command, wct, vwv, - 0, num_bytes, bytes)) { + bytes_alignment, num_bytes, bytes)) { goto fail; } @@ -489,11 +513,12 @@ bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, if (size_hint == 0) { size_hint = 100; } - req->outbuf = talloc_array(req, char, smb_wct + size_hint); + req->outbuf = talloc_array(req, uint8_t, smb_wct + size_hint); if (req->outbuf == NULL) { goto fail; } - req->outbuf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, char, smb_wct); + req->outbuf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, uint8_t, + smb_wct); req->num_async = 0; req->async = NULL; @@ -502,7 +527,7 @@ bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, req->recv_helper.fn = NULL; SSVAL(req->outbuf, smb_tid, cli->cnum); - cli_setup_packet_buf(cli, req->outbuf); + cli_setup_packet_buf(cli, (char *)req->outbuf); req->mid = cli_new_mid(cli); @@ -527,6 +552,7 @@ bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, void cli_chain_uncork(struct cli_state *cli) { struct cli_request *req = cli->chain_accumulator; + size_t smblen; SMB_ASSERT(req != NULL); @@ -536,22 +562,35 @@ void cli_chain_uncork(struct cli_state *cli) cli->chain_accumulator = NULL; SSVAL(req->outbuf, smb_mid, req->mid); - smb_setlen(req->outbuf, talloc_get_size(req->outbuf) - 4); - cli_calculate_sign_mac(cli, req->outbuf); + smblen = talloc_get_size(req->outbuf) - 4; + + smb_setlen((char *)req->outbuf, smblen); + + if (smblen > 0x1ffff) { + /* + * This is a POSIX 14 word large write. Overwrite just the + * size field, the '0xFFSMB' has been set by smb_setlen which + * _smb_setlen_large does not do. + */ + _smb_setlen_large(((char *)req->outbuf), smblen); + } + + cli_calculate_sign_mac(cli, (char *)req->outbuf); if (cli_encryption_on(cli)) { NTSTATUS status; char *enc_buf; - status = cli_encrypt_message(cli, req->outbuf, &enc_buf); + status = cli_encrypt_message(cli, (char *)req->outbuf, + &enc_buf); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error in encrypting client message. " "Error %s\n", nt_errstr(status))); TALLOC_FREE(req); return; } - req->outbuf = enc_buf; + req->outbuf = (uint8_t *)enc_buf; req->enc_state = cli->trans_enc_state; } @@ -569,6 +608,7 @@ void cli_chain_uncork(struct cli_state *cli) * @param[in] additional_flags open_and_x wants to add oplock header flags * @param[in] wct How many words? * @param[in] vwv The words, already in network order + * @param[in] bytes_alignment How shall we align "bytes"? * @param[in] num_bytes How many bytes? * @param[in] bytes The data the request ships * @@ -581,7 +621,8 @@ struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, uint8_t smb_command, uint8_t additional_flags, uint8_t wct, const uint16_t *vwv, - uint16_t num_bytes, const uint8_t *bytes) + size_t bytes_alignment, + uint32_t num_bytes, const uint8_t *bytes) { struct async_req *result; bool uncork = false; @@ -596,7 +637,7 @@ struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, } result = cli_request_chain(mem_ctx, ev, cli, smb_command, - additional_flags, wct, vwv, + additional_flags, wct, vwv, bytes_alignment, num_bytes, bytes); if (result == NULL) { @@ -611,6 +652,37 @@ struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, } /** + * Calculate the current ofs to wct for requests like write&x + * @param[in] req The smb request we're currently building + * @retval how many bytes offset have we accumulated? + */ + +uint16_t cli_wct_ofs(const struct cli_state *cli) +{ + size_t buf_size; + + if (cli->chain_accumulator == NULL) { + return smb_wct - 4; + } + + buf_size = talloc_get_size(cli->chain_accumulator->outbuf); + + if (buf_size == smb_wct) { + return smb_wct - 4; + } + + /* + * Add alignment for subsequent requests + */ + + if ((buf_size % 4) != 0) { + buf_size += (4 - (buf_size % 4)); + } + + return buf_size - 4; +} + +/** * Figure out if there is an andx command behind the current one * @param[in] buf The smb buffer to look at * @param[in] ofs The offset to the wct field that is followed by the cmd @@ -955,6 +1027,39 @@ static void cli_state_handler(struct event_context *event_ctx, DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); + if (flags & EVENT_FD_WRITE) { + size_t to_send; + ssize_t sent; + + for (req = cli->outstanding_requests; req; req = req->next) { + to_send = smb_len(req->outbuf)+4; + if (to_send > req->sent) { + break; + } + } + + if (req == NULL) { + if (cli->fd_event != NULL) { + event_fd_set_not_writeable(cli->fd_event); + } + return; + } + + sent = sys_send(cli->fd, req->outbuf + req->sent, + to_send - req->sent, 0); + + if (sent < 0) { + status = map_nt_error_from_unix(errno); + goto sock_error; + } + + req->sent += sent; + + if (req->sent == to_send) { + return; + } + } + if (flags & EVENT_FD_READ) { int res, available; size_t old_size, new_size; @@ -1020,38 +1125,6 @@ static void cli_state_handler(struct event_context *event_ctx, } } - if (flags & EVENT_FD_WRITE) { - size_t to_send; - ssize_t sent; - - for (req = cli->outstanding_requests; req; req = req->next) { - to_send = smb_len(req->outbuf)+4; - if (to_send > req->sent) { - break; - } - } - - if (req == NULL) { - if (cli->fd_event != NULL) { - event_fd_set_not_writeable(cli->fd_event); - } - return; - } - - sent = sys_send(cli->fd, req->outbuf + req->sent, - to_send - req->sent, 0); - - if (sent < 0) { - status = map_nt_error_from_unix(errno); - goto sock_error; - } - - req->sent += sent; - - if (req->sent == to_send) { - return; - } - } return; sock_error: diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index b5287774f5..5892bdc859 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1269,7 +1269,7 @@ struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx, } } - result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, + result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0, talloc_get_size(bytes), bytes); TALLOC_FREE(bytes); return result; diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index d94427809c..ff01b6798f 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -705,7 +705,7 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, return NULL; } - result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv, + result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv, 0, data.length, data.data); if (result == NULL) { TALLOC_FREE(data_copy); diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 733abb6510..7c75826414 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -895,7 +895,7 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } result = cli_request_send(mem_ctx, ev, cli, SMBopenX, additional_flags, - 15, vwv, talloc_get_size(bytes), bytes); + 15, vwv, 0, talloc_get_size(bytes), bytes); TALLOC_FREE(bytes); return result; } @@ -974,7 +974,7 @@ struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev, SSVAL(vwv+0, 0, fnum); SIVALS(vwv+1, 0, -1); - return cli_request_send(mem_ctx, ev, cli, SMBclose, 0, 3, vwv, + return cli_request_send(mem_ctx, ev, cli, SMBclose, 0, 3, vwv, 0, 0, NULL); } diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1c2a0d56c4..b33d0f0938 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -36,6 +36,41 @@ static size_t cli_read_max_bufsize(struct cli_state *cli) return (cli->max_xmit - (smb_size+32)) & ~1023; } +/**************************************************************************** + Calculate the recommended write buffer size +****************************************************************************/ +static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode) +{ + if (write_mode == 0 && + !client_is_signing_on(cli) && + !cli_encryption_on(cli) && + (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && + (cli->capabilities & CAP_LARGE_FILES)) { + /* Only do massive writes if we can do them direct + * with no signing or encrypting - not on a pipe. */ + return CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE; + } + + if (cli->is_samba) { + return CLI_SAMBA_MAX_LARGE_WRITEX_SIZE; + } + + if (((cli->capabilities & CAP_LARGE_WRITEX) == 0) + || client_is_signing_on(cli) + || strequal(cli->dev, "LPT1:")) { + + /* + * Printer devices are restricted to max_xmit writesize in + * Vista and XPSP3 as are signing connections. + */ + + return (cli->max_xmit - (smb_size+32)) & ~1023; + } + + return CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; +} + + /* * Send a read&x request */ @@ -77,7 +112,7 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, wct += 2; } - result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, + result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, 0, 0, NULL); if (result == NULL) { return NULL; @@ -614,31 +649,7 @@ ssize_t cli_write(struct cli_state *cli, mpx = 1; } - /* Default (small) writesize. */ - writesize = (cli->max_xmit - (smb_size+32)) & ~1023; - - if (write_mode == 0 && - !client_is_signing_on(cli) && - !cli_encryption_on(cli) && - (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) && - (cli->capabilities & CAP_LARGE_FILES)) { - /* Only do massive writes if we can do them direct - * with no signing or encrypting - not on a pipe. */ - writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE; - } else if ((cli->capabilities & CAP_LARGE_WRITEX) && - (strcmp(cli->dev, "LPT1:") != 0)) { - - /* Printer devices are restricted to max_xmit - * writesize in Vista and XPSP3. */ - - if (cli->is_samba) { - writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE; - } else if (!client_is_signing_on(cli)) { - /* Windows restricts signed writes to max_xmit. - * Found by Volker. */ - writesize = CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; - } - } + writesize = cli_write_max_bufsize(cli, write_mode); blocks = (size + (writesize-1)) / writesize; @@ -733,3 +744,409 @@ ssize_t cli_smbwrite(struct cli_state *cli, return total; } + +/* + * Send a write&x request + */ + +struct async_req *cli_write_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, + uint16_t mode, const uint8_t *buf, + off_t offset, size_t size) +{ + bool bigoffset = ((cli->capabilities & CAP_LARGE_FILES) != 0); + uint8_t wct = bigoffset ? 14 : 12; + size_t max_write = cli_write_max_bufsize(cli, mode); + uint16_t vwv[14]; + + size = MIN(size, max_write); + + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SSVAL(vwv+2, 0, fnum); + SIVAL(vwv+3, 0, offset); + SIVAL(vwv+5, 0, 0); + SSVAL(vwv+7, 0, mode); + SSVAL(vwv+8, 0, 0); + SSVAL(vwv+9, 0, (size>>16)); + SSVAL(vwv+10, 0, size); + + SSVAL(vwv+11, 0, + cli_wct_ofs(cli) + + 1 /* the wct field */ + + wct * 2 /* vwv */ + + 2 /* num_bytes field */ + + 1 /* pad */); + + if (bigoffset) { + SIVAL(vwv+12, 0, (((uint64_t)offset)>>32) & 0xffffffff); + } + + return cli_request_send(mem_ctx, ev, cli, SMBwriteX, 0, wct, vwv, + 2, size, buf); +} + +NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten) +{ + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + size_t written; + + if (async_req_is_error(req, &status)) { + return status; + } + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + if (wct < 6) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + written = SVAL(vwv+2, 0); + written |= SVAL(vwv+4, 0)<<16; + *pwritten = written; + + return NT_STATUS_OK; +} + +struct cli_writeall_state { + struct event_context *ev; + struct cli_state *cli; + uint16_t fnum; + uint16_t mode; + const uint8_t *buf; + off_t offset; + size_t size; + size_t written; +}; + +static void cli_writeall_written(struct async_req *req); + +static struct async_req *cli_writeall_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint16_t mode, + const uint8_t *buf, + off_t offset, size_t size) +{ + struct async_req *result; + struct async_req *subreq; + struct cli_writeall_state *state; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + goto fail; + } + state = talloc(result, struct cli_writeall_state); + if (state == NULL) { + goto fail; + } + result->private_data = state; + + state->ev = ev; + state->cli = cli; + state->fnum = fnum; + state->mode = mode; + state->buf = buf; + state->offset = offset; + state->size = size; + state->written = 0; + + subreq = cli_write_andx_send(state, state->ev, state->cli, state->fnum, + state->mode, state->buf, state->offset, + state->size); + if (subreq == NULL) { + goto fail; + } + + subreq->async.fn = cli_writeall_written; + subreq->async.priv = result; + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void cli_writeall_written(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct cli_writeall_state *state = talloc_get_type_abort( + req->private_data, struct cli_writeall_state); + NTSTATUS status; + size_t written, to_write; + + status = cli_write_andx_recv(subreq, &written); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + state->written += written; + + if (state->written > state->size) { + async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + + to_write = state->size - state->written; + + if (to_write == 0) { + async_req_done(req); + return; + } + + subreq = cli_write_andx_send(state, state->ev, state->cli, state->fnum, + state->mode, + state->buf + state->written, + state->offset + state->written, to_write); + if (subreq == NULL) { + async_req_error(req, NT_STATUS_NO_MEMORY); + return; + } + + subreq->async.fn = cli_writeall_written; + subreq->async.priv = req; +} + +static NTSTATUS cli_writeall_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct cli_push_state { + struct async_req *req; + + struct event_context *ev; + struct cli_state *cli; + uint16_t fnum; + uint16_t mode; + off_t start_offset; + size_t window_size; + + size_t (*source)(uint8_t *buf, size_t n, void *priv); + void *priv; + + size_t chunk_size; + + size_t sent; + bool eof; + + /* + * Outstanding requests + */ + int num_reqs; + struct async_req **reqs; + + int pending; + + uint8_t *buf; +}; + +static void cli_push_written(struct async_req *req); + +struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, uint16_t mode, + off_t start_offset, size_t window_size, + size_t (*source)(uint8_t *buf, size_t n, + void *priv), + void *priv) +{ + struct async_req *result; + struct cli_push_state *state; + int i; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + goto failed; + } + state = talloc(result, struct cli_push_state); + if (state == NULL) { + goto failed; + } + result->private_data = state; + state->req = result; + + state->cli = cli; + state->ev = ev; + state->fnum = fnum; + state->start_offset = start_offset; + state->mode = mode; + state->source = source; + state->priv = priv; + state->eof = false; + state->sent = 0; + state->pending = 0; + + state->chunk_size = cli_write_max_bufsize(cli, mode); + + state->num_reqs = MAX(window_size/state->chunk_size, 1); + state->num_reqs = MIN(state->num_reqs, cli->max_mux); + + state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, + state->num_reqs); + if (state->reqs == NULL) { + goto failed; + } + + state->buf = TALLOC_ARRAY( + state, uint8_t, state->chunk_size * state->num_reqs); + if (state->buf == NULL) { + goto failed; + } + + for (i=0; i<state->num_reqs; i++) { + size_t to_write; + uint8_t *buf = state->buf + i*state->chunk_size; + + to_write = state->source(buf, state->chunk_size, state->priv); + if (to_write == 0) { + state->eof = true; + break; + } + + state->reqs[i] = cli_writeall_send( + state->reqs, state->ev, state->cli, state->fnum, + state->mode, buf, state->start_offset + state->sent, + to_write); + if (state->reqs[i] == NULL) { + goto failed; + } + + state->reqs[i]->async.fn = cli_push_written; + state->reqs[i]->async.priv = state; + + state->sent += to_write; + state->pending += 1; + } + + if (i == 0) { + if (!async_post_status(result, NT_STATUS_OK)) { + goto failed; + } + return result; + } + + return result; + + failed: + TALLOC_FREE(result); + return NULL; +} + +static void cli_push_written(struct async_req *req) +{ + struct cli_push_state *state = talloc_get_type_abort( + req->async.priv, struct cli_push_state); + NTSTATUS status; + int i; + uint8_t *buf; + size_t to_write; + + for (i=0; i<state->num_reqs; i++) { + if (state->reqs[i] == req) { + break; + } + } + + if (i == state->num_reqs) { + async_req_error(state->req, NT_STATUS_INTERNAL_ERROR); + return; + } + + status = cli_writeall_recv(req); + TALLOC_FREE(state->reqs[i]); + req = NULL; + if (!NT_STATUS_IS_OK(status)) { + async_req_error(state->req, status); + return; + } + + state->pending -= 1; + if (state->pending == 0) { + async_req_done(state->req); + return; + } + + if (state->eof) { + return; + } + + buf = state->buf + i * state->chunk_size; + + to_write = state->source(buf, state->chunk_size, state->priv); + if (to_write == 0) { + state->eof = true; + return; + } + + state->reqs[i] = cli_writeall_send( + state->reqs, state->ev, state->cli, state->fnum, + state->mode, buf, state->start_offset + state->sent, to_write); + if (state->reqs[i] == NULL) { + async_req_error(state->req, NT_STATUS_NO_MEMORY); + return; + } + + state->reqs[i]->async.fn = cli_push_written; + state->reqs[i]->async.priv = state; + + state->sent += to_write; + state->pending += 1; +} + +NTSTATUS cli_push_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, + off_t start_offset, size_t window_size, + size_t (*source)(uint8_t *buf, size_t n, void *priv), + void *priv) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS result = NT_STATUS_NO_MEMORY; + + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + return NT_STATUS_INVALID_PARAMETER; + } + + ev = event_context_init(frame); + if (ev == NULL) { + goto nomem; + } + + req = cli_push_send(frame, ev, cli, fnum, mode, start_offset, + window_size, source, priv); + if (req == NULL) { + goto nomem; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + result = cli_push_recv(req); + nomem: + TALLOC_FREE(frame); + return result; +} diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 120b6c0e29..baa73aeb14 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -918,7 +918,7 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, * Primary request, retrieve our mid */ result = cli_request_send(mem_ctx, state->ev, state->cli, - cmd, 0, wct, vwv, + cmd, 0, wct, vwv, 0, talloc_get_size(bytes), bytes); if (result == NULL) { goto fail; @@ -936,8 +936,8 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, wct * sizeof(uint16_t) + num_bytes + 3)) { goto fail; } - result = cli_request_send(mem_ctx, state->ev, state->cli, - cmd, 0, wct, vwv, num_bytes, bytes); + result = cli_request_send(mem_ctx, state->ev, state->cli, cmd, + 0, wct, vwv, 0, num_bytes, bytes); if (result == NULL) { goto fail; } diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index bfe5e7b97b..02b13ae63e 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -21,9 +21,6 @@ #include "includes.h" -int num_good_sends = 0; -int num_good_receives = 0; - static const struct opcode_names { const char *nmb_opcode_name; int opcode; @@ -796,8 +793,6 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type) packet->fd = fd; - num_good_receives++; - DEBUG(5,("Received a packet of len %d from (%s) port %d\n", length, inet_ntoa(packet->ip), packet->port ) ); @@ -838,9 +833,6 @@ static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port) DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n", inet_ntoa(ip),port,strerror(errno))); - if (ret) - num_good_sends++; - return(ret); } |