diff options
author | Stefan Metzmacher <metze@samba.org> | 2015-05-28 14:25:27 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2015-06-12 17:08:17 +0200 |
commit | dd037b0be4ed2df7239cb61bd3d4bb868bb09126 (patch) | |
tree | e31b84f84715a1c1dfe6dffa8359f0582a297805 /source4 | |
parent | 36b97d0bb9fe004f3d8a500f3af83dff34f86d7b (diff) | |
download | samba-dd037b0be4ed2df7239cb61bd3d4bb868bb09126.tar.gz |
s4:libcli/raw: make sure smbcli_transport_connect_send/recv correctly cleanup on error
We need to make sure that we remove any pending writev_send or read_smb_send
request before closing the socket fd. As a side effect we always close the
socket fd if we don't return success for any any reason.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11316
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source4')
-rw-r--r-- | source4/libcli/raw/clisocket.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c index dd3ea3971c1..1959a933dde 100644 --- a/source4/libcli/raw/clisocket.c +++ b/source4/libcli/raw/clisocket.c @@ -36,11 +36,14 @@ struct smbcli_transport_connect_state { struct tevent_context *ev; struct socket_context *sock; + struct tevent_req *io_req; uint8_t *request; struct iovec iov; uint8_t *response; }; +static void smbcli_transport_connect_cleanup(struct tevent_req *req, + enum tevent_req_state req_state); static void smbcli_transport_connect_writev_done(struct tevent_req *subreq); static void smbcli_transport_connect_read_smb_done(struct tevent_req *subreq); @@ -72,6 +75,8 @@ static struct tevent_req *smbcli_transport_connect_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + tevent_req_set_cleanup_fn(req, smbcli_transport_connect_cleanup); + status = nbt_name_to_blob(state, &calling_blob, calling); if (tevent_req_nterror(req, status)) { return tevent_req_post(req, ev); @@ -115,6 +120,7 @@ static struct tevent_req *smbcli_transport_connect_send(TALLOC_CTX *mem_ctx, tevent_req_set_callback(subreq, smbcli_transport_connect_writev_done, req); + state->io_req = subreq; if (timeout_msec > 0) { struct timeval endtime; @@ -128,6 +134,36 @@ static struct tevent_req *smbcli_transport_connect_send(TALLOC_CTX *mem_ctx, return req; } +static void smbcli_transport_connect_cleanup(struct tevent_req *req, + enum tevent_req_state req_state) +{ + struct smbcli_transport_connect_state *state = + tevent_req_data(req, + struct smbcli_transport_connect_state); + + TALLOC_FREE(state->io_req); + + if (state->sock == NULL) { + return; + } + + if (state->sock->fd == -1) { + return; + } + + if (req_state == TEVENT_REQ_DONE) { + /* + * we keep the socket open for the caller to use + */ + state->sock = NULL; + return; + } + + close(state->sock->fd); + state->sock->fd = -1; + state->sock = NULL; +} + static void smbcli_transport_connect_writev_done(struct tevent_req *subreq) { struct tevent_req *req = @@ -139,14 +175,12 @@ static void smbcli_transport_connect_writev_done(struct tevent_req *subreq) ssize_t ret; int err; + state->io_req = NULL; + ret = writev_recv(subreq, &err); TALLOC_FREE(subreq); if (ret == -1) { NTSTATUS status = map_nt_error_from_unix_common(err); - - close(state->sock->fd); - state->sock->fd = -1; - tevent_req_nterror(req, status); return; } @@ -159,6 +193,7 @@ static void smbcli_transport_connect_writev_done(struct tevent_req *subreq) tevent_req_set_callback(subreq, smbcli_transport_connect_read_smb_done, req); + state->io_req = subreq; } static void smbcli_transport_connect_read_smb_done(struct tevent_req *subreq) @@ -174,22 +209,18 @@ static void smbcli_transport_connect_read_smb_done(struct tevent_req *subreq) NTSTATUS status; uint8_t error; + state->io_req = NULL; + ret = read_smb_recv(subreq, state, &state->response, &err); + TALLOC_FREE(subreq); if (ret == -1) { status = map_nt_error_from_unix_common(err); - - close(state->sock->fd); - state->sock->fd = -1; - tevent_req_nterror(req, status); return; } if (ret < 4) { - close(state->sock->fd); - state->sock->fd = -1; - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -201,9 +232,6 @@ static void smbcli_transport_connect_read_smb_done(struct tevent_req *subreq) case NBSSnegative: if (ret < 5) { - close(state->sock->fd); - state->sock->fd = -1; - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -236,9 +264,6 @@ static void smbcli_transport_connect_read_smb_done(struct tevent_req *subreq) break; } - close(state->sock->fd); - state->sock->fd = -1; - tevent_req_nterror(req, status); } |