From 1335059ff5ef1a8f0f9aedf6a6db366074d457f3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 26 Jul 2011 19:44:51 +0200 Subject: s3: Fix async smb handling In cli_echo with more than one response we ended up with more than one read_smb request. One from the call to cli_smb_req_set_pending called from cli_smb_received. The other one from cli_smb_received itself. I don't really see another way to deal with this than to hold the read_smb request in the cli_state. Metze, please check! Volker --- source3/libsmb/async_smb.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 87614bd326..ecc77803b0 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -139,6 +139,7 @@ void cli_smb_req_unset_pending(struct tevent_req *req) * delete the socket read fde. */ TALLOC_FREE(cli->conn.pending); + cli->conn.read_smb_req = NULL; return; } @@ -193,7 +194,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->conn.pending); @@ -207,7 +207,7 @@ bool cli_smb_req_set_pending(struct tevent_req *req) cli->conn.pending = pending; talloc_set_destructor(req, cli_smb_req_destructor); - if (num_pending > 0) { + if (cli->conn.read_smb_req != NULL) { return true; } @@ -215,12 +215,13 @@ 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->conn.pending, state->ev, cli->conn.fd); - if (subreq == NULL) { + cli->conn.read_smb_req = read_smb_send(cli->conn.pending, state->ev, + cli->conn.fd); + if (cli->conn.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->conn.read_smb_req, cli_smb_received, cli); return true; } @@ -531,8 +532,16 @@ static void cli_smb_received(struct tevent_req *subreq) uint16_t mid; bool oplock_break; + if (subreq != cli->conn.read_smb_req) { + DEBUG(1, ("Internal error: cli_smb_received called with " + "unexpected subreq\n")); + status = NT_STATUS_INTERNAL_ERROR; + goto fail; + } + received = read_smb_recv(subreq, talloc_tos(), &inbuf, &err); TALLOC_FREE(subreq); + cli->conn.read_smb_req = NULL; if (received == -1) { cli_state_disconnect(cli); status = map_nt_error_from_unix(err); @@ -642,19 +651,22 @@ static void cli_smb_received(struct tevent_req *subreq) TALLOC_FREE(chain); } done: - if (talloc_array_length(cli->conn.pending) > 0) { + if ((talloc_array_length(cli->conn.pending) > 0) && + (cli->conn.read_smb_req == NULL)) { /* * Set up another read request for the other pending cli_smb * requests */ state = tevent_req_data(cli->conn.pending[0], struct cli_smb_state); - subreq = read_smb_send(cli->conn.pending, state->ev, cli->conn.fd); - if (subreq == NULL) { + cli->conn.read_smb_req = read_smb_send( + cli->conn.pending, state->ev, cli->conn.fd); + if (cli->conn.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->conn.read_smb_req, + cli_smb_received, cli); } return; fail: -- cgit