s3:rpc_client: implement rpc_transport_np_init() on top of rpc_transport_tstream_init()
[ira/wip.git] / source3 / rpc_client / rpc_transport_np.c
index 9d803aa9d4baf003edfce1a51b33af760b48796e..a3f3a1735daac6033bc39eb6107f1e43efacddb2 100644 (file)
  */
 
 #include "includes.h"
+#include "libsmb/cli_np_tstream.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_CLI
 
-struct rpc_transport_np_state {
-       struct cli_state *cli;
-       const char *pipe_name;
-       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 unsigned int rpc_np_set_timeout(void *priv, unsigned int timeout)
-{
-       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 = rpc_np_is_connected(np_transport);
-       if (!ok) {
-               return 0;
-       }
-
-       return cli_set_timeout(np_transport->cli, timeout);
-}
-
-static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s)
-{
-       if (!rpc_np_is_connected(s)) {
-               DEBUG(10, ("socket was closed, no need to send close request.\n"));
-               return 0;
-       }
-
-       /* TODO: do not use a sync call with a destructor!!! */
-       if (!NT_STATUS_IS_OK(cli_close(s->cli, s->fnum))) {
-               DEBUG(1, ("rpc_transport_np_state_destructor: cli_close "
-                         "failed on pipe %s. Error was %s\n", s->pipe_name,
-                         cli_errstr(s->cli)));
-       }
-       DEBUG(10, ("rpc_pipe_destructor: closed %s\n", s->pipe_name));
-       /*
-        * We can't do much on failure
-        */
-       return 0;
-}
-
-struct rpc_np_write_state {
-       struct rpc_transport_np_state *np_transport;
-       size_t size;
-       size_t written;
-};
-
-static void rpc_np_write_done(struct tevent_req *subreq);
-
-static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
-                                           struct event_context *ev,
-                                           const uint8_t *data, size_t size,
-                                           void *priv)
-{
-       struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
-               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. */
-                                    data, 0, size);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-       tevent_req_set_callback(subreq, rpc_np_write_done, req);
-       return req;
-}
-
-static void rpc_np_write_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct rpc_np_write_state *state = tevent_req_data(
-               req, struct rpc_np_write_state);
-       NTSTATUS status;
-
-       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;
-       }
-       tevent_req_done(req);
-}
-
-static NTSTATUS rpc_np_write_recv(struct tevent_req *req, ssize_t *pwritten)
-{
-       struct rpc_np_write_state *state = tevent_req_data(
-               req, struct rpc_np_write_state);
-       NTSTATUS status;
-
-       if (tevent_req_is_nterror(req, &status)) {
-               return status;
-       }
-       *pwritten = state->written;
-       return NT_STATUS_OK;
-}
-
-struct rpc_np_read_state {
-       struct rpc_transport_np_state *np_transport;
-       uint8_t *data;
-       size_t size;
-       ssize_t received;
-};
-
-static void rpc_np_read_done(struct tevent_req *subreq);
-
-static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
-                                          struct event_context *ev,
-                                          uint8_t *data, size_t size,
-                                          void *priv)
-{
-       struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
-               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;
-
-       subreq = cli_read_andx_send(mem_ctx, ev, np_transport->cli,
-                                   np_transport->fnum, 0, size);
-       if (subreq == NULL) {
-               goto fail;
-       }
-       tevent_req_set_callback(subreq, rpc_np_read_done, req);
-       return req;
- fail:
-       TALLOC_FREE(req);
-       return NULL;
-}
-
-static void rpc_np_read_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct rpc_np_read_state *state = tevent_req_data(
-               req, struct rpc_np_read_state);
-       NTSTATUS status;
-       uint8_t *rcvbuf;
-
-       /* We must free subreq in this function as there is
-          a timer event attached to it. */
-
-       status = cli_read_andx_recv(subreq, &state->received, &rcvbuf);
-       /*
-        * We can't TALLOC_FREE(subreq) as usual here, as rcvbuf still is a
-        * child of that.
-        */
-       if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
-               status = NT_STATUS_OK;
-       }
-       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;
-       }
-
-       memcpy(state->data, rcvbuf, state->received);
-       TALLOC_FREE(subreq);
-       tevent_req_done(req);
-}
-
-static NTSTATUS rpc_np_read_recv(struct tevent_req *req, ssize_t *preceived)
-{
-       struct rpc_np_read_state *state = tevent_req_data(
-               req, struct rpc_np_read_state);
-       NTSTATUS status;
-
-       if (tevent_req_is_nterror(req, &status)) {
-               return status;
-       }
-       *preceived = state->received;
-       return NT_STATUS_OK;
-}
-
-struct rpc_np_trans_state {
-       struct rpc_transport_np_state *np_transport;
-       uint16_t setup[2];
-       uint32_t max_rdata_len;
-       uint8_t *rdata;
-       uint32_t rdata_len;
-};
-
-static void rpc_np_trans_done(struct tevent_req *subreq);
-
-static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
-                                           struct event_context *ev,
-                                           uint8_t *data, size_t data_len,
-                                           uint32_t max_rdata_len,
-                                           void *priv)
-{
-       struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
-               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);
-       SSVAL(state->setup+1, 0, np_transport->fnum);
-
-       subreq = cli_trans_send(
-               state, ev, np_transport->cli, SMBtrans,
-               "\\PIPE\\", 0, 0, 0, state->setup, 2, 0,
-               NULL, 0, 0, data, data_len, max_rdata_len);
-       if (subreq == NULL) {
-               goto fail;
-       }
-       tevent_req_set_callback(subreq, rpc_np_trans_done, req);
-       return req;
-
- fail:
-       TALLOC_FREE(req);
-       return NULL;
-}
-
-static void rpc_np_trans_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct rpc_np_trans_state *state = tevent_req_data(
-               req, struct rpc_np_trans_state);
-       NTSTATUS status;
-
-       status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
-                               NULL, 0, NULL,
-                               &state->rdata, 0, &state->rdata_len);
-       TALLOC_FREE(subreq);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
-               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;
-       }
-
-       tevent_req_done(req);
-}
-
-static NTSTATUS rpc_np_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-                                 uint8_t **prdata, uint32_t *prdata_len)
-{
-       struct rpc_np_trans_state *state = tevent_req_data(
-               req, struct rpc_np_trans_state);
-       NTSTATUS status;
-
-       if (tevent_req_is_nterror(req, &status)) {
-               return status;
-       }
-       *prdata = talloc_move(mem_ctx, &state->rdata);
-       *prdata_len = state->rdata_len;
-       return NT_STATUS_OK;
-}
-
 struct rpc_transport_np_init_state {
        struct rpc_cli_transport *transport;
-       struct rpc_transport_np_state *transport_np;
 };
 
 static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq);
@@ -384,9 +34,10 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
                                              struct cli_state *cli,
                                              const struct ndr_syntax_id *abstract_syntax)
 {
-       struct tevent_req *req, *subreq;
+       struct tevent_req *req;
        struct rpc_transport_np_init_state *state;
-       bool ok;
+       const char *pipe_name;
+       struct tevent_req *subreq;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct rpc_transport_np_init_state);
@@ -394,36 +45,17 @@ 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);
-       }
-       state->transport_np = talloc(state->transport,
-                                    struct rpc_transport_np_state);
-       if (tevent_req_nomem(state->transport_np, req)) {
+       pipe_name = get_pipe_name_from_syntax(state, abstract_syntax);
+       if (tevent_req_nomem(pipe_name, req)) {
                return tevent_req_post(req, ev);
        }
-       state->transport->priv = state->transport_np;
 
-       state->transport_np->pipe_name = get_pipe_name_from_syntax(
-               state->transport_np, abstract_syntax);
-       state->transport_np->cli = cli;
-
-       subreq = cli_ntcreate_send(
-               state, ev, cli, state->transport_np->pipe_name, 0,
-               DESIRED_ACCESS_PIPE, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
-               FILE_OPEN, 0, 0);
+       subreq = tstream_cli_np_open_send(state, ev, cli, pipe_name);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open,
-                               req);
+       tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, req);
+
        return req;
 }
 
@@ -434,16 +66,23 @@ static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq)
        struct rpc_transport_np_init_state *state = tevent_req_data(
                req, struct rpc_transport_np_init_state);
        NTSTATUS status;
+       struct tstream_context *stream;
 
-       status = cli_ntcreate_recv(subreq, &state->transport_np->fnum);
+       status = tstream_cli_np_open_recv(subreq, state, &stream);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(req, status);
                return;
        }
 
-       talloc_set_destructor(state->transport_np,
-                             rpc_transport_np_state_destructor);
+       status = rpc_transport_tstream_init(state,
+                                           &stream,
+                                           &state->transport);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+
        tevent_req_done(req);
 }
 
@@ -459,15 +98,6 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req,
                return status;
        }
 
-       state->transport->write_send = rpc_np_write_send;
-       state->transport->write_recv = rpc_np_write_recv;
-       state->transport->read_send = rpc_np_read_send;
-       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;
-       state->transport->set_timeout = rpc_np_set_timeout;
-
        *presult = talloc_move(mem_ctx, &state->transport);
        return NT_STATUS_OK;
 }
@@ -503,14 +133,3 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
        TALLOC_FREE(frame);
        return status;
 }
-
-struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
-{
-       struct rpc_transport_np_state *state = talloc_get_type(
-               p->transport->priv, struct rpc_transport_np_state);
-
-       if (state == NULL) {
-               return NULL;
-       }
-       return state->cli;
-}