s4:libcli/smb2: convert smb2_connect_*() to tevent_req
authorStefan Metzmacher <metze@samba.org>
Wed, 27 Apr 2011 06:57:41 +0000 (08:57 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 28 Apr 2011 18:35:49 +0000 (20:35 +0200)
metze

source4/libcli/smb2/connect.c
source4/libcli/smb2/wscript_build
source4/librpc/rpc/dcerpc_connect.c

index 64ed6c3acce0ffe4a970ac1b5be6adcf8e67946f..85624019d1e7e593598eff44fde5d571457d49dd 100644 (file)
@@ -20,6 +20,8 @@
 */
 
 #include "includes.h"
+#include <tevent.h>
+#include "lib/util/tevent_ntstatus.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
 #include "libcli/smb2/smb2.h"
@@ -29,6 +31,7 @@
 #include "param/param.h"
 
 struct smb2_connect_state {
+       struct tevent_context *ev;
        struct cli_credentials *credentials;
        struct resolve_context *resolve_ctx;
        const char *host;
@@ -46,19 +49,24 @@ struct smb2_connect_state {
 /*
   continue after tcon reply
 */
-static void continue_tcon(struct smb2_request *req)
+static void continue_tcon(struct smb2_request *smb2req)
 {
-       struct composite_context *c = talloc_get_type(req->async.private_data, 
-                                                     struct composite_context);
-       struct smb2_connect_state *state = talloc_get_type(c->private_data, 
-                                                          struct smb2_connect_state);
-
-       c->status = smb2_tree_connect_recv(req, &state->tcon);
-       if (!composite_is_ok(c)) return;
-       
+       struct tevent_req *req =
+               talloc_get_type_abort(smb2req->async.private_data,
+               struct tevent_req);
+       struct smb2_connect_state *state =
+               tevent_req_data(req,
+               struct smb2_connect_state);
+       NTSTATUS status;
+
+       status = smb2_tree_connect_recv(smb2req, &state->tcon);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
        state->tree->tid = state->tcon.out.tid;
 
-       composite_done(c);
+       tevent_req_done(req);
 }
 
 /*
@@ -66,44 +74,59 @@ static void continue_tcon(struct smb2_request *req)
 */
 static void continue_session(struct composite_context *creq)
 {
-       struct composite_context *c = talloc_get_type(creq->async.private_data, 
-                                                     struct composite_context);
-       struct smb2_connect_state *state = talloc_get_type(c->private_data, 
-                                                          struct smb2_connect_state);
-       struct smb2_request *req;
+       struct tevent_req *req =
+               talloc_get_type_abort(creq->async.private_data,
+               struct tevent_req);
+       struct smb2_connect_state *state =
+               tevent_req_data(req,
+               struct smb2_connect_state);
+       struct smb2_request *smb2req;
+       NTSTATUS status;
 
-       c->status = smb2_session_setup_spnego_recv(creq);
-       if (!composite_is_ok(c)) return;
+       status = smb2_session_setup_spnego_recv(creq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
 
        state->tree = smb2_tree_init(state->session, state, true);
-       if (composite_nomem(state->tree, c)) return;
+       if (tevent_req_nomem(state->tree, req)) {
+               return;
+       }
 
        state->tcon.in.reserved = 0;
        state->tcon.in.path     = talloc_asprintf(state, "\\\\%s\\%s", 
                                                  state->host, state->share);
-       if (composite_nomem(state->tcon.in.path, c)) return;
-       
-       req = smb2_tree_connect_send(state->tree, &state->tcon);
-       if (composite_nomem(req, c)) return;
+       if (tevent_req_nomem(state->tcon.in.path, req)) {
+               return;
+       }
 
-       req->async.fn = continue_tcon;
-       req->async.private_data = c;    
+       smb2req = smb2_tree_connect_send(state->tree, &state->tcon);
+       if (tevent_req_nomem(smb2req, req)) {
+               return;
+       }
+       smb2req->async.fn = continue_tcon;
+       smb2req->async.private_data = req;
 }
 
 /*
   continue after negprot reply
 */
-static void continue_negprot(struct smb2_request *req)
+static void continue_negprot(struct smb2_request *smb2req)
 {
-       struct composite_context *c = talloc_get_type(req->async.private_data, 
-                                                     struct composite_context);
-       struct smb2_connect_state *state = talloc_get_type(c->private_data, 
-                                                          struct smb2_connect_state);
-       struct smb2_transport *transport = req->transport;
+       struct tevent_req *req =
+               talloc_get_type_abort(smb2req->async.private_data,
+               struct tevent_req);
+       struct smb2_connect_state *state =
+               tevent_req_data(req,
+               struct smb2_connect_state);
+       struct smb2_transport *transport = smb2req->transport;
        struct composite_context *creq;
+       NTSTATUS status;
 
-       c->status = smb2_negprot_recv(req, c, &state->negprot);
-       if (!composite_is_ok(c)) return;
+       status = smb2_negprot_recv(smb2req, state, &state->negprot);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
 
        transport->negotiate.secblob = state->negprot.out.secblob;
        talloc_steal(transport, transport->negotiate.secblob.data);
@@ -115,7 +138,7 @@ static void continue_negprot(struct smb2_request *req)
        switch (transport->options.signing) {
        case SMB_SIGNING_OFF:
                if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
-                       composite_error(c, NT_STATUS_ACCESS_DENIED);
+                       tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
                        return;
                }
                transport->signing_required = false;
@@ -138,18 +161,23 @@ static void continue_negprot(struct smb2_request *req)
                if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
                        transport->signing_required = true;
                } else {
-                       composite_error(c, NT_STATUS_ACCESS_DENIED);
+                       tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
                        return;
                }
                break;
        }
 
        state->session = smb2_session_init(transport, state->gensec_settings, state, true);
-       if (composite_nomem(state->session, c)) return;
+       if (tevent_req_nomem(state->session, req)) {
+               return;
+       }
 
        creq = smb2_session_setup_spnego_send(state->session, state->credentials);
-
-       composite_continue(c, creq, continue_session, c);
+       if (tevent_req_nomem(creq, req)) {
+               return;
+       }
+       creq->async.fn = continue_session;
+       creq->async.private_data = req;
 }
 
 /*
@@ -157,27 +185,34 @@ static void continue_negprot(struct smb2_request *req)
 */
 static void continue_socket(struct composite_context *creq)
 {
-       struct composite_context *c = talloc_get_type(creq->async.private_data, 
-                                                     struct composite_context);
-       struct smb2_connect_state *state = talloc_get_type(c->private_data, 
-                                                          struct smb2_connect_state);
+       struct tevent_req *req =
+               talloc_get_type_abort(creq->async.private_data,
+               struct tevent_req);
+       struct smb2_connect_state *state =
+               tevent_req_data(req,
+               struct smb2_connect_state);
        struct smbcli_socket *sock;
        struct smb2_transport *transport;
-       struct smb2_request *req;
+       struct smb2_request *smb2req;
+       NTSTATUS status;
        uint16_t dialects[3] = {
                SMB2_DIALECT_REVISION_000,
                SMB2_DIALECT_REVISION_202,
                SMB2_DIALECT_REVISION_210
        };
 
-       c->status = smbcli_sock_connect_recv(creq, state, &sock);
-       if (!composite_is_ok(c)) return;
+       status = smbcli_sock_connect_recv(creq, state, &sock);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
 
        transport = smb2_transport_init(sock, state, &state->options);
-       if (composite_nomem(transport, c)) return;
+       if (tevent_req_nomem(transport, req)) {
+               return;
+       }
 
        ZERO_STRUCT(state->negprot);
-       state->negprot.in.dialect_count = sizeof(dialects) / sizeof(dialects[0]);
+       state->negprot.in.dialect_count = ARRAY_SIZE(dialects);
        switch (transport->options.signing) {
        case SMB_SIGNING_OFF:
                state->negprot.in.security_mode = 0;
@@ -195,11 +230,12 @@ static void continue_socket(struct composite_context *creq)
        unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
        state->negprot.in.dialects = dialects;
 
-       req = smb2_negprot_send(transport, &state->negprot);
-       if (composite_nomem(req, c)) return;
-
-       req->async.fn = continue_negprot;
-       req->async.private_data = c;
+       smb2req = smb2_negprot_send(transport, &state->negprot);
+       if (tevent_req_nomem(smb2req, req)) {
+               return;
+       }
+       smb2req->async.fn = continue_negprot;
+       smb2req->async.private_data = req;
 }
 
 
@@ -208,16 +244,21 @@ static void continue_socket(struct composite_context *creq)
 */
 static void continue_resolve(struct composite_context *creq)
 {
-       struct composite_context *c = talloc_get_type(creq->async.private_data, 
-                                                     struct composite_context);
-       struct smb2_connect_state *state = talloc_get_type(c->private_data, 
-                                                          struct smb2_connect_state);
+       struct tevent_req *req =
+               talloc_get_type_abort(creq->async.private_data,
+               struct tevent_req);
+       struct smb2_connect_state *state =
+               tevent_req_data(req,
+               struct smb2_connect_state);
+       NTSTATUS status;
        const char *addr;
        const char **ports;
        const char *default_ports[] = { "445", NULL };
 
-       c->status = resolve_name_recv(creq, state, &addr);
-       if (!composite_is_ok(c)) return;
+       status = resolve_name_recv(creq, state, &addr);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
 
        if (state->ports == NULL) {
                ports = default_ports;
@@ -225,92 +266,140 @@ static void continue_resolve(struct composite_context *creq)
                ports = state->ports;
        }
 
-       creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx, state->socket_options);
-
-       composite_continue(c, creq, continue_socket, c);
+       creq = smbcli_sock_connect_send(state, addr, ports,
+                                       state->host, state->resolve_ctx,
+                                       state->ev, state->socket_options);
+       if (tevent_req_nomem(creq, req)) {
+               return;
+       }
+       creq->async.fn = continue_socket;
+       creq->async.private_data = req;
 }
 
 /*
   a composite function that does a full negprot/sesssetup/tcon, returning
   a connected smb2_tree
  */
-struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx,
-                                           const char *host,
-                                               const char **ports,
-                                           const char *share,
-                                           struct resolve_context *resolve_ctx,
-                                           struct cli_credentials *credentials,
-                                           struct tevent_context *ev,
-                                           struct smbcli_options *options,
-                                               const char *socket_options,
-                                               struct gensec_settings *gensec_settings)
+struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    const char *host,
+                                    const char **ports,
+                                    const char *share,
+                                    struct resolve_context *resolve_ctx,
+                                    struct cli_credentials *credentials,
+                                    struct smbcli_options *options,
+                                    const char *socket_options,
+                                    struct gensec_settings *gensec_settings)
 {
-       struct composite_context *c;
+       struct tevent_req *req;
        struct smb2_connect_state *state;
        struct nbt_name name;
        struct composite_context *creq;
 
-       c = composite_create(mem_ctx, ev);
-       if (c == NULL) return NULL;
-
-       state = talloc(c, struct smb2_connect_state);
-       if (composite_nomem(state, c)) return c;
-       c->private_data = state;
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smb2_connect_state);
+       if (req == NULL) {
+               return NULL;
+       }
 
+       state->ev = ev;
        state->credentials = credentials;
        state->options = *options;
-       state->host = talloc_strdup(c, host);
-       if (composite_nomem(state->host, c)) return c;
-       state->ports = talloc_reference(state, ports);
-       state->share = talloc_strdup(c, share);
-       if (composite_nomem(state->share, c)) return c;
-       state->resolve_ctx = talloc_reference(state, resolve_ctx);
-       state->socket_options = talloc_reference(state, socket_options);
-       state->gensec_settings = talloc_reference(state, gensec_settings);
+       state->host = host;
+       state->ports = ports;
+       state->share = share;
+       state->resolve_ctx = resolve_ctx;
+       state->socket_options = socket_options;
+       state->gensec_settings = gensec_settings;
 
        ZERO_STRUCT(name);
        name.name = host;
 
-       creq = resolve_name_send(resolve_ctx, state, &name, c->event_ctx);
-       composite_continue(c, creq, continue_resolve, c);
-       return c;
+       creq = resolve_name_send(resolve_ctx, state, &name, ev);
+       if (tevent_req_nomem(creq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       creq->async.fn = continue_resolve;
+       creq->async.private_data = req;
+       return req;
 }
 
 /*
   receive a connect reply
 */
-NTSTATUS smb2_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
+NTSTATUS smb2_connect_recv(struct tevent_req *req,
+                          TALLOC_CTX *mem_ctx,
                           struct smb2_tree **tree)
 {
+       struct smb2_connect_state *state =
+               tevent_req_data(req,
+               struct smb2_connect_state);
        NTSTATUS status;
-       struct smb2_connect_state *state = talloc_get_type(c->private_data, 
-                                                          struct smb2_connect_state);
-       status = composite_wait(c);
-       if (NT_STATUS_IS_OK(status)) {
-               *tree = talloc_steal(mem_ctx, state->tree);
+
+       if (tevent_req_is_nterror(req, &status)) {
+               tevent_req_received(req);
+               return status;
        }
-       talloc_free(c);
-       return status;
+
+       *tree = talloc_move(mem_ctx, &state->tree);
+
+       tevent_req_received(req);
+       return NT_STATUS_OK;
 }
 
 /*
   sync version of smb2_connect
 */
-NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, 
-                     const char *host, const char **ports, 
-                         const char *share,
+NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx,
+                     const char *host,
+                     const char **ports,
+                     const char *share,
                      struct resolve_context *resolve_ctx,
                      struct cli_credentials *credentials,
                      struct smb2_tree **tree,
                      struct tevent_context *ev,
                      struct smbcli_options *options,
-                         const char *socket_options,
-                         struct gensec_settings *gensec_settings)
+                     const char *socket_options,
+                     struct gensec_settings *gensec_settings)
 {
-       struct composite_context *c = smb2_connect_send(mem_ctx, host, ports, 
-                                                                                                       share, resolve_ctx, 
-                                                                                                       credentials, ev, options,
-                                                                                                       socket_options,
-                                                                                                       gensec_settings);
-       return smb2_connect_recv(c, mem_ctx, tree);
+       struct tevent_req *subreq;
+       NTSTATUS status;
+       bool ok;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       if (frame == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       subreq = smb2_connect_send(frame,
+                                  ev,
+                                  host,
+                                  ports,
+                                  share,
+                                  resolve_ctx,
+                                  credentials,
+                                  options,
+                                  socket_options,
+                                  gensec_settings);
+       if (subreq == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ok = tevent_req_poll(subreq, ev);
+       if (!ok) {
+               status = map_nt_error_from_unix(errno);
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       status = smb2_connect_recv(subreq, mem_ctx, tree);
+       TALLOC_FREE(subreq);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       TALLOC_FREE(frame);
+       return NT_STATUS_OK;
 }
index c39cf5fd39ae0b583596c9bd410081003190cf55..5b5ac7d4e68609f49de3b57fc3326c022a5a9402 100644 (file)
@@ -3,6 +3,7 @@
 bld.SAMBA_SUBSYSTEM('LIBCLI_SMB2',
        source='transport.c request.c negprot.c session.c tcon.c create.c close.c connect.c getinfo.c write.c read.c setinfo.c find.c ioctl.c logoff.c tdis.c flush.c lock.c notify.c cancel.c keepalive.c break.c util.c signing.c lease_break.c',
        autoproto='smb2_proto.h',
-       public_deps='LIBCLI_RAW LIBPACKET gensec'
+       deps='UTIL_TEVENT',
+       public_deps='LIBCLI_RAW LIBPACKET gensec tevent'
        )
 
index 842ef4320631013dc7c0c0702c4aab158323e3ff..c236399b52940d8c24eb62ffb3ec4fecd78daf80 100644 (file)
@@ -186,16 +186,18 @@ static void continue_pipe_open_smb2(struct composite_context *ctx)
 /*
   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
 */
-static void continue_smb2_connect(struct composite_context *ctx)
+static void continue_smb2_connect(struct tevent_req *subreq)
 {
        struct composite_context *open_req;
-       struct composite_context *c = talloc_get_type(ctx->async.private_data,
-                                                     struct composite_context);
+       struct composite_context *c =
+               tevent_req_callback_data(subreq,
+               struct composite_context);
        struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
                                                       struct pipe_np_smb2_state);
 
        /* receive result of smb2 connect request */
-       c->status = smb2_connect_recv(ctx, c, &s->tree);
+       c->status = smb2_connect_recv(subreq, c, &s->tree);
+       TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
        /* prepare named pipe open parameters */
@@ -220,7 +222,7 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
 {
        struct composite_context *c;
        struct pipe_np_smb2_state *s;
-       struct composite_context *conn_req;
+       struct tevent_req *subreq;
        struct smbcli_options options;
 
        /* composite context allocation and setup */
@@ -247,17 +249,17 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
        lpcfg_smbcli_options(lp_ctx, &options);
 
        /* send smb2 connect request */
-       conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, 
+       subreq = smb2_connect_send(s, c->event_ctx,
+                       s->io.binding->host,
                        lpcfg_parm_string_list(mem_ctx, lp_ctx, NULL, "smb2", "ports", NULL),
-                                       "IPC$", 
-                                    s->io.resolve_ctx,
-                                    s->io.creds,
-                                    c->event_ctx,
-                                    &options,
-                                        lpcfg_socket_options(lp_ctx),
-                                        lpcfg_gensec_settings(mem_ctx, lp_ctx)
-                                        );
-       composite_continue(c, conn_req, continue_smb2_connect, c);
+                       "IPC$",
+                       s->io.resolve_ctx,
+                       s->io.creds,
+                       &options,
+                       lpcfg_socket_options(lp_ctx),
+                       lpcfg_gensec_settings(mem_ctx, lp_ctx));
+       if (composite_nomem(subreq, c)) return c;
+       tevent_req_set_callback(subreq, continue_smb2_connect, c);
        return c;
 }