From 249f412420367ec4af01012ae1ac1635d22d2e68 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Jun 2011 11:32:44 +0200 Subject: [PATCH] s3: Fix bug 8203 Always have the read_smb_req pending, even if the request has not yet been sent completely. --- source3/include/client.h | 1 + source3/libsmb/async_smb.c | 41 ++++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/source3/include/client.h b/source3/include/client.h index 7d66bf9..858182c 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -148,6 +148,7 @@ struct cli_state { struct tevent_queue *outgoing; struct tevent_req **pending; + struct tevent_req *read_smb_req; }; struct file_info { diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 8c5627d..55e49f1 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -240,12 +240,8 @@ void cli_smb_req_unset_pending(struct tevent_req *req) int i; if (num_pending == 1) { - /* - * The pending read_smb tevent_req is a child of - * cli->pending. So if nothing is pending anymore, we need to - * delete the socket read fde. - */ TALLOC_FREE(cli->pending); + cli->read_smb_req = NULL; return; } @@ -294,7 +290,6 @@ bool cli_smb_req_set_pending(struct tevent_req *req) struct cli_state *cli; struct tevent_req **pending; int num_pending; - struct tevent_req *subreq; cli = state->cli; num_pending = talloc_array_length(cli->pending); @@ -308,7 +303,7 @@ bool cli_smb_req_set_pending(struct tevent_req *req) cli->pending = pending; talloc_set_destructor(req, cli_smb_req_destructor); - if (num_pending > 0) { + if (cli->read_smb_req != NULL) { return true; } @@ -316,12 +311,12 @@ bool cli_smb_req_set_pending(struct tevent_req *req) * We're the first ones, add the read_smb request that waits for the * answer from the server */ - subreq = read_smb_send(cli->pending, state->ev, cli->fd); - if (subreq == NULL) { + cli->read_smb_req = read_smb_send(cli, state->ev, cli->fd); + if (cli->read_smb_req == NULL) { cli_smb_req_unset_pending(req); return false; } - tevent_req_set_callback(subreq, cli_smb_received, cli); + tevent_req_set_callback(cli->read_smb_req, cli_smb_received, cli); return true; } @@ -524,6 +519,12 @@ static NTSTATUS cli_smb_req_iov_send(struct tevent_req *req, return NT_STATUS_NO_MEMORY; } tevent_req_set_callback(subreq, cli_smb_sent, req); + + if (!cli_smb_req_set_pending(req)) { + TALLOC_FREE(subreq); + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; } @@ -590,22 +591,19 @@ static void cli_smb_sent(struct tevent_req *subreq) case SMBtranss2: case SMBnttranss: case SMBntcancel: + cli_smb_req_unset_pending(req); state->inbuf = NULL; tevent_req_done(req); return; case SMBlockingX: if ((CVAL(state->header, smb_wct) == 8) && (CVAL(state->vwv+3, 0) == LOCKING_ANDX_OPLOCK_RELEASE)) { + cli_smb_req_unset_pending(req); state->inbuf = NULL; tevent_req_done(req); return; } } - - if (!cli_smb_req_set_pending(req)) { - tevent_req_nterror(req, NT_STATUS_NO_MEMORY); - return; - } } static void cli_smb_received(struct tevent_req *subreq) @@ -624,6 +622,7 @@ static void cli_smb_received(struct tevent_req *subreq) received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err); TALLOC_FREE(subreq); + cli->read_smb_req = NULL; if (received == -1) { if (cli->fd != -1) { close(cli->fd); @@ -703,6 +702,8 @@ static void cli_smb_received(struct tevent_req *subreq) req = cli->pending[i]; state = tevent_req_data(req, struct cli_smb_state); + cli_smb_req_unset_pending(req); + if (!oplock_break /* oplock breaks are not signed */ && !cli_check_sign_mac(cli, (char *)inbuf, state->seqnum+1)) { DEBUG(10, ("cli_check_sign_mac failed\n")); @@ -737,18 +738,20 @@ static void cli_smb_received(struct tevent_req *subreq) TALLOC_FREE(chain); } done: - if (talloc_array_length(cli->pending) > 0) { + if ((talloc_array_length(cli->pending) > 0) && + (cli->read_smb_req == NULL)) { /* * Set up another read request for the other pending cli_smb * requests */ state = tevent_req_data(cli->pending[0], struct cli_smb_state); - subreq = read_smb_send(cli->pending, state->ev, cli->fd); - if (subreq == NULL) { + cli->read_smb_req = read_smb_send(cli, state->ev, cli->fd); + if (cli->read_smb_req == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; } - tevent_req_set_callback(subreq, cli_smb_received, cli); + tevent_req_set_callback(cli->read_smb_req, cli_smb_received, + cli); } return; fail: -- 1.7.0.4