s3:rpc_client: add rpccli_is_connected()
authorStefan Metzmacher <metze@samba.org>
Tue, 6 Apr 2010 12:26:29 +0000 (14:26 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 7 Apr 2010 12:00:01 +0000 (14:00 +0200)
metze
(cherry picked from commit 4f41b53487ac9bc96c7960e8edab464558656373)
(similar to commit 958b49323968740e2cbf69dc2a0a5dd57d5bcf87)

Signed-off-by: Stefan Metzmacher <metze@samba.org>
source3/include/client.h
source3/include/proto.h
source3/rpc_client/cli_pipe.c
source3/rpc_client/rpc_transport_np.c
source3/rpc_client/rpc_transport_smbd.c
source3/rpc_client/rpc_transport_sock.c

index 19142109fd098320427a122a3f23e38b419a1d0c..bdc6aeb863f080566d8d438ac58af52ad54a3755 100644 (file)
@@ -110,6 +110,9 @@ struct rpc_cli_transport {
         */
        NTSTATUS (*trans_recv)(struct async_req *req, TALLOC_CTX *mem_ctx,
                               uint8_t **prdata, uint32_t *prdata_len);
+
+       bool (*is_connected)(void *priv);
+
        void *priv;
 };
 
index 446f0e58bcd0358eb0a7ab40e02dfde30212a237..47b56def86f4efb75bc2e248a41ba98b2fb7848d 100644 (file)
@@ -5312,6 +5312,7 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
                       struct cli_pipe_auth_data *auth);
 unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli,
                                unsigned int timeout);
+bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli);
 bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16]);
 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
                               struct cli_pipe_auth_data **presult);
index cc0c66c2171da3466e24deb34bed55adb93d954b..94e714d3b8176261446a6edc42c058d478781367 100644 (file)
@@ -2961,6 +2961,19 @@ unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
        return cli_set_timeout(cli, timeout);
 }
 
+bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
+{
+       if (rpc_cli == NULL) {
+               return false;
+       }
+
+       if (rpc_cli->transport == NULL) {
+               return false;
+       }
+
+       return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
+}
+
 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
 {
        struct cli_state *cli;
index 1997e9c8c9d3042fa0263e94ef789647f26535e5..ae0c326324126877d32c942f5ad4a1b2e51d7aac 100644 (file)
@@ -28,11 +28,30 @@ struct rpc_transport_np_state {
        uint16_t fnum;
 };
 
+static bool rpc_np_is_connected(void *priv)
+{
+       struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
+               priv, struct rpc_transport_np_state);
+       bool ok;
+
+       if (np_transport->cli == NULL) {
+               return false;
+       }
+
+       ok = cli_state_is_connected(np_transport->cli);
+       if (!ok) {
+               np_transport->cli = NULL;
+               return false;
+       }
+
+       return true;
+}
+
 static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s)
 {
        bool ret;
 
-       if (!cli_state_is_connected(s->cli)) {
+       if (!rpc_np_is_connected(s)) {
                DEBUG(10, ("socket was closed, no need to send close request.\n"));
                return 0;
        }
@@ -51,6 +70,7 @@ static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s)
 }
 
 struct rpc_np_write_state {
+       struct rpc_transport_np_state *np_transport;
        size_t size;
        size_t written;
 };
@@ -66,13 +86,26 @@ static struct async_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_np_state);
        struct async_req *result, *subreq;
        struct rpc_np_write_state *state;
+       bool ok;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct rpc_np_write_state)) {
                return NULL;
        }
+
+       ok = rpc_np_is_connected(np_transport);
+       if (!ok) {
+               ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID);
+               if (!ok) {
+                       goto fail;
+               }
+               return result;
+       }
+
+       state->np_transport = np_transport;
        state->size = size;
 
+
        subreq = cli_write_andx_send(mem_ctx, ev, np_transport->cli,
                                     np_transport->fnum,
                                     8, /* 8 means message mode. */
@@ -99,6 +132,7 @@ static void rpc_np_write_done(struct async_req *subreq)
        status = cli_write_andx_recv(subreq, &state->written);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
+               state->np_transport->cli = NULL;
                async_req_nterror(req, status);
                return;
        }
@@ -119,6 +153,7 @@ static NTSTATUS rpc_np_write_recv(struct async_req *req, ssize_t *pwritten)
 }
 
 struct rpc_np_read_state {
+       struct rpc_transport_np_state *np_transport;
        uint8_t *data;
        size_t size;
        ssize_t received;
@@ -135,11 +170,23 @@ static struct async_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_np_state);
        struct async_req *result, *subreq;
        struct rpc_np_read_state *state;
+       bool ok;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct rpc_np_read_state)) {
                return NULL;
        }
+
+       ok = rpc_np_is_connected(np_transport);
+       if (!ok) {
+               ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID);
+               if (!ok) {
+                       goto fail;
+               }
+               return result;
+       }
+
+       state->np_transport = np_transport;
        state->data = data;
        state->size = size;
 
@@ -178,18 +225,21 @@ static void rpc_np_read_done(struct async_req *subreq)
        }
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(subreq);
+               state->np_transport->cli = NULL;
                async_req_nterror(req, status);
                return;
        }
 
        if (state->received > state->size) {
                TALLOC_FREE(subreq);
+               state->np_transport->cli = NULL;
                async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
                return;
        }
 
        if (state->received == 0) {
                TALLOC_FREE(subreq);
+               state->np_transport->cli = NULL;
                async_req_nterror(req, NT_STATUS_PIPE_BROKEN);
                return;
        }
@@ -213,6 +263,7 @@ static NTSTATUS rpc_np_read_recv(struct async_req *req, ssize_t *preceived)
 }
 
 struct rpc_np_trans_state {
+       struct rpc_transport_np_state *np_transport;
        uint16_t setup[2];
        uint32_t max_rdata_len;
        uint8_t *rdata;
@@ -231,12 +282,23 @@ static struct async_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_np_state);
        struct async_req *result, *subreq;
        struct rpc_np_trans_state *state;
+       bool ok;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct rpc_np_trans_state)) {
                return NULL;
        }
 
+       ok = rpc_np_is_connected(np_transport);
+       if (!ok) {
+               ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID);
+               if (!ok) {
+                       goto fail;
+               }
+               return result;
+       }
+
+       state->np_transport = np_transport;
        state->max_rdata_len = max_rdata_len;
 
        SSVAL(state->setup+0, 0, TRANSACT_DCERPCCMD);
@@ -273,16 +335,19 @@ static void rpc_np_trans_done(struct async_req *subreq)
                status = NT_STATUS_OK;
        }
        if (!NT_STATUS_IS_OK(status)) {
+               state->np_transport->cli = NULL;
                async_req_nterror(req, status);
                return;
        }
 
        if (state->rdata_len > state->max_rdata_len) {
+               state->np_transport->cli = NULL;
                async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
                return;
        }
 
        if (state->rdata_len == 0) {
+               state->np_transport->cli = NULL;
                async_req_nterror(req, NT_STATUS_PIPE_BROKEN);
                return;
        }
@@ -319,12 +384,22 @@ struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
 {
        struct async_req *result, *subreq;
        struct rpc_transport_np_init_state *state;
+       bool ok;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct rpc_transport_np_init_state)) {
                return NULL;
        }
 
+       ok = cli_state_is_connected(cli);
+       if (!ok) {
+               ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID);
+               if (!ok) {
+                       goto fail;
+               }
+               return result;
+       }
+
        state->transport = talloc(state, struct rpc_cli_transport);
        if (state->transport == NULL) {
                goto fail;
@@ -394,6 +469,7 @@ NTSTATUS rpc_transport_np_init_recv(struct async_req *req,
        state->transport->read_recv = rpc_np_read_recv;
        state->transport->trans_send = rpc_np_trans_send;
        state->transport->trans_recv = rpc_np_trans_recv;
+       state->transport->is_connected = rpc_np_is_connected;
 
        *presult = talloc_move(mem_ctx, &state->transport);
        return NT_STATUS_OK;
index 823f216c128aa9c255f360fe19f8272067483701..262caf9ee39e0f43967bb5ee074327711bb5cfdc 100644 (file)
@@ -429,8 +429,53 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
        return status;
 }
 
+static void rpc_smbd_disconnect(struct rpc_transport_smbd_state *transp)
+{
+       if (transp == NULL) {
+               return;
+       }
+
+       if (transp->conn == NULL) {
+               return;
+       }
+
+       if (transp->conn->cli == NULL) {
+               return;
+       }
+
+       if (transp->conn->cli->fd != -1) {
+               close(transp->conn->cli->fd);
+               transp->conn->cli->fd = -1;
+       }
+
+       transp->conn = NULL;
+}
+
+static bool rpc_smbd_is_connected(void *priv)
+{
+       struct rpc_transport_smbd_state *transp = talloc_get_type_abort(
+               priv, struct rpc_transport_smbd_state);
+       bool ok;
+
+       if (transp->conn == NULL) {
+               return false;
+       }
+
+       if (transp->sub_transp == NULL) {
+               return false;
+       }
+
+       ok = transp->sub_transp->is_connected(transp->sub_transp->priv);
+       if (!ok) {
+               rpc_smbd_disconnect(transp);
+               return false;
+       }
+
+       return true;
+}
+
 struct rpc_smbd_write_state {
-       struct rpc_cli_transport *sub_transp;
+       struct rpc_transport_smbd_state *transp;
        ssize_t written;
 };
 
@@ -445,12 +490,23 @@ static struct async_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_smbd_state);
        struct async_req *result, *subreq;
        struct rpc_smbd_write_state *state;
+       bool ok;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct rpc_smbd_write_state)) {
                return NULL;
        }
-       state->sub_transp = transp->sub_transp;
+
+       ok = rpc_smbd_is_connected(transp);
+       if (!ok) {
+               ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID);
+               if (!ok) {
+                       goto fail;
+               }
+               return result;
+       }
+
+       state->transp = transp;
 
        subreq = transp->sub_transp->write_send(state, ev, data, size,
                                                transp->sub_transp->priv);
@@ -480,9 +536,10 @@ static void rpc_smbd_write_done(struct async_req *subreq)
                req->private_data, struct rpc_smbd_write_state);
        NTSTATUS status;
 
-       status = state->sub_transp->write_recv(subreq, &state->written);
+       status = state->transp->sub_transp->write_recv(subreq, &state->written);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
+               rpc_smbd_disconnect(state->transp);
                async_req_nterror(req, status);
                return;
        }
@@ -503,7 +560,7 @@ static NTSTATUS rpc_smbd_write_recv(struct async_req *req, ssize_t *pwritten)
 }
 
 struct rpc_smbd_read_state {
-       struct rpc_cli_transport *sub_transp;
+       struct rpc_transport_smbd_state *transp;
        ssize_t received;
 };
 
@@ -518,12 +575,23 @@ static struct async_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_smbd_state);
        struct async_req *result, *subreq;
        struct rpc_smbd_read_state *state;
+       bool ok;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct rpc_smbd_read_state)) {
                return NULL;
        }
-       state->sub_transp = transp->sub_transp;
+
+       ok = rpc_smbd_is_connected(transp);
+       if (!ok) {
+               ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID);
+               if (!ok) {
+                       goto fail;
+               }
+               return result;
+       }
+
+       state->transp = transp;
 
        subreq = transp->sub_transp->read_send(state, ev, data, size,
                                                transp->sub_transp->priv);
@@ -553,9 +621,10 @@ static void rpc_smbd_read_done(struct async_req *subreq)
                req->private_data, struct rpc_smbd_read_state);
        NTSTATUS status;
 
-       status = state->sub_transp->read_recv(subreq, &state->received);
+       status = state->transp->sub_transp->read_recv(subreq, &state->received);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
+               rpc_smbd_disconnect(state->transp);
                async_req_nterror(req, status);
                return;
        }
@@ -663,6 +732,7 @@ NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req,
        state->transport->read_recv = rpc_smbd_read_recv;
        state->transport->trans_send = NULL;
        state->transport->trans_recv = NULL;
+       state->transport->is_connected = rpc_smbd_is_connected;
 
        *presult = talloc_move(mem_ctx, &state->transport);
        return NT_STATUS_OK;
index 2cc66946902434637472f4caf2aca510855d5072..95e16c381f1f65ab6da3bc3695168f7bebcd6681 100644 (file)
@@ -27,15 +27,32 @@ struct rpc_transport_sock_state {
        int timeout;
 };
 
-static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s)
+static void rpc_sock_disconnect(struct rpc_transport_sock_state *s)
 {
        if (s->fd != -1) {
                close(s->fd);
                s->fd = -1;
        }
+}
+
+static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s)
+{
+       rpc_sock_disconnect(s);
        return 0;
 }
 
+static bool rpc_sock_is_connected(void *priv)
+{
+       struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort(
+               priv, struct rpc_transport_sock_state);
+
+       if (sock_transp->fd == -1) {
+               return false;
+       }
+
+       return true;
+}
+
 struct rpc_sock_read_state {
        struct rpc_transport_sock_state *transp;
        ssize_t received;
@@ -59,7 +76,7 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx,
                             struct rpc_sock_read_state)) {
                return NULL;
        }
-       if (sock_transp->fd == -1) {
+       if (!rpc_sock_is_connected(sock_transp)) {
                if (!async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID)) {
                        goto fail;
                }
@@ -97,11 +114,8 @@ static void rpc_sock_read_done(struct tevent_req *subreq)
        state->received = async_recv_recv(subreq, &err);
 
        if (state->received == -1) {
-               if (state->transp->fd != -1) {
-                       close(state->transp->fd);
-                       state->transp->fd = -1;
-               }
                TALLOC_FREE(subreq);
+               rpc_sock_disconnect(state->transp);
                async_req_nterror(req, map_nt_error_from_unix(err));
                return;
        }
@@ -145,7 +159,7 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx,
                             struct rpc_sock_write_state)) {
                return NULL;
        }
-       if (sock_transp->fd == -1) {
+       if (!rpc_sock_is_connected(sock_transp)) {
                if (!async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID)) {
                        goto fail;
                }
@@ -183,11 +197,8 @@ static void rpc_sock_write_done(struct tevent_req *subreq)
        state->sent = async_send_recv(subreq, &err);
 
        if (state->sent == -1) {
-               if (state->transp->fd != -1) {
-                       close(state->transp->fd);
-                       state->transp->fd = -1;
-               }
                TALLOC_FREE(subreq);
+               rpc_sock_disconnect(state->transp);
                async_req_nterror(req, map_nt_error_from_unix(err));
                return;
        }
@@ -235,6 +246,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd,
        result->write_recv = rpc_sock_write_recv;
        result->read_send = rpc_sock_read_send;
        result->read_recv = rpc_sock_read_recv;
+       result->is_connected = rpc_sock_is_connected;
 
        *presult = result;
        return NT_STATUS_OK;