diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 15 | ||||
-rw-r--r-- | source3/libsmb/clireadwrite.c | 258 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_np.c | 14 |
3 files changed, 166 insertions, 121 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index b8353d51c9..d06466def9 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2761,11 +2761,16 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, /* The following definitions come from libsmb/clireadwrite.c */ -struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, int fnum, - off_t offset, size_t size); -NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, +struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size, + struct tevent_req **psmbreq); +struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size); +NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received, uint8_t **rcvbuf); struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct event_context *ev, diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index f2f447b4c9..a59b26f961 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -70,21 +70,25 @@ static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode) return CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE; } +struct cli_read_andx_state { + size_t size; + uint16_t vwv[12]; + NTSTATUS status; + size_t received; + uint8_t *buf; +}; -/* - * Send a read&x request - */ +static void cli_read_andx_done(struct tevent_req *subreq); -struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, int fnum, - off_t offset, size_t size) +struct tevent_req *cli_read_andx_create(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size, + struct tevent_req **psmbreq) { - struct async_req *result; - struct cli_request *req; + struct tevent_req *req, *subreq; + struct cli_read_andx_state *state; bool bigoffset = False; - - uint16_t vwv[12]; uint8_t wct = 10; if (size > cli_read_max_bufsize(cli)) { @@ -94,82 +98,85 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - 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); - SSVAL(vwv + 5, 0, size); - SSVAL(vwv + 6, 0, size); - SSVAL(vwv + 7, 0, (size >> 16)); - SSVAL(vwv + 8, 0, 0); - SSVAL(vwv + 9, 0, 0); + req = tevent_req_create(mem_ctx, &state, struct cli_read_andx_state); + if (req == NULL) { + return NULL; + } + state->size = size; + + SCVAL(state->vwv + 0, 0, 0xFF); + SCVAL(state->vwv + 0, 1, 0); + SSVAL(state->vwv + 1, 0, 0); + SSVAL(state->vwv + 2, 0, fnum); + SIVAL(state->vwv + 3, 0, offset); + SSVAL(state->vwv + 5, 0, size); + SSVAL(state->vwv + 6, 0, size); + SSVAL(state->vwv + 7, 0, (size >> 16)); + SSVAL(state->vwv + 8, 0, 0); + SSVAL(state->vwv + 9, 0, 0); if ((uint64_t)offset >> 32) { - bigoffset = True; - SIVAL(vwv + 10, 0, + bigoffset = true; + SIVAL(state->vwv + 10, 0, (((uint64_t)offset)>>32) & 0xffffffff); wct += 2; } - result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, 0, - 0, NULL); - if (result == NULL) { + subreq = cli_smb_req_create(state, ev, cli, SMBreadX, 0, wct, + state->vwv, 0, NULL); + if (subreq == NULL) { + TALLOC_FREE(req); return NULL; } + tevent_req_set_callback(subreq, cli_read_andx_done, req); + *psmbreq = subreq; + return req; +} - req = talloc_get_type_abort(result->private_data, struct cli_request); - - req->data.read.ofs = offset; - req->data.read.size = size; - req->data.read.received = 0; - req->data.read.rcvbuf = NULL; +struct tevent_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, int fnum, + off_t offset, size_t size) +{ + struct tevent_req *req, *subreq; - return result; + req = cli_read_andx_create(mem_ctx, ev, cli, fnum, offset, size, + &subreq); + if ((req == NULL) || !cli_smb_req_send(subreq)) { + TALLOC_FREE(req); + return NULL; + } + return req; } -/* - * Pull the data out of a finished async read_and_x request. rcvbuf is - * talloced from the request, so better make sure that you copy it away before - * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not - * talloc_move it! - */ - -NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, - uint8_t **rcvbuf) +static void cli_read_andx_done(struct tevent_req *subreq) { - struct cli_request *cli_req = talloc_get_type_abort( - req->private_data, struct cli_request); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_read_andx_state *state = tevent_req_data( + req, struct cli_read_andx_state); + uint8_t *inbuf; uint8_t wct; uint16_t *vwv; - uint16_t num_bytes; + uint32_t num_bytes; uint8_t *bytes; - uint8_t *buf; - NTSTATUS status; - size_t size; - - if (async_req_is_nterror(req, &status)) { - return status; - } - status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); - - if (NT_STATUS_IS_ERR(status)) { - return status; - } - - if (wct < 12) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; + state->status = cli_smb_recv(subreq, 12, &wct, &vwv, &num_bytes, + &bytes); + if (NT_STATUS_IS_ERR(state->status)) { + tevent_req_nterror(req, state->status); + return; } /* size is the number of bytes the server returned. * Might be zero. */ - size = SVAL(vwv + 5, 0); - size |= (((unsigned int)SVAL(vwv + 7, 0)) << 16); + state->received = SVAL(vwv + 5, 0); + state->received |= (((unsigned int)SVAL(vwv + 7, 0)) << 16); - if (size > cli_req->data.read.size) { + if (state->received > state->size) { DEBUG(5,("server returned more than we wanted!\n")); - return NT_STATUS_UNEXPECTED_IO_ERROR; + tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR); + return; } /* @@ -177,24 +184,52 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, * bcc field can't be correct. */ - if ((size < 0xffff) && (size > num_bytes)) { + if ((state->received < 0xffff) && (state->received > num_bytes)) { DEBUG(5, ("server announced more bytes than sent\n")); - return NT_STATUS_INVALID_NETWORK_RESPONSE; + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } - buf = (uint8_t *)smb_base(cli_req->inbuf) + SVAL(vwv+6, 0); + inbuf = cli_smb_inbuf(subreq); + state->buf = (uint8_t *)smb_base(inbuf) + SVAL(vwv+6, 0); - if (trans_oob(smb_len(cli_req->inbuf), SVAL(vwv+6, 0), size) - || (buf < bytes)) { + if (trans_oob(smb_len(inbuf), SVAL(vwv+6, 0), state->received) + || (state->buf < bytes)) { DEBUG(5, ("server returned invalid read&x data offset\n")); - return NT_STATUS_INVALID_NETWORK_RESPONSE; + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } + tevent_req_done(req); +} - *rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0)); - *received = size; +/* + * Pull the data out of a finished async read_and_x request. rcvbuf is + * talloced from the request, so better make sure that you copy it away before + * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not + * talloc_move it! + */ + +NTSTATUS cli_read_andx_recv(struct tevent_req *req, ssize_t *received, + uint8_t **rcvbuf) +{ + struct cli_read_andx_state *state = tevent_req_data( + req, struct cli_read_andx_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *received = state->received; + *rcvbuf = state->buf; return NT_STATUS_OK; } +struct cli_pull_subreq { + struct tevent_req *req; + ssize_t received; + uint8_t *buf; +}; + /* * Parallel read support. * @@ -221,7 +256,7 @@ struct cli_pull_state { * Outstanding requests */ int num_reqs; - struct async_req **reqs; + struct cli_pull_subreq *reqs; /* * For how many bytes did we send requests already? @@ -259,7 +294,7 @@ static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) state->num_reqs, state->top_req); } -static void cli_pull_read_done(struct async_req *read_req); +static void cli_pull_read_done(struct tevent_req *read_req); /* * Prepare an async pull request @@ -308,7 +343,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, 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->reqs = TALLOC_ZERO_ARRAY(state, struct cli_pull_subreq, state->num_reqs); if (state->reqs == NULL) { goto failed; @@ -317,6 +352,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->requested = 0; for (i=0; i<state->num_reqs; i++) { + struct cli_pull_subreq *subreq = &state->reqs[i]; SMB_OFF_T size_left; size_t request_thistime; @@ -328,18 +364,16 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, size_left = size - state->requested; request_thistime = MIN(size_left, state->chunk_size); - state->reqs[i] = cli_read_andx_send( + subreq->req = cli_read_andx_send( state->reqs, ev, cli, fnum, state->start_offset + state->requested, request_thistime); - if (state->reqs[i] == NULL) { + if (subreq->req == NULL) { goto failed; } - - state->reqs[i]->async.fn = cli_pull_read_done; - state->reqs[i]->async.priv = result; - + tevent_req_set_callback(subreq->req, cli_pull_read_done, + result); state->requested += request_thistime; } return result; @@ -354,18 +388,30 @@ failed: * requests if necessary. */ -static void cli_pull_read_done(struct async_req *read_req) +static void cli_pull_read_done(struct tevent_req *subreq) { - struct async_req *pull_req = talloc_get_type_abort( - read_req->async.priv, struct async_req); + struct async_req *req = tevent_req_callback_data( + subreq, struct async_req); struct cli_pull_state *state = talloc_get_type_abort( - pull_req->private_data, struct cli_pull_state); - struct cli_request *read_state = talloc_get_type_abort( - read_req->private_data, struct cli_request); + req->private_data, struct cli_pull_state); + struct cli_pull_subreq *pull_subreq = NULL; NTSTATUS status; + int i; + + for (i = 0; i < state->num_reqs; i++) { + pull_subreq = &state->reqs[i]; + if (subreq == pull_subreq->req) { + break; + } + } + if (i == state->num_reqs) { + /* Huh -- received something we did not send?? */ + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } - status = cli_read_andx_recv(read_req, &read_state->data.read.received, - &read_state->data.read.rcvbuf); + status = cli_read_andx_recv(subreq, &pull_subreq->received, + &pull_subreq->buf); if (!NT_STATUS_IS_OK(status)) { async_req_nterror(state->req, status); return; @@ -380,39 +426,36 @@ static void cli_pull_read_done(struct async_req *read_req) * requests. */ - while (state->reqs[state->top_req] != NULL) { - struct cli_request *top_read; + while (state->reqs[state->top_req].req != NULL) { + struct cli_pull_subreq *top_subreq; DEBUG(11, ("cli_pull_read_done: top_req = %d\n", state->top_req)); - if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { + top_subreq = &state->reqs[state->top_req]; + + if (tevent_req_is_in_progress(top_subreq->req)) { DEBUG(11, ("cli_pull_read_done: top request not yet " "done\n")); return; } - top_read = talloc_get_type_abort( - state->reqs[state->top_req]->private_data, - struct cli_request); - DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " - "pushed\n", (int)top_read->data.read.received, + "pushed\n", (int)top_subreq->received, (int)state->pushed)); - status = state->sink((char *)top_read->data.read.rcvbuf, - top_read->data.read.received, - state->priv); + status = state->sink((char *)top_subreq->buf, + top_subreq->received, state->priv); if (!NT_STATUS_IS_OK(status)) { async_req_nterror(state->req, status); return; } - state->pushed += top_read->data.read.received; + state->pushed += top_subreq->received; - TALLOC_FREE(state->reqs[state->top_req]); + TALLOC_FREE(state->reqs[state->top_req].req); if (state->requested < state->size) { - struct async_req *new_req; + struct tevent_req *new_req; SMB_OFF_T size_left; size_t request_thistime; @@ -435,18 +478,17 @@ static void cli_pull_read_done(struct async_req *read_req) if (async_req_nomem(new_req, state->req)) { return; } + tevent_req_set_callback(new_req, cli_pull_read_done, + req); - new_req->async.fn = cli_pull_read_done; - new_req->async.priv = pull_req; - - state->reqs[state->top_req] = new_req; + state->reqs[state->top_req].req = new_req; state->requested += request_thistime; } state->top_req = (state->top_req+1) % state->num_reqs; } - async_req_done(pull_req); + async_req_done(req); } NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index e6de8396a8..cc8f2e17c6 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -119,7 +119,7 @@ struct rpc_np_read_state { ssize_t received; }; -static void rpc_np_read_done(struct async_req *subreq); +static void rpc_np_read_done(struct tevent_req *subreq); static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -128,8 +128,7 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, { struct rpc_transport_np_state *np_transport = talloc_get_type_abort( priv, struct rpc_transport_np_state); - struct tevent_req *req; - struct async_req *subreq; + struct tevent_req *req, *subreq; struct rpc_np_read_state *state; req = tevent_req_create(mem_ctx, &state, struct rpc_np_read_state); @@ -144,18 +143,17 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, if (subreq == NULL) { goto fail; } - subreq->async.fn = rpc_np_read_done; - subreq->async.priv = req; + tevent_req_set_callback(subreq, rpc_np_read_done, req); return req; fail: TALLOC_FREE(req); return NULL; } -static void rpc_np_read_done(struct async_req *subreq) +static void rpc_np_read_done(struct tevent_req *subreq) { - struct tevent_req *req = talloc_get_type_abort( - subreq->async.priv, struct tevent_req); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); struct rpc_np_read_state *state = tevent_req_data( req, struct rpc_np_read_state); NTSTATUS status; |