s3:rpc_client: add rpccli_is_connected()
authorStefan Metzmacher <metze@samba.org>
Thu, 25 Mar 2010 14:00:38 +0000 (15:00 +0100)
committerKarolin Seeger <kseeger@samba.org>
Tue, 30 Mar 2010 08:33:41 +0000 (10:33 +0200)
metze
(cherry picked from commit 4f41b53487ac9bc96c7960e8edab464558656373)
(cherry picked from commit 958b49323968740e2cbf69dc2a0a5dd57d5bcf87)

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 cc32cd1be36bcbae12d8c92fa3eeeebf1aa06b19..252d9b3ffe840b6aa3b5d66a1d3768e6cab0f16e 100644 (file)
@@ -110,6 +110,9 @@ struct rpc_cli_transport {
         */
        NTSTATUS (*trans_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                               uint8_t **prdata, uint32_t *prdata_len);
+
+       bool (*is_connected)(void *priv);
+
        void *priv;
 };
 
index 4e2c75f5d8429357e309e5f82199fa557b3f0a97..3da0ff8be04814c7db8a16e869e7d5bf3f4559b7 100644 (file)
@@ -5292,6 +5292,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 bb037e8a4e032d13b5b8adbf53a54296f66e033b..e27f8297a8693a3d950b6e29758bd1814bfd5fb4 100644 (file)
@@ -3060,6 +3060,19 @@ unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
        return 0;
 }
 
+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 014ce92adccacaf037944e42a31d1ab92b82bc91..0fe3d026e2a80a5f13bfdb4800811276f38d5dab 100644 (file)
@@ -28,9 +28,28 @@ 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)
 {
-       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;
        }
@@ -49,6 +68,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;
 };
@@ -64,13 +84,23 @@ static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_np_state);
        struct tevent_req *req, *subreq;
        struct rpc_np_write_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_np_write_state);
        if (req == NULL) {
                return NULL;
        }
+
+       ok = rpc_np_is_connected(np_transport);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
+               return tevent_req_post(req, ev);
+       }
+
+       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. */
@@ -93,6 +123,7 @@ static void rpc_np_write_done(struct tevent_req *subreq)
        status = cli_write_andx_recv(subreq, &state->written);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, status);
                return;
        }
@@ -113,6 +144,7 @@ static NTSTATUS rpc_np_write_recv(struct tevent_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;
@@ -129,11 +161,20 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_np_state);
        struct tevent_req *req, *subreq;
        struct rpc_np_read_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_np_read_state);
        if (req == NULL) {
                return NULL;
        }
+
+       ok = rpc_np_is_connected(np_transport);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
+               return tevent_req_post(req, ev);
+       }
+
+       state->np_transport = np_transport;
        state->data = data;
        state->size = size;
 
@@ -171,18 +212,21 @@ static void rpc_np_read_done(struct tevent_req *subreq)
        }
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(subreq);
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, status);
                return;
        }
 
        if (state->received > state->size) {
                TALLOC_FREE(subreq);
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
                return;
        }
 
        if (state->received == 0) {
                TALLOC_FREE(subreq);
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, NT_STATUS_PIPE_BROKEN);
                return;
        }
@@ -206,6 +250,7 @@ static NTSTATUS rpc_np_read_recv(struct tevent_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;
@@ -224,12 +269,20 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_np_state);
        struct tevent_req *req, *subreq;
        struct rpc_np_trans_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_np_trans_state);
        if (req == NULL) {
                return NULL;
        }
 
+       ok = rpc_np_is_connected(np_transport);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
+               return tevent_req_post(req, ev);
+       }
+
+       state->np_transport = np_transport;
        state->max_rdata_len = max_rdata_len;
 
        SSVAL(state->setup+0, 0, TRANSACT_DCERPCCMD);
@@ -265,16 +318,19 @@ static void rpc_np_trans_done(struct tevent_req *subreq)
                status = NT_STATUS_OK;
        }
        if (!NT_STATUS_IS_OK(status)) {
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, status);
                return;
        }
 
        if (state->rdata_len > state->max_rdata_len) {
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
                return;
        }
 
        if (state->rdata_len == 0) {
+               state->np_transport->cli = NULL;
                tevent_req_nterror(req, NT_STATUS_PIPE_BROKEN);
                return;
        }
@@ -311,6 +367,7 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
 {
        struct tevent_req *req, *subreq;
        struct rpc_transport_np_init_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct rpc_transport_np_init_state);
@@ -318,6 +375,12 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
+       ok = cli_state_is_connected(cli);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
+               return tevent_req_post(req, ev);
+       }
+
        state->transport = talloc(state, struct rpc_cli_transport);
        if (tevent_req_nomem(state->transport, req)) {
                return tevent_req_post(req, ev);
@@ -383,6 +446,7 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_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 929e553c8492b899da75d89a726d4e1618d9bb71..47c426f120b1961eb4d4f5c2606c0004fba6c2aa 100644 (file)
@@ -419,8 +419,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;
 };
 
@@ -435,12 +480,20 @@ static struct tevent_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_smbd_state);
        struct tevent_req *req, *subreq;
        struct rpc_smbd_write_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_smbd_write_state);
        if (req == NULL) {
                return NULL;
        }
-       state->sub_transp = transp->sub_transp;
+
+       ok = rpc_smbd_is_connected(transp);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
+               return tevent_req_post(req, ev);
+       }
+
+       state->transp = transp;
 
        subreq = transp->sub_transp->write_send(state, ev, data, size,
                                                transp->sub_transp->priv);
@@ -468,9 +521,10 @@ static void rpc_smbd_write_done(struct tevent_req *subreq)
                req, 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);
                tevent_req_nterror(req, status);
                return;
        }
@@ -491,7 +545,7 @@ static NTSTATUS rpc_smbd_write_recv(struct tevent_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;
 };
 
@@ -506,12 +560,20 @@ static struct tevent_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx,
                priv, struct rpc_transport_smbd_state);
        struct tevent_req *req, *subreq;
        struct rpc_smbd_read_state *state;
+       bool ok;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_smbd_read_state);
        if (req == NULL) {
                return NULL;
        }
-       state->sub_transp = transp->sub_transp;
+
+       ok = rpc_smbd_is_connected(transp);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
+               return tevent_req_post(req, ev);
+       }
+
+       state->transp = transp;
 
        subreq = transp->sub_transp->read_send(state, ev, data, size,
                                                transp->sub_transp->priv);
@@ -538,9 +600,10 @@ static void rpc_smbd_read_done(struct tevent_req *subreq)
                req, 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);
                tevent_req_nterror(req, status);
                return;
        }
@@ -645,6 +708,7 @@ NTSTATUS rpc_transport_smbd_init_recv(struct tevent_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 4ab17dbd8daf0f86e206f6203fef7a67592f6394..5132504a85f24c4d4cdd1d89a9a30abde5842460 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;
@@ -58,7 +75,7 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx,
        if (req == NULL) {
                return NULL;
        }
-       if (sock_transp->fd == -1) {
+       if (!rpc_sock_is_connected(sock_transp)) {
                tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
                return tevent_req_post(req, ev);
        }
@@ -94,11 +111,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);
                tevent_req_nterror(req, map_nt_error_from_unix(err));
                return;
        }
@@ -141,7 +155,7 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx,
        if (req == NULL) {
                return NULL;
        }
-       if (sock_transp->fd == -1) {
+       if (!rpc_sock_is_connected(sock_transp)) {
                tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID);
                return tevent_req_post(req, ev);
        }
@@ -177,11 +191,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);
                tevent_req_nterror(req, map_nt_error_from_unix(err));
                return;
        }
@@ -229,6 +240,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;