s4:libnet/libnet_rpc.c - quiet an enum warning
[samba.git] / source4 / libnet / libnet_rpc.c
index 8b3e7bae3c1f1c274aa69891eaec8cfe398fa213..8aacfc398a1d9c7be7f89d3f5ec59931b9bb5a67 100644 (file)
@@ -6,7 +6,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "libnet/libnet.h"
 #include "libcli/libcli.h"
 #include "libcli/composite/composite.h"
-#include "librpc/rpc/dcerpc.h"
+#include "librpc/rpc/dcerpc_proto.h"
 #include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "librpc/gen_ndr/ndr_samr.h"
 
@@ -32,6 +31,9 @@ struct rpc_connect_srv_state {
        struct libnet_context *ctx;
        struct libnet_RpcConnect r;
        const char *binding;
+
+       /* information about the progress */
+       void (*monitor_fn)(struct monitor_msg*);
 };
 
 
@@ -49,7 +51,8 @@ static void continue_pipe_connect(struct composite_context *ctx);
 
 static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx,
                                                           TALLOC_CTX *mem_ctx,
-                                                          struct libnet_RpcConnect *r)
+                                                          struct libnet_RpcConnect *r,
+                                                          void (*monitor)(struct monitor_msg*))
 {
        struct composite_context *c;    
        struct rpc_connect_srv_state *s;
@@ -57,15 +60,14 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
        struct composite_context *pipe_connect_req;
 
        /* composite context allocation and setup */
-       c = talloc_zero(mem_ctx, struct composite_context);
-       if (c == NULL) return NULL;
+       c = composite_create(ctx, ctx->event_ctx);
+       if (c == NULL) return c;
 
        s = talloc_zero(c, struct rpc_connect_srv_state);
        if (composite_nomem(s, c)) return c;
 
-       c->state = COMPOSITE_STATE_IN_PROGRESS;
        c->private_data = s;
-       c->event_ctx = ctx->event_ctx;
+       s->monitor_fn   = monitor;
 
        s->ctx = ctx;
        s->r = *r;
@@ -103,8 +105,22 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
                return c;
        }
 
+       switch (r->level) {
+       case LIBNET_RPC_CONNECT_SERVER:
+       case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
+               b->flags = r->in.dcerpc_flags;
+               break;
+       default:
+               /* other types have already been checked before */
+               break;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               b->flags |= DCERPC_DEBUG_PRINT_BOTH;
+       }
+
        if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
-               b->target_hostname = talloc_reference(b, r->in.name);
+               b->target_hostname = talloc_strdup(b, r->in.name);
                if (composite_nomem(b->target_hostname, c)) {
                        return c;
                }
@@ -112,7 +128,8 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
 
        /* connect to remote dcerpc pipe */
        pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
-                                                     ctx->cred, c->event_ctx);
+                                                     ctx->cred, c->event_ctx,
+                                                     ctx->lp_ctx);
        if (composite_nomem(pipe_connect_req, c)) return c;
 
        composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
@@ -133,8 +150,26 @@ static void continue_pipe_connect(struct composite_context *ctx)
 
        /* receive result of rpc pipe connection */
        c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
+       
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+               struct msg_net_rpc_connect data;
+               struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
+               
+               /* prepare monitor message and post it */
+               data.host        = binding->host;
+               data.endpoint    = binding->endpoint;
+               data.transport   = binding->transport;
+               data.domain_name = binding->target_hostname;
+               
+               msg.type      = mon_NetRpcConnect;
+               msg.data      = (void*)&data;
+               msg.data_size = sizeof(data);
+               s->monitor_fn(&msg);
+       }
 
-       composite_done(c);
+       composite_done(c);      
 }
 
 
@@ -166,10 +201,10 @@ static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c,
                /* reference created pipe structure to long-term libnet_context
                   so that it can be used by other api functions even after short-term
                   mem_ctx is freed */
-               if (r->in.dcerpc_iface == &dcerpc_table_samr) {
+               if (r->in.dcerpc_iface == &ndr_table_samr) {
                        ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 
-               } else if (r->in.dcerpc_iface == &dcerpc_table_lsarpc) {
+               } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
                        ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
                }
 
@@ -196,7 +231,7 @@ struct rpc_connect_dc_state {
 };
 
 
-static void continue_lookup_dc(struct composite_context *ctx);
+static void continue_lookup_dc(struct tevent_req *req);
 static void continue_rpc_connect(struct composite_context *ctx);
 
 
@@ -211,22 +246,22 @@ static void continue_rpc_connect(struct composite_context *ctx);
 
 static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx,
                                                          TALLOC_CTX *mem_ctx,
-                                                         struct libnet_RpcConnect *r)
+                                                         struct libnet_RpcConnect *r,
+                                                         void (*monitor)(struct monitor_msg *msg))
 {
        struct composite_context *c;
        struct rpc_connect_dc_state *s;
-       struct composite_context *lookup_dc_req;
+       struct tevent_req *lookup_dc_req;
 
        /* composite context allocation and setup */
-       c = talloc_zero(mem_ctx, struct composite_context);
-       if (c == NULL) return NULL;
+       c = composite_create(ctx, ctx->event_ctx);
+       if (c == NULL) return c;
 
        s = talloc_zero(c, struct rpc_connect_dc_state);
        if (composite_nomem(s, c)) return c;
 
-       c->state = COMPOSITE_STATE_IN_PROGRESS;
        c->private_data = s;
-       c->event_ctx = ctx->event_ctx;
+       s->monitor_fn   = monitor;
 
        s->ctx = ctx;
        s->r   = *r;
@@ -253,7 +288,7 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
        lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
        if (composite_nomem(lookup_dc_req, c)) return c;
 
-       composite_continue(c, lookup_dc_req, continue_lookup_dc, c);
+       tevent_req_set_callback(lookup_dc_req, continue_lookup_dc, c);
        return c;
 }
 
@@ -262,34 +297,36 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
   Step 2 of RpcConnectDC: get domain controller name and
   initiate RpcConnect to it
 */
-static void continue_lookup_dc(struct composite_context *ctx)
+static void continue_lookup_dc(struct tevent_req *req)
 {
        struct composite_context *c;
        struct rpc_connect_dc_state *s;
        struct composite_context *rpc_connect_req;
        struct monitor_msg msg;
        struct msg_net_lookup_dc data;
-       
-       c = talloc_get_type(ctx->async.private_data, struct composite_context);
-       s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
+
+       c = tevent_req_callback_data(req, struct composite_context);
+       s = talloc_get_type_abort(c->private_data, struct rpc_connect_dc_state);
        
        /* receive result of domain controller lookup */
-       c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
+       c->status = libnet_LookupDCs_recv(req, c, &s->f);
        if (!composite_is_ok(c)) return;
 
        /* decide on preferred address type depending on DC type */
        s->connect_name = s->f.out.dcs[0].name;
 
-       /* prepare a monitor message and post it */
-       msg.type         = net_lookup_dc;
-       msg.data         = &data;
-       msg.data_size    = sizeof(data);
-
-       data.domain_name = s->f.in.domain_name;
-       data.hostname    = s->f.out.dcs[0].name;
-       data.address     = s->f.out.dcs[0].address;
-       
-       if (s->monitor_fn) s->monitor_fn(&msg);
+       /* post monitor message */
+       if (s->monitor_fn) {
+               /* prepare a monitor message and post it */
+               data.domain_name = s->f.in.domain_name;
+               data.hostname    = s->f.out.dcs[0].name;
+               data.address     = s->f.out.dcs[0].address;
+               
+               msg.type         = mon_NetLookupDc;
+               msg.data         = &data;
+               msg.data_size    = sizeof(data);
+               s->monitor_fn(&msg);
+       }
 
        /* ok, pdc has been found so do attempt to rpc connect */
        s->r2.level            = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
@@ -299,9 +336,10 @@ static void continue_lookup_dc(struct composite_context *ctx)
        s->r2.in.name          = talloc_strdup(s, s->connect_name);
        s->r2.in.address       = talloc_steal(s, s->f.out.dcs[0].address);
        s->r2.in.dcerpc_iface  = s->r.in.dcerpc_iface;  
+       s->r2.in.dcerpc_flags  = s->r.in.dcerpc_flags;
 
        /* send rpc connect request to the server */
-       rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2);
+       rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
        if (composite_nomem(rpc_connect_req, c)) return;
 
        composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
@@ -315,8 +353,6 @@ static void continue_rpc_connect(struct composite_context *ctx)
 {
        struct composite_context *c;
        struct rpc_connect_dc_state *s;
-       struct monitor_msg msg;
-       struct msg_net_pipe_connected data;
 
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
@@ -328,17 +364,23 @@ static void continue_rpc_connect(struct composite_context *ctx)
        if (!composite_is_ok(c)) return;
 
        s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
-
-       /* prepare a monitor message and post it */
-       msg.type       = net_pipe_connected;
-       msg.data       = NULL;
-       msg.data_size  = 0;
-
-       data.host      = s->r.out.dcerpc_pipe->binding->host;
-       data.endpoint  = s->r.out.dcerpc_pipe->binding->endpoint;
-       data.transport = s->r.out.dcerpc_pipe->binding->transport;
-
-       if (s->monitor_fn) s->monitor_fn(&msg);
+       
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+               struct msg_net_rpc_connect data;
+               struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
+
+               data.host        = binding->host;
+               data.endpoint    = binding->endpoint;
+               data.transport   = binding->transport;
+               data.domain_name = binding->target_hostname;
+               
+               msg.type      = mon_NetRpcConnect;
+               msg.data      = (void*)&data;
+               msg.data_size = sizeof(data);
+               s->monitor_fn(&msg);
+       }
 
        composite_done(c);
 }
@@ -365,16 +407,25 @@ static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
 
        status = composite_wait(c);
        if (NT_STATUS_IS_OK(status)) {
-               /* move connected rpc pipe between memory contexts */
-               r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
+               /* move connected rpc pipe between memory contexts 
+                  
+                  The use of talloc_reparent(talloc_parent(), ...) is
+                  bizarre, but it is needed because of the absolutely
+                  atrocious use of talloc in this code. We need to
+                  force the original parent to change, but finding
+                  the original parent is well nigh impossible at this
+                  point in the code (yes, I tried).
+                */
+               r->out.dcerpc_pipe = talloc_reparent(talloc_parent(s->r.out.dcerpc_pipe), 
+                                                    mem_ctx, s->r.out.dcerpc_pipe);
 
                /* reference created pipe structure to long-term libnet_context
                   so that it can be used by other api functions even after short-term
                   mem_ctx is freed */
-               if (r->in.dcerpc_iface == &dcerpc_table_samr) {
+               if (r->in.dcerpc_iface == &ndr_table_samr) {
                        ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 
-               } else if (r->in.dcerpc_iface == &dcerpc_table_lsarpc) {
+               } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
                        ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
                }
 
@@ -403,13 +454,16 @@ struct rpc_connect_dci_state {
        struct lsa_QueryInfoPolicy lsa_query_info;
        struct dcerpc_binding *final_binding;
        struct dcerpc_pipe *final_pipe;
+
+       /* information about the progress */
+       void (*monitor_fn)(struct monitor_msg*);
 };
 
 
 static void continue_dci_rpc_connect(struct composite_context *ctx);
-static void continue_lsa_policy(struct rpc_request *req);
-static void continue_lsa_query_info(struct rpc_request *req);
-static void continue_lsa_query_info2(struct rpc_request *req);
+static void continue_lsa_policy(struct tevent_req *subreq);
+static void continue_lsa_query_info(struct tevent_req *subreq);
+static void continue_lsa_query_info2(struct tevent_req *subreq);
 static void continue_epm_map_binding(struct composite_context *ctx);
 static void continue_secondary_conn(struct composite_context *ctx);
 static void continue_epm_map_binding_send(struct composite_context *c);
@@ -427,41 +481,45 @@ static void continue_epm_map_binding_send(struct composite_context *c);
 
 static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx,
                                                              TALLOC_CTX *mem_ctx,
-                                                             struct libnet_RpcConnect *r)
+                                                             struct libnet_RpcConnect *r,
+                                                             void (*monitor)(struct monitor_msg*))
 {
        struct composite_context *c, *conn_req;
        struct rpc_connect_dci_state *s;
 
        /* composite context allocation and setup */
-       c = talloc_zero(mem_ctx, struct composite_context);
-       if (c == NULL) return NULL;
+       c = composite_create(ctx, ctx->event_ctx);
+       if (c == NULL) return c;
 
        s = talloc_zero(c, struct rpc_connect_dci_state);
        if (composite_nomem(s, c)) return c;
 
-       c->state = COMPOSITE_STATE_IN_PROGRESS;
        c->private_data = s;
-       c->event_ctx = ctx->event_ctx;
+       s->monitor_fn   = monitor;
 
        s->ctx = ctx;
        s->r   = *r;
        ZERO_STRUCT(s->r.out);
 
+
        /* proceed to pure rpc connection if the binding string is provided,
           otherwise try to connect domain controller */
        if (r->in.binding == NULL) {
-               s->rpc_conn.in.name    = r->in.name;
-               s->rpc_conn.level      = LIBNET_RPC_CONNECT_DC;
+               /* Pass on any binding flags (such as anonymous fallback) that have been set */
+               s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags;
+
+               s->rpc_conn.in.name         = r->in.name;
+               s->rpc_conn.level           = LIBNET_RPC_CONNECT_DC;
        } else {
-               s->rpc_conn.in.binding = r->in.binding;
-               s->rpc_conn.level      = LIBNET_RPC_CONNECT_BINDING;
+               s->rpc_conn.in.binding      = r->in.binding;
+               s->rpc_conn.level           = LIBNET_RPC_CONNECT_BINDING;
        }
 
        /* we need to query information on lsarpc interface first */
-       s->rpc_conn.in.dcerpc_iface    = &dcerpc_table_lsarpc;
+       s->rpc_conn.in.dcerpc_iface    = &ndr_table_lsarpc;
        
        /* request connection to the lsa pipe on the pdc */
-       conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn);
+       conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn);
        if (composite_nomem(c, conn_req)) return c;
 
        composite_continue(c, conn_req, continue_dci_rpc_connect, c);
@@ -477,7 +535,7 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
 {
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
-       struct rpc_request *open_pol_req;
+       struct tevent_req *subreq;
 
        c = talloc_get_type(ctx->async.private_data, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
@@ -488,6 +546,23 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
                return;
        }
 
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+               struct msg_net_rpc_connect data;
+               struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
+
+               data.host        = binding->host;
+               data.endpoint    = binding->endpoint;
+               data.transport   = binding->transport;
+               data.domain_name = binding->target_hostname;
+
+               msg.type      = mon_NetRpcConnect;
+               msg.data      = (void*)&data;
+               msg.data_size = sizeof(data);
+               s->monitor_fn(&msg);
+       }
+
        /* prepare to open a policy handle on lsa pipe */
        s->lsa_pipe = s->ctx->lsa.pipe;
        
@@ -505,10 +580,12 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
        s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        s->lsa_open_policy.out.handle     = &s->lsa_handle;
 
-       open_pol_req = dcerpc_lsa_OpenPolicy2_send(s->lsa_pipe, c, &s->lsa_open_policy);
-       if (composite_nomem(open_pol_req, c)) return;
+       subreq = dcerpc_lsa_OpenPolicy2_r_send(s, c->event_ctx,
+                                              s->lsa_pipe->binding_handle,
+                                              &s->lsa_open_policy);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, open_pol_req, continue_lsa_policy, c);
+       tevent_req_set_callback(subreq, continue_lsa_policy, c);
 }
 
 
@@ -516,16 +593,16 @@ static void continue_dci_rpc_connect(struct composite_context *ctx)
   Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
   for kerberos realm (dns name) and guid. The query may fail.
 */
-static void continue_lsa_policy(struct rpc_request *req)
+static void continue_lsa_policy(struct tevent_req *subreq)
 {
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
-       struct rpc_request *query_info_req;
 
-       c = talloc_get_type(req->async.private, struct composite_context);
+       c = tevent_req_callback_data(subreq, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(c->status)) {
                composite_error(c, c->status);
                return;
@@ -536,22 +613,38 @@ static void continue_lsa_policy(struct rpc_request *req)
                s->r.out.guid  = NULL;
                s->r.out.domain_name = NULL;
                s->r.out.domain_sid  = NULL;
+
                /* Skip to the creating the actual connection, no info available on this transport */
                continue_epm_map_binding_send(c);
                return;
+
        } else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) {
                composite_error(c, s->lsa_open_policy.out.result);
                return;
        }
 
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+
+               msg.type      = mon_LsaOpenPolicy;
+               msg.data      = NULL;
+               msg.data_size = 0;
+               s->monitor_fn(&msg);
+       }
+
        /* query lsa info for dns domain name and guid */
        s->lsa_query_info2.in.handle = &s->lsa_handle;
        s->lsa_query_info2.in.level  = LSA_POLICY_INFO_DNS;
+       s->lsa_query_info2.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
+       if (composite_nomem(s->lsa_query_info2.out.info, c)) return;
 
-       query_info_req = dcerpc_lsa_QueryInfoPolicy2_send(s->lsa_pipe, c, &s->lsa_query_info2);
-       if (composite_nomem(query_info_req, c)) return;
+       subreq = dcerpc_lsa_QueryInfoPolicy2_r_send(s, c->event_ctx,
+                                                   s->lsa_pipe->binding_handle,
+                                                   &s->lsa_query_info2);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, query_info_req, continue_lsa_query_info2, c);
+       tevent_req_set_callback(subreq, continue_lsa_query_info2, c);
 }
 
 
@@ -559,22 +652,22 @@ static void continue_lsa_policy(struct rpc_request *req)
   Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
   may result in failure) and query lsa info for domain name and sid.
 */
-static void continue_lsa_query_info2(struct rpc_request *req)
+static void continue_lsa_query_info2(struct tevent_req *subreq)
 {      
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
-       struct rpc_request *query_info_req;
 
-       c = talloc_get_type(req->async.private, struct composite_context);
+       c = tevent_req_callback_data(subreq, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_QueryInfoPolicy2_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        
        /* In case of error just null the realm and guid and proceed
           to the next step. After all, it doesn't have to be AD domain
           controller we talking to - NT-style PDC also counts */
 
-       if (NT_STATUS_EQUAL(c->status, NT_STATUS_NET_WRITE_FAULT)) {
+       if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
                s->r.out.realm = NULL;
                s->r.out.guid  = NULL;
 
@@ -598,38 +691,53 @@ static void continue_lsa_query_info2(struct rpc_request *req)
                /* Copy the dns domain name and guid from the query result */
 
                /* this should actually be a conversion from lsa_StringLarge */
-               s->r.out.realm = s->lsa_query_info2.out.info->dns.dns_domain.string;
+               s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string;
                s->r.out.guid  = talloc(c, struct GUID);
                if (composite_nomem(s->r.out.guid, c)) {
                        s->r.out.error_string = NULL;
                        return;
                }
-               *s->r.out.guid = s->lsa_query_info2.out.info->dns.domain_guid;
+               *s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid;
+       }
+
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+               
+               msg.type      = mon_LsaQueryPolicy;
+               msg.data      = NULL;
+               msg.data_size = 0;
+               s->monitor_fn(&msg);
        }
 
        /* query lsa info for domain name and sid */
        s->lsa_query_info.in.handle = &s->lsa_handle;
        s->lsa_query_info.in.level  = LSA_POLICY_INFO_DOMAIN;
+       s->lsa_query_info.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
+       if (composite_nomem(s->lsa_query_info.out.info, c)) return;
 
-       query_info_req = dcerpc_lsa_QueryInfoPolicy_send(s->lsa_pipe, c, &s->lsa_query_info);
-       if (composite_nomem(query_info_req, c)) return;
+       subreq = dcerpc_lsa_QueryInfoPolicy_r_send(s, c->event_ctx,
+                                                  s->lsa_pipe->binding_handle,
+                                                  &s->lsa_query_info);
+       if (composite_nomem(subreq, c)) return;
 
-       composite_continue_rpc(c, query_info_req, continue_lsa_query_info, c);
+       tevent_req_set_callback(subreq, continue_lsa_query_info, c);
 }
 
 
 /*
   Step 5 of RpcConnectDCInfo: Get domain name and sid
 */
-static void continue_lsa_query_info(struct rpc_request *req)
+static void continue_lsa_query_info(struct tevent_req *subreq)
 {
        struct composite_context *c;
        struct rpc_connect_dci_state *s;
 
-       c = talloc_get_type(req->async.private, struct composite_context);
+       c = tevent_req_callback_data(subreq, struct composite_context);
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(c->status)) {
                s->r.out.error_string = talloc_asprintf(c,
                                                        "lsa_QueryInfoPolicy failed: %s",
@@ -638,9 +746,19 @@ static void continue_lsa_query_info(struct rpc_request *req)
                return;
        }
 
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+               
+               msg.type      = mon_LsaQueryPolicy;
+               msg.data      = NULL;
+               msg.data_size = 0;
+               s->monitor_fn(&msg);
+       }
+
        /* Copy the domain name and sid from the query result */
-       s->r.out.domain_sid  = s->lsa_query_info.out.info->domain.sid;
-       s->r.out.domain_name = s->lsa_query_info.out.info->domain.name.string;
+       s->r.out.domain_sid  = (*s->lsa_query_info.out.info)->domain.sid;
+       s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string;
 
        continue_epm_map_binding_send(c);
 }
@@ -649,7 +767,7 @@ static void continue_lsa_query_info(struct rpc_request *req)
    Step 5 (continued) of RpcConnectDCInfo: request endpoint
    map binding.
 
-   We may short-cut to this step if we dont' support LSA OpenPolicy on this transport
+   We may short-cut to this step if we don't support LSA OpenPolicy on this transport
 */
 static void continue_epm_map_binding_send(struct composite_context *c)
 {
@@ -658,7 +776,7 @@ static void continue_epm_map_binding_send(struct composite_context *c)
        s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 
        /* prepare to get endpoint mapping for the requested interface */
-       s->final_binding = talloc(s, struct dcerpc_binding);
+       s->final_binding = talloc_zero(s, struct dcerpc_binding);
        if (composite_nomem(s->final_binding, c)) return;
        
        *s->final_binding = *s->lsa_pipe->binding;
@@ -666,7 +784,7 @@ static void continue_epm_map_binding_send(struct composite_context *c)
        if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return;
 
        epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
-                                                 s->lsa_pipe->conn->event_ctx);
+                                                 s->lsa_pipe->conn->event_ctx, s->ctx->lp_ctx);
        if (composite_nomem(epm_map_req, c)) return;
 
        composite_continue(c, epm_map_req, continue_epm_map_binding, c);
@@ -725,6 +843,25 @@ static void continue_secondary_conn(struct composite_context *ctx)
        }
 
        s->r.out.dcerpc_pipe = s->final_pipe;
+
+       /* post monitor message */
+       if (s->monitor_fn) {
+               struct monitor_msg msg;
+               struct msg_net_rpc_connect data;
+               struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
+               
+               /* prepare monitor message and post it */
+               data.host        = binding->host;
+               data.endpoint    = binding->endpoint;
+               data.transport   = binding->transport;
+               data.domain_name = binding->target_hostname;
+               
+               msg.type      = mon_NetRpcConnect;
+               msg.data      = (void*)&data;
+               msg.data_size = sizeof(data);
+               s->monitor_fn(&msg);
+       }
+
        composite_done(c);
 }
 
@@ -759,18 +896,23 @@ static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct
                /* reference created pipe structure to long-term libnet_context
                   so that it can be used by other api functions even after short-term
                   mem_ctx is freed */
-               if (r->in.dcerpc_iface == &dcerpc_table_samr) {
+               if (r->in.dcerpc_iface == &ndr_table_samr) {
                        ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
+                       ctx->samr.samr_handle = ctx->samr.pipe->binding_handle;
 
-               } else if (r->in.dcerpc_iface == &dcerpc_table_lsarpc) {
+               } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
                        ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
+                       ctx->lsa.lsa_handle = ctx->lsa.pipe->binding_handle;
                }
 
        } else {
                if (s->r.out.error_string) {
                        r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
-               } else {
+               } else if (r->in.binding == NULL) {
                        r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
+               } else {
+                       r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s", 
+                                                             r->in.binding, nt_errstr(status));
                }
        }
 
@@ -791,7 +933,8 @@ static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct
 
 struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
                                                 TALLOC_CTX *mem_ctx,
-                                                struct libnet_RpcConnect *r)
+                                                struct libnet_RpcConnect *r,
+                                                void (*monitor)(struct monitor_msg*))
 {
        struct composite_context *c;
 
@@ -799,16 +942,16 @@ struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
        case LIBNET_RPC_CONNECT_SERVER:
        case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
        case LIBNET_RPC_CONNECT_BINDING:
-               c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r);
+               c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor);
                break;
 
        case LIBNET_RPC_CONNECT_PDC:
        case LIBNET_RPC_CONNECT_DC:
-               c = libnet_RpcConnectDC_send(ctx, mem_ctx, r);
+               c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor);
                break;
 
        case LIBNET_RPC_CONNECT_DC_INFO:
-               c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r);
+               c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor);
                break;
 
        default:
@@ -866,6 +1009,6 @@ NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 {
        struct composite_context *c;
        
-       c = libnet_RpcConnect_send(ctx, mem_ctx, r);
+       c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL);
        return libnet_RpcConnect_recv(c, ctx, mem_ctx, r);
 }