summaryrefslogtreecommitdiff
path: root/source4/libcli
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2015-05-28 14:25:27 +0200
committerStefan Metzmacher <metze@samba.org>2015-06-12 17:08:17 +0200
commitdd037b0be4ed2df7239cb61bd3d4bb868bb09126 (patch)
treee31b84f84715a1c1dfe6dffa8359f0582a297805 /source4/libcli
parent36b97d0bb9fe004f3d8a500f3af83dff34f86d7b (diff)
downloadsamba-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/libcli')
-rw-r--r--source4/libcli/raw/clisocket.c59
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);
}