s4:libcli/raw: make sure smbcli_transport_connect_send/recv correctly cleanup on...
authorStefan Metzmacher <metze@samba.org>
Thu, 28 May 2015 12:25:27 +0000 (14:25 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 12 Jun 2015 15:08:17 +0000 (17:08 +0200)
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>
source4/libcli/raw/clisocket.c

index dd3ea3971c1510ea49a974c83cb00f36357843a1..1959a933dde0100a405bb8e5a8deba1a85018454 100644 (file)
 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);
 }