s4:cldap: rewrite the cldap library based on tsocket
authorStefan Metzmacher <metze@samba.org>
Fri, 13 Feb 2009 12:13:54 +0000 (13:13 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 19 Mar 2009 15:25:59 +0000 (16:25 +0100)
metze

12 files changed:
source4/cldap_server/cldap_server.c
source4/cldap_server/netlogon.c
source4/cldap_server/rootdse.c
source4/libcli/cldap/cldap.c
source4/libcli/cldap/cldap.h
source4/libcli/config.mk
source4/libnet/libnet_become_dc.c
source4/libnet/libnet_site.c
source4/libnet/libnet_unbecome_dc.c
source4/torture/ldap/cldap.c
source4/torture/ldap/cldapbench.c
source4/torture/rpc/dssync.c

index 240f2b1dc23d3cb5ba9ea5d94e2ed8d9ac3bf2db..1a08cd21f90d2b871d02a329710b419e0228075a 100644 (file)
@@ -20,8 +20,8 @@
 */
 
 #include "includes.h"
+#include <talloc.h>
 #include "libcli/ldap/ldap.h"
-#include "lib/socket/socket.h"
 #include "lib/messaging/irpc.h"
 #include "smbd/service_task.h"
 #include "smbd/service.h"
 #include "ldb_wrap.h"
 #include "auth/auth.h"
 #include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
 
 /*
   handle incoming cldap requests
 */
-static void cldapd_request_handler(struct cldap_socket *cldap, 
-                                  struct ldap_message *ldap_msg, 
-                                  struct socket_address *src)
+static void cldapd_request_handler(struct cldap_socket *cldap,
+                                  void *private_data,
+                                  struct cldap_incoming *in)
 {
+       struct cldapd_server *cldapd = talloc_get_type(private_data,
+                                      struct cldapd_server);
        struct ldap_SearchRequest *search;
-       if (ldap_msg->type != LDAP_TAG_SearchRequest) {
-               DEBUG(0,("Invalid CLDAP request type %d from %s:%d\n", 
-                        ldap_msg->type, src->addr, src->port));
-               cldap_error_reply(cldap, ldap_msg->messageid, src,
+
+       if (in->ldap_msg->type != LDAP_TAG_SearchRequest) {
+               DEBUG(0,("Invalid CLDAP request type %d from %s\n",
+                        in->ldap_msg->type,
+                        tsocket_address_string(in->src, in)));
+               cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
                                  LDAP_OPERATIONS_ERROR, "Invalid CLDAP request");
+               talloc_free(in);
                return;
        }
 
-       search = &ldap_msg->r.SearchRequest;
+       search = &in->ldap_msg->r.SearchRequest;
 
        if (strcmp("", search->basedn) != 0) {
-               DEBUG(0,("Invalid CLDAP basedn '%s' from %s:%d\n", 
-                        search->basedn, src->addr, src->port));
-               cldap_error_reply(cldap, ldap_msg->messageid, src,
+               DEBUG(0,("Invalid CLDAP basedn '%s' from %s\n",
+                        search->basedn,
+                        tsocket_address_string(in->src, in)));
+               cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
                                  LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn");
+               talloc_free(in);
                return;
        }
 
        if (search->scope != LDAP_SEARCH_SCOPE_BASE) {
-               DEBUG(0,("Invalid CLDAP scope %d from %s:%d\n", 
-                        search->scope, src->addr, src->port));
-               cldap_error_reply(cldap, ldap_msg->messageid, src,
+               DEBUG(0,("Invalid CLDAP scope %d from %s\n",
+                        search->scope,
+                        tsocket_address_string(in->src, in)));
+               cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
                                  LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope");
+               talloc_free(in);
                return;
        }
 
        if (search->num_attributes == 1 &&
            strcasecmp(search->attributes[0], "netlogon") == 0) {
-               cldapd_netlogon_request(cldap, ldap_msg->messageid,
-                                       search->tree, src);
+               cldapd_netlogon_request(cldap,
+                                       cldapd,
+                                       in,
+                                       in->ldap_msg->messageid,
+                                       search->tree,
+                                       in->src);
+               talloc_free(in);
                return;
        }
 
-       cldapd_rootdse_request(cldap, ldap_msg->messageid,
-                              search, src);
+       cldapd_rootdse_request(cldap, cldapd, in,
+                              in->ldap_msg->messageid,
+                              search, in->src);
+       talloc_free(in);
 }
 
 
@@ -88,28 +105,36 @@ static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_
                                  const char *address)
 {
        struct cldap_socket *cldapsock;
-       struct socket_address *socket_address;
+       struct tsocket_address *socket_address;
        NTSTATUS status;
-
-       /* listen for unicasts on the CLDAP port (389) */
-       cldapsock = cldap_socket_init(cldapd, cldapd->task->event_ctx, lp_iconv_convenience(cldapd->task->lp_ctx));
-       NT_STATUS_HAVE_NO_MEMORY(cldapsock);
-
-       socket_address = socket_address_from_strings(cldapsock, cldapsock->sock->backend_name, 
-                                                    address, lp_cldap_port(lp_ctx));
-       if (!socket_address) {
-               talloc_free(cldapsock);
-               return NT_STATUS_NO_MEMORY;
+       int ret;
+
+       ret = tsocket_address_inet_from_strings(cldapd,
+                                               "ip",
+                                               address,
+                                               lp_cldap_port(lp_ctx),
+                                               &socket_address);
+       if (ret != 0) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(0,("invalid address %s:%d - %s:%s\n",
+                        address, lp_cldap_port(lp_ctx),
+                        gai_strerror(ret), nt_errstr(status)));
+               return status;
        }
 
-       status = socket_listen(cldapsock->sock, socket_address, 0, 0);
+       /* listen for unicasts on the CLDAP port (389) */
+       status = cldap_socket_init(cldapd,
+                                  cldapd->task->event_ctx,
+                                  socket_address,
+                                  NULL,
+                                  &cldapsock);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("Failed to bind to %s:%d - %s\n", 
-                        address, lp_cldap_port(lp_ctx), nt_errstr(status)));
-               talloc_free(cldapsock);
+               DEBUG(0,("Failed to bind to %s - %s\n", 
+                        tsocket_address_string(socket_address, socket_address),
+                        nt_errstr(status)));
+               talloc_free(socket_address);
                return status;
        }
-
        talloc_free(socket_address);
 
        cldap_set_incoming_handler(cldapsock, cldapd_request_handler, cldapd);
@@ -117,7 +142,6 @@ static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_
        return NT_STATUS_OK;
 }
 
-
 /*
   setup our listening sockets on the configured network interfaces
 */
index 0df35be6fdd59da03084217c7ca52949e027f6cc..33c0adc3b18b6d34a2f8abfe968d91124282cefb 100644 (file)
@@ -24,7 +24,6 @@
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
 #include "lib/events/events.h"
-#include "lib/socket/socket.h"
 #include "smbd/service_task.h"
 #include "cldap_server/cldap_server.h"
 #include "librpc/gen_ndr/ndr_misc.h"
@@ -36,6 +35,8 @@
 #include "system/network.h"
 #include "lib/socket/netif.h"
 #include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
+
 /*
   fill in the cldap netlogon union for a given version
 */
@@ -402,12 +403,13 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
 /*
   handle incoming cldap requests
 */
-void cldapd_netlogon_request(struct cldap_socket *cldap, 
+void cldapd_netlogon_request(struct cldap_socket *cldap,
+                            struct cldapd_server *cldapd,
+                            TALLOC_CTX *tmp_ctx,
                             uint32_t message_id,
                             struct ldb_parse_tree *tree,
-                            struct socket_address *src)
+                            struct tsocket_address *src)
 {
-       struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private_data, struct cldapd_server);
        int i;
        const char *domain = NULL;
        const char *host = NULL;
@@ -419,8 +421,6 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
        struct netlogon_samlogon_response netlogon;
        NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
 
-       TALLOC_CTX *tmp_ctx = talloc_new(cldap);
-
        if (tree->operation != LDB_OP_AND) goto failed;
 
        /* extract the query elements */
@@ -478,24 +478,25 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
                 domain, host, user, version, domain_guid));
 
        status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, domain, NULL, NULL, domain_guid,
-                                                user, acct_control, src->addr, 
+                                                user, acct_control,
+                                                tsocket_address_inet_addr_string(src, tmp_ctx),
                                                 version, cldapd->task->lp_ctx, &netlogon);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
-       status = cldap_netlogon_reply(cldap, message_id, src, version,
+       status = cldap_netlogon_reply(cldap,
+                                     lp_iconv_convenience(cldapd->task->lp_ctx),
+                                     message_id, src, version,
                                      &netlogon);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
-       talloc_free(tmp_ctx);
        return;
        
 failed:
        DEBUG(2,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n",
                 domain, host, version, nt_errstr(status)));
-       talloc_free(tmp_ctx);
-       cldap_empty_reply(cldap, message_id, src);      
+       cldap_empty_reply(cldap, message_id, src);
 }
index daa5060d07cf7ae1580f410711bec33c9a02488d..7e867deff29f2d244c6d82558d55dc4eb8310b16 100644 (file)
 */
 
 #include "includes.h"
+#include <tevent.h>
 #include "libcli/ldap/ldap.h"
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
-#include "lib/events/events.h"
-#include "lib/socket/socket.h"
 #include "smbd/service_task.h"
 #include "cldap_server/cldap_server.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "dsdb/samdb/samdb.h"
-#include "auth/auth.h"
 #include "ldb_wrap.h"
-#include "system/network.h"
-#include "lib/socket/netif.h"
 
 static void cldapd_rootdse_fill(struct cldapd_server *cldapd,
                                TALLOC_CTX *mem_ctx,
@@ -151,15 +147,15 @@ done:
   handle incoming cldap requests
 */
 void cldapd_rootdse_request(struct cldap_socket *cldap, 
+                           struct cldapd_server *cldapd,
+                           TALLOC_CTX *tmp_ctx,
                            uint32_t message_id,
                            struct ldap_SearchRequest *search,
-                           struct socket_address *src)
+                           struct tsocket_address *src)
 {
-       struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private_data, struct cldapd_server);
        NTSTATUS status;
        struct cldap_reply reply;
        struct ldap_Result result;
-       TALLOC_CTX *tmp_ctx = talloc_new(cldap);
 
        ZERO_STRUCT(result);
 
@@ -176,6 +172,5 @@ void cldapd_rootdse_request(struct cldap_socket *cldap,
                         ldb_filter_from_tree(tmp_ctx, search->tree), nt_errstr(status)));
        }
 
-       talloc_free(tmp_ctx);
        return;
 }
index b18ba12b1fc2ac8a77681bed834c6a1154fa2fcc..0f2175b42ddfdcbcc5800ebb50f191e7b96342e9 100644 (file)
@@ -4,6 +4,7 @@
    cldap client library
 
    Copyright (C) Andrew Tridgell 2005
+   Copyright (C) Stefan Metzmacher 2009
    
    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
 */
 
 #include "includes.h"
-#include "lib/events/events.h"
+#include <tevent.h>
 #include "../lib/util/dlinklist.h"
 #include "libcli/ldap/ldap.h"
 #include "libcli/ldap/ldap_ndr.h"
 #include "libcli/cldap/cldap.h"
-#include "lib/socket/socket.h"
+#include "../lib/tsocket/tsocket.h"
 #include "libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
+#include "../lib/util/asn1.h"
+#include "../lib/util/tevent_ntstatus.h"
 
 /*
-  destroy a pending request
+  context structure for operations on cldap packets
 */
-static int cldap_request_destructor(struct cldap_request *req)
+struct cldap_socket {
+       /* the low level socket */
+       struct tsocket_context *sock;
+
+       /*
+        * Are we in connected mode, which means
+        * we get ICMP errors back instead of timing
+        * out requests. And we can only send requests
+        * to the connected peer.
+        */
+       bool connected;
+
+       /*
+        * we allow sync requests only, if the caller
+        * did not pass an event context to cldap_socket_init()
+        */
+       struct {
+               bool allow_poll;
+               struct tevent_context *ctx;
+       } event;
+
+       /* the queue for outgoing dgrams */
+       struct tevent_queue *send_queue;
+
+       /* do we have an async tsocket_recvfrom request pending */
+       struct tevent_req *recv_subreq;
+
+       struct {
+               /* a queue of pending search requests */
+               struct cldap_search_state *list;
+
+               /* mapping from message_id to pending request */
+               struct idr_context *idr;
+       } searches;
+
+       /* what to do with incoming request packets */
+       struct {
+               void (*handler)(struct cldap_socket *,
+                               void *private_data,
+                               struct cldap_incoming *);
+               void *private_data;
+       } incoming;
+};
+
+struct cldap_search_state {
+       struct cldap_search_state *prev, *next;
+
+       struct {
+               struct cldap_socket *cldap;
+       } caller;
+
+       int message_id;
+
+       struct {
+               uint32_t idx;
+               uint32_t delay;
+               uint32_t count;
+               struct tsocket_address *dest;
+               DATA_BLOB blob;
+       } request;
+
+       struct {
+               struct cldap_incoming *in;
+               struct asn1_data *asn1;
+       } response;
+
+       struct tevent_req *req;
+};
+
+static int cldap_socket_destructor(struct cldap_socket *c)
 {
-       if (req->state == CLDAP_REQUEST_SEND) {
-               DLIST_REMOVE(req->cldap->send_queue, req);
-       }
-       if (!req->is_reply && req->message_id != 0) {
-               idr_remove(req->cldap->idr, req->message_id);
-               req->message_id = 0;
+       tsocket_disconnect(c->sock);
+
+       while (c->searches.list) {
+               struct cldap_search_state *s = c->searches.list;
+               DLIST_REMOVE(c->searches.list, s);
+               ZERO_STRUCT(s->caller);
        }
+
+       talloc_free(c->recv_subreq);
+       talloc_free(c->send_queue);
+       talloc_free(c->sock);
        return 0;
 }
 
-/*
-  handle recv events on a cldap socket
-*/
-static void cldap_socket_recv(struct cldap_socket *cldap)
-{
-       TALLOC_CTX *tmp_ctx = talloc_new(cldap);
-       NTSTATUS status;
-       struct socket_address *src;
-       DATA_BLOB blob;
-       size_t nread, dsize;
-       struct asn1_data *asn1 = asn1_init(tmp_ctx);
-       struct ldap_message *ldap_msg;
-       struct cldap_request *req;
-
-       if (!asn1) return;
+static void cldap_recvfrom_done(struct tevent_req *subreq);
 
-       status = socket_pending(cldap->sock, &dsize);
-       if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(tmp_ctx);
-               return;
+static bool cldap_recvfrom_setup(struct cldap_socket *c)
+{
+       if (c->recv_subreq) {
+               return true;
        }
 
-       blob = data_blob_talloc(tmp_ctx, NULL, dsize);
-       if (blob.data == NULL) {
-               talloc_free(tmp_ctx);
-               return;
+       if (!c->searches.list && !c->incoming.handler) {
+               return true;
        }
 
-       status = socket_recvfrom(cldap->sock, blob.data, blob.length, &nread,
-                                tmp_ctx, &src);
-       if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(tmp_ctx);
-               return;
+       c->recv_subreq = tsocket_recvfrom_send(c->sock, c);
+       if (!c->recv_subreq) {
+               return false;
        }
-       blob.length = nread;
+       tevent_req_set_callback(c->recv_subreq, cldap_recvfrom_done, c);
 
-       DEBUG(2,("Received cldap packet of length %d from %s:%d\n", 
-                (int)blob.length, src->addr, src->port));
+       return true;
+}
 
-       if (!asn1_load(asn1, blob)) {
-               DEBUG(2,("Failed to setup for asn.1 decode\n"));
-               talloc_free(tmp_ctx);
+static void cldap_recvfrom_stop(struct cldap_socket *c)
+{
+       if (!c->recv_subreq) {
                return;
        }
 
-       ldap_msg = talloc(tmp_ctx, struct ldap_message);
-       if (ldap_msg == NULL) {
-               talloc_free(tmp_ctx);
+       if (c->searches.list || c->incoming.handler) {
                return;
        }
 
-       /* this initial decode is used to find the message id */
-       status = ldap_decode(asn1, NULL, ldap_msg);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status)));
-               talloc_free(tmp_ctx);
-               return;
-       }
-
-       /* find the pending request */
-       req = idr_find(cldap->idr, ldap_msg->messageid);
-       if (req == NULL) {
-               if (cldap->incoming.handler) {
-                       cldap->incoming.handler(cldap, ldap_msg, src);
-               } else {
-                       DEBUG(2,("Mismatched cldap reply %u from %s:%d\n",
-                                ldap_msg->messageid, src->addr, src->port));
-               }
-               talloc_free(tmp_ctx);
-               return;
-       }
+       talloc_free(c->recv_subreq);
+       c->recv_subreq = NULL;
+}
 
-       req->asn1 = talloc_steal(req, asn1);
-       req->asn1->ofs = 0;
+static void cldap_socket_recv_dgram(struct cldap_socket *c,
+                                   struct cldap_incoming *in);
 
-       req->state = CLDAP_REQUEST_DONE;
-       talloc_free(req->te);
+static void cldap_recvfrom_done(struct tevent_req *subreq)
+{
+       struct cldap_socket *c = tevent_req_callback_data(subreq,
+                                struct cldap_socket);
+       struct cldap_incoming *in = NULL;
+       ssize_t ret;
 
-       talloc_free(tmp_ctx);
+       c->recv_subreq = NULL;
 
-       if (req->async.fn) {
-               req->async.fn(req);
+       in = talloc_zero(c, struct cldap_incoming);
+       if (!in) {
+               goto nomem;
        }
-}
-
-/*
-  handle request timeouts
-*/
-static void cldap_request_timeout(struct tevent_context *event_ctx, 
-                                 struct tevent_timer *te, struct timeval t,
-                                 void *private_data)
-{
-       struct cldap_request *req = talloc_get_type(private_data, struct cldap_request);
-
-       /* possibly try again */
-       if (req->num_retries != 0) {
-               size_t len = req->encoded.length;
 
-               req->num_retries--;
+       ret = tsocket_recvfrom_recv(subreq,
+                                   &in->recv_errno,
+                                   in,
+                                   &in->buf,
+                                   &in->src);
+       talloc_free(subreq);
+       subreq = NULL;
+       if (ret >= 0) {
+               in->len = ret;
+       }
+       if (ret == -1 && in->recv_errno == 0) {
+               in->recv_errno = EIO;
+       }
 
-               socket_sendto(req->cldap->sock, &req->encoded, &len, 
-                             req->dest);
+       /* this function should free or steal 'in' */
+       cldap_socket_recv_dgram(c, in);
+       in = NULL;
 
-               req->te = event_add_timed(req->cldap->event_ctx, req, 
-                                         timeval_current_ofs(req->timeout, 0),
-                                         cldap_request_timeout, req);
-               return;
+       if (!cldap_recvfrom_setup(c)) {
+               goto nomem;
        }
 
-       req->state = CLDAP_REQUEST_ERROR;
-       req->status = NT_STATUS_IO_TIMEOUT;
-       if (req->async.fn) {
-               req->async.fn(req);
-       }
+       return;
+
+nomem:
+       talloc_free(subreq);
+       talloc_free(in);
+       /*TODO: call a dead socket handler */
+       return;
 }
 
 /*
-  handle send events on a cldap socket
+  handle recv events on a cldap socket
 */
-static void cldap_socket_send(struct cldap_socket *cldap)
+static void cldap_socket_recv_dgram(struct cldap_socket *c,
+                                   struct cldap_incoming *in)
 {
-       struct cldap_request *req;
+       DATA_BLOB blob;
+       struct asn1_data *asn1;
+       void *p;
+       struct cldap_search_state *search;
        NTSTATUS status;
 
-       while ((req = cldap->send_queue)) {
-               size_t len;
-               
-               len = req->encoded.length;
-               status = socket_sendto(cldap->sock, &req->encoded, &len,
-                                      req->dest);
-               if (NT_STATUS_IS_ERR(status)) {
-                       DEBUG(0,("Failed to send cldap request of length %u to %s:%d\n",
-                                (unsigned)req->encoded.length, req->dest->addr, req->dest->port));
-                       DLIST_REMOVE(cldap->send_queue, req);
-                       req->state = CLDAP_REQUEST_ERROR;
-                       req->status = status;
-                       if (req->async.fn) {
-                               req->async.fn(req);
-                       }
-                       continue;
-               }
+       if (in->recv_errno != 0) {
+               goto error;
+       }
 
-               if (!NT_STATUS_IS_OK(status)) return;
+       blob = data_blob_const(in->buf, in->len);
 
-               DLIST_REMOVE(cldap->send_queue, req);
+       asn1 = asn1_init(in);
+       if (!asn1) {
+               goto nomem;
+       }
 
-               if (req->is_reply) {
-                       talloc_free(req);
-               } else {
-                       req->state = CLDAP_REQUEST_WAIT;
+       if (!asn1_load(asn1, blob)) {
+               goto nomem;
+       }
 
-                       req->te = event_add_timed(cldap->event_ctx, req, 
-                                                 timeval_current_ofs(req->timeout, 0),
-                                                 cldap_request_timeout, req);
+       in->ldap_msg = talloc(in, struct ldap_message);
+       if (in->ldap_msg == NULL) {
+               goto nomem;
+       }
 
-                       EVENT_FD_READABLE(cldap->fde);
-               }
+       /* this initial decode is used to find the message id */
+       status = ldap_decode(asn1, NULL, in->ldap_msg);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto nterror;
        }
 
-       EVENT_FD_NOT_WRITEABLE(cldap->fde);
-       return;
-}
+       /* find the pending request */
+       p = idr_find(c->searches.idr, in->ldap_msg->messageid);
+       if (p == NULL) {
+               if (!c->incoming.handler) {
+                       goto done;
+               }
 
+               /* this function should free or steal 'in' */
+               c->incoming.handler(c, c->incoming.private_data, in);
+               return;
+       }
 
-/*
-  handle fd events on a cldap_socket
-*/
-static void cldap_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
-                                uint16_t flags, void *private_data)
-{
-       struct cldap_socket *cldap = talloc_get_type(private_data, struct cldap_socket);
-       if (flags & EVENT_FD_WRITE) {
-               cldap_socket_send(cldap);
-       } 
-       if (flags & EVENT_FD_READ) {
-               cldap_socket_recv(cldap);
+       search = talloc_get_type(p, struct cldap_search_state);
+       search->response.in = talloc_move(search, &in);
+       search->response.asn1 = asn1;
+       search->response.asn1->ofs = 0;
+
+       tevent_req_done(search->req);
+       goto done;
+
+nomem:
+       in->recv_errno = ENOMEM;
+error:
+       status = map_nt_error_from_unix(in->recv_errno);
+nterror:
+       /* in connected mode the first pending search gets the error */
+       if (!c->connected) {
+               /* otherwise we just ignore the error */
+               goto done;
        }
+       if (!c->searches.list) {
+               goto done;
+       }
+       tevent_req_nterror(c->searches.list->req, status);
+done:
+       talloc_free(in);
 }
 
 /*
-  initialise a cldap_socket. The event_ctx is optional, if provided
-  then operations will use that event context
+  initialise a cldap_sock
 */
-struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx, 
-                                      struct tevent_context *event_ctx,
-                                      struct smb_iconv_convenience *iconv_convenience)
+NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx,
+                          struct tevent_context *ev,
+                          const struct tsocket_address *local_addr,
+                          const struct tsocket_address *remote_addr,
+                          struct cldap_socket **_cldap)
 {
-       struct cldap_socket *cldap;
+       struct cldap_socket *c = NULL;
+       struct tsocket_address *any = NULL;
        NTSTATUS status;
+       int ret;
 
-       cldap = talloc(mem_ctx, struct cldap_socket);
-       if (cldap == NULL) goto failed;
+       c = talloc_zero(mem_ctx, struct cldap_socket);
+       if (!c) {
+               goto nomem;
+       }
 
-       cldap->event_ctx = talloc_reference(cldap, event_ctx);
-       if (cldap->event_ctx == NULL) goto failed;
+       if (!ev) {
+               ev = tevent_context_init(c);
+               if (!ev) {
+                       goto nomem;
+               }
+               c->event.allow_poll = true;
+       }
+       c->event.ctx = ev;
+
+       if (!local_addr) {
+               ret = tsocket_address_inet_from_strings(c, "ipv4",
+                                                       NULL, 0,
+                                                       &any);
+               if (ret != 0) {
+                       status = map_nt_error_from_unix(errno);
+                       goto nterror;
+               }
+               local_addr = any;
+       }
 
-       cldap->idr = idr_init(cldap);
-       if (cldap->idr == NULL) goto failed;
+       c->searches.idr = idr_init(c);
+       if (!c->searches.idr) {
+               goto nomem;
+       }
 
-       status = socket_create("ip", SOCKET_TYPE_DGRAM, &cldap->sock, 0);
-       if (!NT_STATUS_IS_OK(status)) goto failed;
+       ret = tsocket_address_create_socket(local_addr,
+                                           TSOCKET_TYPE_DGRAM,
+                                           c, &c->sock);
+       if (ret != 0) {
+               status = map_nt_error_from_unix(errno);
+               goto nterror;
+       }
+       talloc_free(any);
 
-       talloc_steal(cldap, cldap->sock);
+       tsocket_set_event_context(c->sock, c->event.ctx);
 
-       cldap->fde = event_add_fd(cldap->event_ctx, cldap, 
-                                     socket_get_fd(cldap->sock), 0,
-                                     cldap_socket_handler, cldap);
+       if (remote_addr) {
+               ret = tsocket_connect(c->sock, remote_addr);
+               if (ret != 0) {
+                       status = map_nt_error_from_unix(errno);
+                       goto nterror;
+               }
+               c->connected = true;
+       }
 
-       cldap->send_queue = NULL;
-       cldap->incoming.handler = NULL;
-       cldap->iconv_convenience = iconv_convenience;
-       
-       return cldap;
+       c->send_queue = tevent_queue_create(c, "cldap_send_queue");
+       if (!c->send_queue) {
+               goto nomem;
+       }
 
-failed:
-       talloc_free(cldap);
-       return NULL;
-}
+       talloc_set_destructor(c, cldap_socket_destructor);
+
+       *_cldap = c;
+       return NT_STATUS_OK;
 
+nomem:
+       status = NT_STATUS_NO_MEMORY;
+nterror:
+       talloc_free(c);
+       return status;
+}
 
 /*
   setup a handler for incoming requests
 */
-NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap,
-                                 void (*handler)(struct cldap_socket *, struct ldap_message *, 
-                                                 struct socket_address *),
-                                 void *private_data)
+NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c,
+                                   void (*handler)(struct cldap_socket *,
+                                                   void *private_data,
+                                                   struct cldap_incoming *),
+                                   void *private_data)
 {
-       cldap->incoming.handler = handler;
-       cldap->incoming.private_data = private_data;
-       EVENT_FD_READABLE(cldap->fde);
+       if (c->connected) {
+               return NT_STATUS_PIPE_CONNECTED;
+       }
+
+       /* if sync requests are allowed, we don't allow an incoming handler */
+       if (c->event.allow_poll) {
+               return NT_STATUS_INVALID_PIPE_STATE;
+       }
+
+       c->incoming.handler = handler;
+       c->incoming.private_data = private_data;
+
+       if (!cldap_recvfrom_setup(c)) {
+               ZERO_STRUCT(c->incoming);
+               return NT_STATUS_NO_MEMORY;
+       }
+
        return NT_STATUS_OK;
 }
 
+struct cldap_reply_state {
+       struct tsocket_address *dest;
+       DATA_BLOB blob;
+};
+
+static void cldap_reply_state_destroy(struct tevent_req *req);
+
 /*
-  queue a cldap request for send
+  queue a cldap reply for send
 */
-struct cldap_request *cldap_search_send(struct cldap_socket *cldap, 
-                                       struct cldap_search *io)
+NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
 {
+       struct cldap_reply_state *state = NULL;
        struct ldap_message *msg;
-       struct cldap_request *req;
-       struct ldap_SearchRequest *search;
+       DATA_BLOB blob1, blob2;
+       NTSTATUS status;
+       struct tevent_req *req;
 
-       req = talloc_zero(cldap, struct cldap_request);
-       if (req == NULL) goto failed;
+       if (cldap->connected) {
+               return NT_STATUS_PIPE_CONNECTED;
+       }
 
-       req->cldap       = cldap;
-       req->state       = CLDAP_REQUEST_SEND;
-       req->timeout     = io->in.timeout;
-       req->num_retries = io->in.retries;
-       req->is_reply    = false;
-       req->asn1        = asn1_init(req);
-       if (!req->asn1) {
-               goto failed;
+       if (!io->dest) {
+               return NT_STATUS_INVALID_ADDRESS;
        }
 
-       req->dest = socket_address_from_strings(req, cldap->sock->backend_name,
-                                               io->in.dest_address, 
-                                               io->in.dest_port);
-       if (!req->dest) goto failed;
+       state = talloc(cldap, struct cldap_reply_state);
+       NT_STATUS_HAVE_NO_MEMORY(state);
 
-       req->message_id = idr_get_new_random(cldap->idr, req, UINT16_MAX);
-       if (req->message_id == -1) goto failed;
+       state->dest = tsocket_address_copy(io->dest, state);
+       if (!state->dest) {
+               goto nomem;
+       }
 
-       talloc_set_destructor(req, cldap_request_destructor);
+       msg = talloc(state, struct ldap_message);
+       if (!msg) {
+               goto nomem;
+       }
 
-       msg = talloc(req, struct ldap_message);
-       if (msg == NULL) goto failed;
-       msg->messageid       = req->message_id;
-       msg->type            = LDAP_TAG_SearchRequest;
+       msg->messageid       = io->messageid;
        msg->controls        = NULL;
-       search = &msg->r.SearchRequest;
 
-       search->basedn         = "";
-       search->scope          = LDAP_SEARCH_SCOPE_BASE;
-       search->deref          = LDAP_DEREFERENCE_NEVER;
-       search->timelimit      = 0;
-       search->sizelimit      = 0;
-       search->attributesonly = false;
-       search->num_attributes = str_list_length(io->in.attributes);
-       search->attributes     = io->in.attributes;
-       search->tree           = ldb_parse_tree(req, io->in.filter);
-       if (search->tree == NULL) {
-               goto failed;
+       if (io->response) {
+               msg->type = LDAP_TAG_SearchResultEntry;
+               msg->r.SearchResultEntry = *io->response;
+
+               if (!ldap_encode(msg, NULL, &blob1, state)) {
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto failed;
+               }
+       } else {
+               blob1 = data_blob(NULL, 0);
        }
 
-       if (!ldap_encode(msg, NULL, &req->encoded, req)) {
-               DEBUG(0,("Failed to encode cldap message to %s:%d\n",
-                        req->dest->addr, req->dest->port));
+       msg->type = LDAP_TAG_SearchResultDone;
+       msg->r.SearchResultDone = *io->result;
+
+       if (!ldap_encode(msg, NULL, &blob2, state)) {
+               status = NT_STATUS_INVALID_PARAMETER;
                goto failed;
        }
+       talloc_free(msg);
 
-       DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *);
+       state->blob = data_blob_talloc(state, NULL, blob1.length + blob2.length);
+       if (!state->blob.data) {
+               goto nomem;
+       }
 
-       EVENT_FD_WRITEABLE(cldap->fde);
+       memcpy(state->blob.data, blob1.data, blob1.length);
+       memcpy(state->blob.data+blob1.length, blob2.data, blob2.length);
+       data_blob_free(&blob1);
+       data_blob_free(&blob2);
+
+       req = tsocket_sendto_queue_send(state,
+                                       cldap->sock,
+                                       cldap->send_queue,
+                                       state->blob.data,
+                                       state->blob.length,
+                                       state->dest);
+       if (!req) {
+               goto nomem;
+       }
+       /* the callback will just free the state, as we don't need a result */
+       tevent_req_set_callback(req, cldap_reply_state_destroy, state);
 
-       return req;
+       return NT_STATUS_OK;
 
+nomem:
+       status = NT_STATUS_NO_MEMORY;
 failed:
+       talloc_free(state);
+       return status;
+}
+
+static void cldap_reply_state_destroy(struct tevent_req *req)
+{
+       struct cldap_reply_state *state = tevent_req_callback_data(req,
+                                         struct cldap_reply_state);
+
+       /* we don't want to know the result here, we just free the state */
        talloc_free(req);
-       return NULL;
+       talloc_free(state);
+}
+
+static int cldap_search_state_destructor(struct cldap_search_state *s)
+{
+       if (s->caller.cldap) {
+               DLIST_REMOVE(s->caller.cldap->searches.list, s);
+               cldap_recvfrom_stop(s->caller.cldap);
+               ZERO_STRUCT(s->caller);
+       }
+
+       return 0;
 }
 
+static void cldap_search_state_queue_done(struct tevent_req *subreq);
+static void cldap_search_state_wakeup_done(struct tevent_req *subreq);
 
 /*
   queue a cldap reply for send
 */
-NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
+struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx,
+                                   struct cldap_socket *cldap,
+                                   const struct cldap_search *io)
 {
+       struct tevent_req *req, *subreq;
+       struct cldap_search_state *state = NULL;
        struct ldap_message *msg;
-       struct cldap_request *req;
-       DATA_BLOB blob1, blob2;
-       NTSTATUS status = NT_STATUS_NO_MEMORY;
+       struct ldap_SearchRequest *search;
+       struct timeval now;
+       struct timeval end;
+       uint32_t i;
+       int ret;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct cldap_search_state);
+       if (!req) {
+               return NULL;
+       }
+       state->req = req;
+       state->caller.cldap = cldap;
+
+       if (io->in.dest_address) {
+               if (cldap->connected) {
+                       tevent_req_nterror(req, NT_STATUS_PIPE_CONNECTED);
+                       goto post;
+               }
+               ret = tsocket_address_inet_from_strings(state,
+                                                       "ipv4",
+                                                       io->in.dest_address,
+                                                       io->in.dest_port,
+                                                       &state->request.dest);
+               if (ret != 0) {
+                       tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       goto post;
+               }
+       } else {
+               if (!cldap->connected) {
+                       tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
+                       goto post;
+               }
+               state->request.dest = NULL;
+       }
 
-       req = talloc_zero(cldap, struct cldap_request);
-       if (req == NULL) goto failed;
+       state->message_id = idr_get_new_random(cldap->searches.idr,
+                                              state, UINT16_MAX);
+       if (state->message_id == -1) {
+               tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
+               goto post;
+       }
 
-       req->cldap       = cldap;
-       req->state       = CLDAP_REQUEST_SEND;
-       req->is_reply    = true;
-       req->asn1        = asn1_init(req);
-       if (!req->asn1) {
-               goto failed;
+       msg = talloc(state, struct ldap_message);
+       if (tevent_req_nomem(msg, req)) {
+               goto post;
        }
 
-       req->dest        = io->dest;
-       if (talloc_reference(req, io->dest) == NULL) goto failed;
+       msg->messageid  = state->message_id;
+       msg->type       = LDAP_TAG_SearchRequest;
+       msg->controls   = NULL;
+       search = &msg->r.SearchRequest;
 
-       talloc_set_destructor(req, cldap_request_destructor);
+       search->basedn          = "";
+       search->scope           = LDAP_SEARCH_SCOPE_BASE;
+       search->deref           = LDAP_DEREFERENCE_NEVER;
+       search->timelimit       = 0;
+       search->sizelimit       = 0;
+       search->attributesonly  = false;
+       search->num_attributes  = str_list_length(io->in.attributes);
+       search->attributes      = io->in.attributes;
+       search->tree            = ldb_parse_tree(msg, io->in.filter);
+       if (tevent_req_nomem(search->tree, req)) {
+               goto post;
+       }
 
-       msg = talloc(req, struct ldap_message);
-       if (msg == NULL) goto failed;
-       msg->messageid       = io->messageid;
-       msg->controls        = NULL;
-       
-       if (io->response) {
-               msg->type = LDAP_TAG_SearchResultEntry;
-               msg->r.SearchResultEntry = *io->response;
+       if (!ldap_encode(msg, NULL, &state->request.blob, state)) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto post;
+       }
+       talloc_free(msg);
+
+       state->request.idx = 0;
+       state->request.delay = 10*1000*1000;
+       state->request.count = 3;
+       if (io->in.timeout > 0) {
+               state->request.delay = io->in.timeout * 1000 * 1000;
+               state->request.count = io->in.retries + 1;
+       }
 
-               if (!ldap_encode(msg, NULL, &blob1, req)) {
-                       DEBUG(0,("Failed to encode cldap message to %s:%d\n",
-                                req->dest->addr, req->dest->port));
-                       status = NT_STATUS_INVALID_PARAMETER;
-                       goto failed;
-               }
-       } else {
-               blob1 = data_blob(NULL, 0);
+       now = tevent_timeval_current();
+       end = now;
+       for (i = 0; i < state->request.count; i++) {
+               end = tevent_timeval_add(&end, 0, state->request.delay);
        }
 
-       msg->type = LDAP_TAG_SearchResultDone;
-       msg->r.SearchResultDone = *io->result;
+       if (!tevent_req_set_endtime(req, state->caller.cldap->event.ctx, end)) {
+               tevent_req_nomem(NULL, req);
+               goto post;
+       }
 
-       if (!ldap_encode(msg, NULL, &blob2, req)) {
-               DEBUG(0,("Failed to encode cldap message to %s:%d\n",
-                        req->dest->addr, req->dest->port));
-               status = NT_STATUS_INVALID_PARAMETER;
-               goto failed;
+       subreq = tsocket_sendto_queue_send(state,
+                                          state->caller.cldap->sock,
+                                          state->caller.cldap->send_queue,
+                                          state->request.blob.data,
+                                          state->request.blob.length,
+                                          state->request.dest);
+       if (tevent_req_nomem(subreq, req)) {
+               goto post;
        }
+       tevent_req_set_callback(subreq, cldap_search_state_queue_done, req);
 
-       req->encoded = data_blob_talloc(req, NULL, blob1.length + blob2.length);
-       if (req->encoded.data == NULL) goto failed;
+       DLIST_ADD_END(cldap->searches.list, state, struct cldap_search_state *);
+       talloc_set_destructor(state, cldap_search_state_destructor);
 
-       memcpy(req->encoded.data, blob1.data, blob1.length);
-       memcpy(req->encoded.data+blob1.length, blob2.data, blob2.length);
+       return req;
 
-       DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *);
+ post:
+       return tevent_req_post(req, cldap->event.ctx);
+}
 
-       EVENT_FD_WRITEABLE(cldap->fde);
+static void cldap_search_state_queue_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(subreq,
+                                struct tevent_req);
+       struct cldap_search_state *state = tevent_req_data(req,
+                                          struct cldap_search_state);
+       ssize_t ret;
+       int sys_errno = 0;
+       struct timeval next;
+
+       ret = tsocket_sendto_queue_recv(subreq, &sys_errno);
+       talloc_free(subreq);
+       if (ret == -1) {
+               NTSTATUS status;
+               status = map_nt_error_from_unix(sys_errno);
+               DLIST_REMOVE(state->caller.cldap->searches.list, state);
+               ZERO_STRUCT(state->caller.cldap);
+               tevent_req_nterror(req, status);
+               return;
+       }
 
-       return NT_STATUS_OK;
+       state->request.idx++;
 
-failed:
-       talloc_free(req);
-       return status;
+       /* wait for incoming traffic */
+       if (!cldap_recvfrom_setup(state->caller.cldap)) {
+               tevent_req_nomem(NULL, req);
+               return;
+       }
+
+       if (state->request.idx > state->request.count) {
+               /* we just wait for the response or a timeout */
+               return;
+       }
+
+       next = tevent_timeval_current_ofs(0, state->request.delay);
+       subreq = tevent_wakeup_send(state,
+                                   state->caller.cldap->event.ctx,
+                                   next);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, cldap_search_state_wakeup_done, req);
+}
+
+static void cldap_search_state_wakeup_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(subreq,
+                                struct tevent_req);
+       struct cldap_search_state *state = tevent_req_data(req,
+                                          struct cldap_search_state);
+       bool ok;
+
+       ok = tevent_wakeup_recv(subreq);
+       talloc_free(subreq);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+
+       subreq = tsocket_sendto_queue_send(state,
+                                          state->caller.cldap->sock,
+                                          state->caller.cldap->send_queue,
+                                          state->request.blob.data,
+                                          state->request.blob.length,
+                                          state->request.dest);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, cldap_search_state_queue_done, req);
 }
 
 /*
   receive a cldap reply
 */
-NTSTATUS cldap_search_recv(struct cldap_request *req, 
-                          TALLOC_CTX *mem_ctx, 
+NTSTATUS cldap_search_recv(struct tevent_req *req,
+                          TALLOC_CTX *mem_ctx,
                           struct cldap_search *io)
 {
+       struct cldap_search_state *state = tevent_req_data(req,
+                                          struct cldap_search_state);
        struct ldap_message *ldap_msg;
        NTSTATUS status;
 
-       if (req == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       while (req->state < CLDAP_REQUEST_DONE) {
-               if (event_loop_once(req->cldap->event_ctx) != 0) {
-                       talloc_free(req);
-                       return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
-               }
-       }
-
-       if (req->state == CLDAP_REQUEST_ERROR) {
-               status = req->status;
-               talloc_free(req);
-               return status;
+       if (tevent_req_is_nterror(req, &status)) {
+               goto failed;
        }
 
        ldap_msg = talloc(mem_ctx, struct ldap_message);
-       NT_STATUS_HAVE_NO_MEMORY(ldap_msg);
+       if (!ldap_msg) {
+               goto nomem;
+       }
 
-       status = ldap_decode(req->asn1, NULL, ldap_msg);
+       status = ldap_decode(state->response.asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status)));
-               talloc_free(req);
-               return status;
+               goto failed;
        }
 
        ZERO_STRUCT(io->out);
@@ -475,167 +742,283 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
        /* the first possible form has a search result in first place */
        if (ldap_msg->type == LDAP_TAG_SearchResultEntry) {
                io->out.response = talloc(mem_ctx, struct ldap_SearchResEntry);
-               NT_STATUS_HAVE_NO_MEMORY(io->out.response);
+               if (!io->out.response) {
+                       goto nomem;
+               }
                *io->out.response = ldap_msg->r.SearchResultEntry;
 
                /* decode the 2nd part */
-               status = ldap_decode(req->asn1, NULL, ldap_msg);
+               status = ldap_decode(state->response.asn1, NULL, ldap_msg);
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status)));
-                       talloc_free(req);
-                       return status;
+                       goto failed;
                }
        }
 
        if (ldap_msg->type != LDAP_TAG_SearchResultDone) {
-               talloc_free(req);
-               return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+               status = NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+               goto failed;
        }
 
        io->out.result = talloc(mem_ctx, struct ldap_Result);
-       NT_STATUS_HAVE_NO_MEMORY(io->out.result);
+       if (!io->out.result) {
+               goto nomem;
+       }
        *io->out.result = ldap_msg->r.SearchResultDone;
 
-       talloc_free(req);
-
        if (io->out.result->resultcode != LDAP_SUCCESS) {
-               return NT_STATUS_LDAP(io->out.result->resultcode);
+               status = NT_STATUS_LDAP(io->out.result->resultcode);
+               goto failed;
        }
+
+       tevent_req_received(req);
        return NT_STATUS_OK;
+
+nomem:
+       status = NT_STATUS_NO_MEMORY;
+failed:
+       tevent_req_received(req);
+       return status;
 }
 
 
 /*
   synchronous cldap search
 */
-NTSTATUS cldap_search(struct cldap_socket *cldap, 
-                     TALLOC_CTX *mem_ctx, 
+NTSTATUS cldap_search(struct cldap_socket *cldap,
+                     TALLOC_CTX *mem_ctx,
                      struct cldap_search *io)
 {
-       struct cldap_request *req = cldap_search_send(cldap, io);
-       return cldap_search_recv(req, mem_ctx, io);
-}
+       struct tevent_req *req;
+       NTSTATUS status;
+
+       if (!cldap->event.allow_poll) {
+               return NT_STATUS_INVALID_PIPE_STATE;
+       }
+
+       if (cldap->searches.list) {
+               return NT_STATUS_PIPE_BUSY;
+       }
 
+       req = cldap_search_send(mem_ctx, cldap, io);
+       NT_STATUS_HAVE_NO_MEMORY(req);
 
+       if (!tevent_req_poll(req, cldap->event.ctx)) {
+               talloc_free(req);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
 
+       status = cldap_search_recv(req, mem_ctx, io);
+       talloc_free(req);
+
+       return status;
+}
+
+struct cldap_netlogon_state {
+       struct cldap_search search;
+};
+
+static void cldap_netlogon_state_done(struct tevent_req *subreq);
 /*
   queue a cldap netlogon for send
 */
-struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap, 
-                                         struct cldap_netlogon *io)
+struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx,
+                                     struct cldap_socket *cldap,
+                                     const struct cldap_netlogon *io)
 {
-       struct cldap_search search;
+       struct tevent_req *req, *subreq;
+       struct cldap_netlogon_state *state;
        char *filter;
-       struct cldap_request *req;
-       const char *attr[] = { "NetLogon", NULL };
-       TALLOC_CTX *tmp_ctx = talloc_new(cldap);
+       static const char * const attr[] = { "NetLogon", NULL };
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct cldap_netlogon_state);
+       if (!req) {
+               return NULL;
+       }
 
-       filter = talloc_asprintf(tmp_ctx, "(&(NtVer=%s)", 
-                                ldap_encode_ndr_uint32(tmp_ctx, io->in.version));
-       if (filter == NULL) goto failed;
+       filter = talloc_asprintf(state, "(&(NtVer=%s)", 
+                                ldap_encode_ndr_uint32(state, io->in.version));
+       if (tevent_req_nomem(filter, req)) {
+               goto post;
+       }
        if (io->in.user) {
                filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user);
-               if (filter == NULL) goto failed;
+               if (tevent_req_nomem(filter, req)) {
+                       goto post;
+               }
        }
        if (io->in.host) {
                filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host);
-               if (filter == NULL) goto failed;
+               if (tevent_req_nomem(filter, req)) {
+                       goto post;
+               }
        }
        if (io->in.realm) {
                filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm);
-               if (filter == NULL) goto failed;
+               if (tevent_req_nomem(filter, req)) {
+                       goto post;
+               }
        }
        if (io->in.acct_control != -1) {
                filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)", 
-                                               ldap_encode_ndr_uint32(tmp_ctx, io->in.acct_control));
-               if (filter == NULL) goto failed;
+                                               ldap_encode_ndr_uint32(state, io->in.acct_control));
+               if (tevent_req_nomem(filter, req)) {
+                       goto post;
+               }
        }
        if (io->in.domain_sid) {
-               struct dom_sid *sid = dom_sid_parse_talloc(tmp_ctx, io->in.domain_sid);
-               if (sid == NULL) goto failed;
+               struct dom_sid *sid = dom_sid_parse_talloc(state, io->in.domain_sid);
+               if (tevent_req_nomem(sid, req)) {
+                       goto post;
+               }
                filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)",
-                                               ldap_encode_ndr_dom_sid(tmp_ctx, sid));
-               if (filter == NULL) goto failed;
+                                               ldap_encode_ndr_dom_sid(state, sid));
+               if (tevent_req_nomem(filter, req)) {
+                       goto post;
+               }
        }
        if (io->in.domain_guid) {
                struct GUID guid;
                NTSTATUS status;
                status = GUID_from_string(io->in.domain_guid, &guid);
-               if (!NT_STATUS_IS_OK(status)) goto failed;
+               if (tevent_req_nterror(req, status)) {
+                       goto post;
+               }
                filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)",
-                                               ldap_encode_ndr_GUID(tmp_ctx, &guid));
-               if (filter == NULL) goto failed;
+                                               ldap_encode_ndr_GUID(state, &guid));
+               if (tevent_req_nomem(filter, req)) {
+                       goto post;
+               }
        }
        filter = talloc_asprintf_append_buffer(filter, ")");
-       if (filter == NULL) goto failed;
-
-       search.in.dest_address = io->in.dest_address;
-       search.in.dest_port    = io->in.dest_port;
-       search.in.filter       = filter;
-       search.in.attributes   = attr;
-       search.in.timeout      = 2;
-       search.in.retries      = 2;
+       if (tevent_req_nomem(filter, req)) {
+               goto post;
+       }
 
-       req = cldap_search_send(cldap, &search);
+       if (io->in.dest_address) {
+               state->search.in.dest_address = talloc_strdup(state,
+                                               io->in.dest_address);
+               if (tevent_req_nomem(state->search.in.dest_address, req)) {
+                       goto post;
+               }
+               state->search.in.dest_port = io->in.dest_port;
+       } else {
+               state->search.in.dest_address   = NULL;
+               state->search.in.dest_port      = 0;
+       }
+       state->search.in.filter         = filter;
+       state->search.in.attributes     = attr;
+       state->search.in.timeout        = 2;
+       state->search.in.retries        = 2;
+
+       subreq = cldap_search_send(state, cldap, &state->search);
+       if (tevent_req_nomem(subreq, req)) {
+               goto post;
+       }
+       tevent_req_set_callback(subreq, cldap_netlogon_state_done, req);
 
-       talloc_free(tmp_ctx);
        return req;
-failed:
-       talloc_free(tmp_ctx);
-       return NULL;
+post:
+       return tevent_req_post(req, cldap->event.ctx);
 }
 
+static void cldap_netlogon_state_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(subreq,
+                                struct tevent_req);
+       struct cldap_netlogon_state *state = tevent_req_data(req,
+                                            struct cldap_netlogon_state);
+       NTSTATUS status;
+
+       status = cldap_search_recv(subreq, state, &state->search);
+       talloc_free(subreq);
+
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
+       tevent_req_done(req);
+}
 
 /*
   receive a cldap netlogon reply
 */
-NTSTATUS cldap_netlogon_recv(struct cldap_request *req, 
-                            TALLOC_CTX *mem_ctx, 
+NTSTATUS cldap_netlogon_recv(struct tevent_req *req,
+                            struct smb_iconv_convenience *iconv_convenience,
+                            TALLOC_CTX *mem_ctx,
                             struct cldap_netlogon *io)
 {
+       struct cldap_netlogon_state *state = tevent_req_data(req,
+                                            struct cldap_netlogon_state);
        NTSTATUS status;
-       struct cldap_search search;
-       struct cldap_socket *cldap;
        DATA_BLOB *data;
 
-       cldap = req->cldap;
-
-       status = cldap_search_recv(req, mem_ctx, &search);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       if (tevent_req_is_nterror(req, &status)) {
+               goto failed;
        }
-       if (search.out.response == NULL) {
-               return NT_STATUS_NOT_FOUND;
+
+       if (state->search.out.response == NULL) {
+               status = NT_STATUS_NOT_FOUND;
+               goto failed;
        }
 
-       if (search.out.response->num_attributes != 1 ||
-           strcasecmp(search.out.response->attributes[0].name, "netlogon") != 0 ||
-           search.out.response->attributes[0].num_values != 1 ||
-           search.out.response->attributes[0].values->length < 2) {
-               return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+       if (state->search.out.response->num_attributes != 1 ||
+           strcasecmp(state->search.out.response->attributes[0].name, "netlogon") != 0 ||
+           state->search.out.response->attributes[0].num_values != 1 ||
+           state->search.out.response->attributes[0].values->length < 2) {
+               status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+               goto failed;
        }
-       data = search.out.response->attributes[0].values;
+       data = state->search.out.response->attributes[0].values;
 
-       status = pull_netlogon_samlogon_response(data, mem_ctx, req->cldap->iconv_convenience,
+       status = pull_netlogon_samlogon_response(data, mem_ctx,
+                                                iconv_convenience,
                                                 &io->out.netlogon);
        if (!NT_STATUS_IS_OK(status)) {
-               return status;
+               goto failed;
        }
-       
+
        if (io->in.map_response) {
                map_netlogon_samlogon_response(&io->out.netlogon);
        }
-       return NT_STATUS_OK;
+
+       status =  NT_STATUS_OK;
+failed:
+       tevent_req_received(req);
+       return status;
 }
 
 /*
   sync cldap netlogon search
 */
-NTSTATUS cldap_netlogon(struct cldap_socket *cldap, 
-                       TALLOC_CTX *mem_ctx, struct cldap_netlogon *io)
+NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
+                       struct smb_iconv_convenience *iconv_convenience,
+                       TALLOC_CTX *mem_ctx,
+                       struct cldap_netlogon *io)
 {
-       struct cldap_request *req = cldap_netlogon_send(cldap, io);
-       return cldap_netlogon_recv(req, mem_ctx, io);
+       struct tevent_req *req;
+       NTSTATUS status;
+
+       if (!cldap->event.allow_poll) {
+               return NT_STATUS_INVALID_PIPE_STATE;
+       }
+
+       if (cldap->searches.list) {
+               return NT_STATUS_PIPE_BUSY;
+       }
+
+       req = cldap_netlogon_send(mem_ctx, cldap, io);
+       NT_STATUS_HAVE_NO_MEMORY(req);
+
+       if (!tevent_req_poll(req, cldap->event.ctx)) {
+               talloc_free(req);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       status = cldap_netlogon_recv(req, iconv_convenience, mem_ctx, io);
+       talloc_free(req);
+
+       return status;
 }
 
 
@@ -643,16 +1026,16 @@ NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
   send an empty reply (used on any error, so the client doesn't keep waiting
   or send the bad request again)
 */
-NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, 
+NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
                           uint32_t message_id,
-                          struct socket_address *src)
+                          struct tsocket_address *dest)
 {
        NTSTATUS status;
        struct cldap_reply reply;
        struct ldap_Result result;
 
        reply.messageid    = message_id;
-       reply.dest         = src;
+       reply.dest         = dest;
        reply.response     = NULL;
        reply.result       = &result;
 
@@ -667,9 +1050,9 @@ NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
   send an error reply (used on any error, so the client doesn't keep waiting
   or send the bad request again)
 */
-NTSTATUS cldap_error_reply(struct cldap_socket *cldap, 
+NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
                           uint32_t message_id,
-                          struct socket_address *src,
+                          struct tsocket_address *dest,
                           int resultcode,
                           const char *errormessage)
 {
@@ -678,7 +1061,7 @@ NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
        struct ldap_Result result;
 
        reply.messageid    = message_id;
-       reply.dest         = src;
+       reply.dest         = dest;
        reply.response     = NULL;
        reply.result       = &result;
 
@@ -695,9 +1078,10 @@ NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
 /*
   send a netlogon reply 
 */
-NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, 
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+                             struct smb_iconv_convenience *iconv_convenience,
                              uint32_t message_id,
-                             struct socket_address *src,
+                             struct tsocket_address *dest,
                              uint32_t version,
                              struct netlogon_samlogon_response *netlogon)
 {
@@ -708,13 +1092,15 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
        TALLOC_CTX *tmp_ctx = talloc_new(cldap);
        DATA_BLOB blob;
 
-       status = push_netlogon_samlogon_response(&blob, tmp_ctx, cldap->iconv_convenience,
+       status = push_netlogon_samlogon_response(&blob, tmp_ctx,
+                                                iconv_convenience,
                                                 netlogon);
        if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
                return status;
        }
        reply.messageid    = message_id;
-       reply.dest         = src;
+       reply.dest         = dest;
        reply.response     = &response;
        reply.result       = &result;
 
@@ -735,4 +1121,3 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
        return status;
 }
 
-
index 8951daa775a2a8c0285530038ba19a386f3ea824..111fa2cfc4514e072a0dd3ead3bcc7f19616000d 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "../lib/util/asn1.h"
 #include "../libcli/netlogon.h"
 
 struct ldap_message;
-
-enum cldap_request_state {CLDAP_REQUEST_SEND, 
-                         CLDAP_REQUEST_WAIT, 
-                         CLDAP_REQUEST_DONE,
-                         CLDAP_REQUEST_ERROR};
-
-/*
-  a cldap request packet
-*/
-struct cldap_request {
-       struct cldap_request *next, *prev;
-
-       struct cldap_socket *cldap;
-
-       enum cldap_request_state state;
-       NTSTATUS status;
-
-       /* where to send the request */
-       struct socket_address *dest;
-
-       /* timeout between retries (seconds) */
-       int timeout;
-       int num_retries;
-
-       bool is_reply;
-
-       /* the ldap message_id */
-       int message_id;
-
-       struct tevent_timer *te;
-
-       /* the encoded request */
-       DATA_BLOB encoded;
-
-       /* the reply data */
-       struct asn1_data *asn1;
-
-       /* information on what to do on completion */
-       struct {
-               void (*fn)(struct cldap_request *);
-               void *private_data;
-       } async;
+struct tsocket_address;
+struct cldap_socket;
+
+struct cldap_incoming {
+       int recv_errno;
+       uint8_t *buf;
+       size_t len;
+       struct tsocket_address *src;
+       struct ldap_message *ldap_msg;
 };
 
 /*
-  context structure for operations on cldap packets
-*/
-struct cldap_socket {
-       struct socket_context *sock;
-       struct tevent_context *event_ctx;
-       struct smb_iconv_convenience *iconv_convenience;
-
-       /* the fd event */
-       struct tevent_fd *fde;
-
-       /* a queue of outgoing requests */
-       struct cldap_request *send_queue;
-
-       /* mapping from message_id to pending request */
-       struct idr_context *idr;
-
-       /* what to do with incoming request packets */
-       struct {
-               void (*handler)(struct cldap_socket *, struct ldap_message *, 
-                               struct socket_address *);
-               void *private_data;
-       } incoming;
-};
-
-
-/*
- a general cldap search request  
+ a general cldap search request
 */
 struct cldap_search {
        struct {
                const char *dest_address;
                uint16_t dest_port;
                const char *filter;
-               const char **attributes;
+               const char * const *attributes;
                int timeout;
                int retries;
        } in;
@@ -111,39 +51,43 @@ struct cldap_search {
        } out;
 };
 
-struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx, 
-                                      struct tevent_context *event_ctx, 
-                                      struct smb_iconv_convenience *iconv_convenience);
+NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx,
+                          struct tevent_context *ev,
+                          const struct tsocket_address *local_addr,
+                          const struct tsocket_address *remote_addr,
+                          struct cldap_socket **_cldap);
+
 NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap,
-                                   void (*handler)(struct cldap_socket *, struct ldap_message *, 
-                                                   struct socket_address *),
+                                   void (*handler)(struct cldap_socket *,
+                                                   void *private_data,
+                                                   struct cldap_incoming *),
                                    void *private_data);
-struct cldap_request *cldap_search_send(struct cldap_socket *cldap, 
-                                       struct cldap_search *io);
-NTSTATUS cldap_search_recv(struct cldap_request *req, TALLOC_CTX *mem_ctx, 
+struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx,
+                                    struct cldap_socket *cldap,
+                                    const struct cldap_search *io);
+NTSTATUS cldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                           struct cldap_search *io);
-NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx, 
+NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx,
                      struct cldap_search *io);
 
-
 /*
   a general cldap reply
 */
 struct cldap_reply {
        uint32_t messageid;
-       struct socket_address *dest;
+       struct tsocket_address *dest;
        struct ldap_SearchResEntry *response;
        struct ldap_Result         *result;
 };
 
 NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io);
 
-NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, 
+NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
                           uint32_t message_id,
-                          struct socket_address *src);
-NTSTATUS cldap_error_reply(struct cldap_socket *cldap, 
+                          struct tsocket_address *dst);
+NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
                           uint32_t message_id,
-                          struct socket_address *src,
+                          struct tsocket_address *dst,
                           int resultcode,
                           const char *errormessage);
 
@@ -168,15 +112,22 @@ struct cldap_netlogon {
        } out;
 };
 
-struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap, 
-                                         struct cldap_netlogon *io);
-NTSTATUS cldap_netlogon_recv(struct cldap_request *req, 
-                            TALLOC_CTX *mem_ctx, 
+struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx,
+                                      struct cldap_socket *cldap,
+                                      const struct cldap_netlogon *io);
+NTSTATUS cldap_netlogon_recv(struct tevent_req *req,
+                            struct smb_iconv_convenience *iconv_convenience,
+                            TALLOC_CTX *mem_ctx,
                             struct cldap_netlogon *io);
-NTSTATUS cldap_netlogon(struct cldap_socket *cldap, 
-                       TALLOC_CTX *mem_ctx, struct cldap_netlogon *io);
-NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, 
+NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
+                       struct smb_iconv_convenience *iconv_convenience,
+                       TALLOC_CTX *mem_ctx,
+                       struct cldap_netlogon *io);
+
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+                             struct smb_iconv_convenience *iconv_convenience,
                              uint32_t message_id,
-                             struct socket_address *src,
+                             struct tsocket_address *dst,
                              uint32_t version,
                              struct netlogon_samlogon_response *netlogon);
+
index dc3431ab9fc6d1121a48f5a5976b64ed7811b8f0..1b87530af80fb494c4bbcd2934f2ea21b9765a09 100644 (file)
@@ -98,7 +98,7 @@ LIBCLI_DGRAM_OBJ_FILES = $(addprefix $(libclisrcdir)/dgram/, \
 
 [SUBSYSTEM::LIBCLI_CLDAP]
 PUBLIC_DEPENDENCIES = LIBCLI_LDAP
-PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBLDB LIBCLI_NETLOGON
+PRIVATE_DEPENDENCIES = LIBTSOCKET LIBSAMBA-UTIL UTIL_TEVENT LIBLDB LIBCLI_NETLOGON
 
 LIBCLI_CLDAP_OBJ_FILES = $(libclisrcdir)/cldap/cldap.o
 # PUBLIC_HEADERS += $(libclisrcdir)/cldap/cldap.h
index bf046745e6a3aacc48be95fbbc3dc56cb195e782..dbbabd6a6da636f8b9e97bf17d6d101aec5c4f34 100644 (file)
@@ -731,12 +731,12 @@ struct libnet_BecomeDC_state {
        struct libnet_BecomeDC_Callbacks callbacks;
 };
 
-static void becomeDC_recv_cldap(struct cldap_request *req);
+static void becomeDC_recv_cldap(struct tevent_req *req);
 
 static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
 {
        struct composite_context *c = s->creq;
-       struct cldap_request *req;
+       struct tevent_req *req;
 
        s->cldap.io.in.dest_address     = s->source_dsa.address;
        s->cldap.io.in.dest_port        = lp_cldap_port(s->libnet->lp_ctx);
@@ -749,25 +749,27 @@ static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
        s->cldap.io.in.version          = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        s->cldap.io.in.map_response     = true;
 
-       s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx, 
-                                         lp_iconv_convenience(s->libnet->lp_ctx));
-       if (composite_nomem(s->cldap.sock, c)) return;
+       c->status = cldap_socket_init(s, s->libnet->event_ctx,
+                                     NULL, NULL, &s->cldap.sock);//TODO
+       if (!composite_is_ok(c)) return;
 
-       req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+       req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
        if (composite_nomem(req, c)) return;
-       req->async.fn           = becomeDC_recv_cldap;
-       req->async.private_data = s;
+       tevent_req_set_callback(req, becomeDC_recv_cldap, s);
 }
 
 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
 
-static void becomeDC_recv_cldap(struct cldap_request *req)
+static void becomeDC_recv_cldap(struct tevent_req *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
+       struct libnet_BecomeDC_state *s = tevent_req_callback_data(req,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
 
-       c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
+       c->status = cldap_netlogon_recv(req,
+                                       lp_iconv_convenience(s->libnet->lp_ctx),
+                                       s, &s->cldap.io);
+       talloc_free(req);
        if (!composite_is_ok(c)) return;
 
        s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
index 4a32ab92ed58b4a1e6559ecfac473f254e29eac1..8a002b24a4b1e03346f8964743e65cdd8b196fa4 100644 (file)
@@ -56,8 +56,14 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_context *lctx, struct li
        search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        search.in.map_response = true;
 
-       cldap = cldap_socket_init(tmp_ctx, lctx->event_ctx, lp_iconv_convenience(lctx->lp_ctx));
-       status = cldap_netlogon(cldap, tmp_ctx, &search);
+       /* we want to use non async calls, so we're not passing an event context */
+       status = cldap_socket_init(tmp_ctx, NULL, NULL, NULL, &cldap);//TODO
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
+               r->out.error_string = NULL;
+               return status;
+       }
+       status = cldap_netlogon(cldap, lp_iconv_convenience(lctx->lp_ctx), tmp_ctx, &search);
        if (!NT_STATUS_IS_OK(status)
            || !search.out.netlogon.data.nt5_ex.client_site) {
                /*
index 3f92daab2817aa088b00f424ae7cf717e8aba4f1..e0e5e421151a87b56f8506403b9af47703fdd022 100644 (file)
@@ -250,12 +250,12 @@ struct libnet_UnbecomeDC_state {
        } dest_dsa;
 };
 
-static void unbecomeDC_recv_cldap(struct cldap_request *req);
+static void unbecomeDC_recv_cldap(struct tevent_req *req);
 
 static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
 {
        struct composite_context *c = s->creq;
-       struct cldap_request *req;
+       struct tevent_req *req;
 
        s->cldap.io.in.dest_address     = s->source_dsa.address;
        s->cldap.io.in.dest_port        = lp_cldap_port(s->libnet->lp_ctx);
@@ -268,25 +268,27 @@ static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
        s->cldap.io.in.version          = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        s->cldap.io.in.map_response     = true;
 
-       s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx,
-                                         lp_iconv_convenience(s->libnet->lp_ctx));
-       if (composite_nomem(s->cldap.sock, c)) return;
+       c->status = cldap_socket_init(s, s->libnet->event_ctx,
+                                     NULL, NULL, &s->cldap.sock);//TODO
+       if (!composite_is_ok(c)) return;
 
-       req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+       req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
        if (composite_nomem(req, c)) return;
-       req->async.fn           = unbecomeDC_recv_cldap;
-       req->async.private_data = s;
+       tevent_req_set_callback(req, unbecomeDC_recv_cldap, s);
 }
 
 static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s);
 
-static void unbecomeDC_recv_cldap(struct cldap_request *req)
+static void unbecomeDC_recv_cldap(struct tevent_req *req)
 {
-       struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private_data,
+       struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(req,
                                            struct libnet_UnbecomeDC_state);
        struct composite_context *c = s->creq;
 
-       c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
+       c->status = cldap_netlogon_recv(req,
+                                       lp_iconv_convenience(s->libnet->lp_ctx),
+                                       s, &s->cldap.io);
+       talloc_free(req);
        if (!composite_is_ok(c)) return;
 
        s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
index 1ddc628a5c643e6f1de23832fe7808a15a9dc7dd..98669288a8f392bf62bbe3659a2d6ef851417e21 100644 (file)
@@ -28,6 +28,7 @@
 #include "torture/torture.h"
 #include "lib/ldb/include/ldb.h"
 #include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
 
 #define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
 
@@ -45,12 +46,21 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        struct netlogon_samlogon_response n1;
        struct GUID guid;
        int i;
+       struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
+       struct tsocket_address *dest_addr;
+       int ret;
 
-       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       ret = tsocket_address_inet_from_strings(tctx, "ip",
+                                               dest,
+                                               lp_cldap_port(tctx->lp_ctx),
+                                               &dest_addr);
+
+       status = cldap_socket_init(tctx, NULL, NULL, dest_addr, &cldap);
+       CHECK_STATUS(status, NT_STATUS_OK);
 
        ZERO_STRUCT(search);
-       search.in.dest_address = dest;
-       search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+       search.in.dest_address = NULL;//dest;
+       search.in.dest_port = 0;//lp_cldap_port(tctx->lp_ctx);
        search.in.acct_control = -1;
        search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        search.in.map_response = true;
@@ -59,7 +69,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
 
        printf("Trying without any attributes\n");
        search = empty_search;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        n1 = search.out.netlogon;
@@ -72,7 +82,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        for (i=0;i<256;i++) {
                search.in.version = i;
                printf("Trying netlogon level %d\n", i);
-               status = cldap_netlogon(cldap, tctx, &search);
+               status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
                CHECK_STATUS(status, NT_STATUS_OK);
        }
 
@@ -80,19 +90,19 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        for (i=0;i<31;i++) {
                search.in.version = (1<<i);
                printf("Trying netlogon level 0x%x\n", i);
-               status = cldap_netlogon(cldap, tctx, &search);
+               status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
                CHECK_STATUS(status, NT_STATUS_OK);
        }
 
        search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP;
 
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        printf("Trying with User=NULL\n");
 
        search.in.user = NULL;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
@@ -100,20 +110,20 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with User=Administrator\n");
 
        search.in.user = "Administrator";
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
 
        search.in.version = NETLOGON_NT_VERSION_5;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        printf("Trying with User=NULL\n");
 
        search.in.user = NULL;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE);
@@ -121,7 +131,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with User=Administrator\n");
 
        search.in.user = "Administrator";
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
@@ -132,7 +142,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with a GUID\n");
        search.in.realm       = NULL;
        search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
        CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid);
@@ -141,13 +151,13 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        guid = GUID_random();
        search.in.user        = NULL;
        search.in.domain_guid = GUID_string(tctx, &guid);
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
 
        printf("Trying with a AAC\n");
        search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST;
        search.in.realm = n1.data.nt5_ex.dns_domain;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -155,7 +165,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with a zero AAC\n");
        search.in.acct_control = 0x0;
        search.in.realm = n1.data.nt5_ex.dns_domain;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -164,7 +174,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        search.in.acct_control = 0x0;
        search.in.user = "Administrator";
        search.in.realm = n1.data.nt5_ex.dns_domain;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator");
@@ -173,7 +183,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        search.in.user = NULL;
        search.in.acct_control = 0xFF00FF00;
        search.in.realm = n1.data.nt5_ex.dns_domain;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -181,14 +191,14 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with a user only\n");
        search = empty_search;
        search.in.user = "Administrator";
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
 
        printf("Trying with just a bad username\n");
        search.in.user = "___no_such_user___";
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
@@ -197,12 +207,12 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with just a bad domain\n");
        search = empty_search;
        search.in.realm = "___no_such_domain___";
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
 
        printf("Trying with a incorrect domain and correct guid\n");
        search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -210,7 +220,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
 
        printf("Trying with a incorrect domain and incorrect guid\n");
        search.in.domain_guid = GUID_string(tctx, &guid);
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -219,7 +229,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
        printf("Trying with a incorrect GUID and correct domain\n");
        search.in.domain_guid = GUID_string(tctx, &guid);
        search.in.realm = n1.data.nt5_ex.dns_domain;
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
        CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -239,10 +249,12 @@ static bool test_cldap_netlogon_flags(struct torture_context *tctx,
        struct cldap_netlogon search;
        struct netlogon_samlogon_response n1;
        uint32_t server_type;
+       struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
 
-       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
+       CHECK_STATUS(status, NT_STATUS_OK);
 
-       printf("Printing out netlogon server type flags:\n");
+       printf("Printing out netlogon server type flags: %s\n", dest);
 
        ZERO_STRUCT(search);
        search.in.dest_address = dest;
@@ -251,7 +263,7 @@ static bool test_cldap_netlogon_flags(struct torture_context *tctx,
        search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        search.in.map_response = true;
 
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        n1 = search.out.netlogon;
@@ -348,10 +360,12 @@ static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
        struct cldap_netlogon search;
        uint32_t server_type;
        struct netlogon_samlogon_response n1;
+       struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
 
        bool result = true;
 
-       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
+       CHECK_STATUS(status, NT_STATUS_OK);
 
        printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: ");
 
@@ -362,7 +376,7 @@ static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
        search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        search.in.map_response = true;
 
-       status = cldap_netlogon(cldap, tctx, &search);
+       status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        n1 = search.out.netlogon;
@@ -423,7 +437,8 @@ static bool test_cldap_generic(struct torture_context *tctx, const char *dest)
        const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL };
        const char *attrs3[] = { "netlogon", NULL };
 
-       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
+       CHECK_STATUS(status, NT_STATUS_OK);
 
        ZERO_STRUCT(search);
        search.in.dest_address = dest;
index ae2cb808360d93f3ee065496a524805ce4400eda..a422732b039100dc62975f6badd4b3b29eb10abb 100644 (file)
 */
 
 #include "includes.h"
-#include "lib/events/events.h"
+#include <tevent.h>
 #include "libcli/cldap/cldap.h"
 #include "libcli/resolve/resolve.h"
 #include "torture/torture.h"
 #include "param/param.h"
 
 struct bench_state {
+       struct torture_context *tctx;
        int pass_count, fail_count;
 };
 
-static void request_netlogon_handler(struct cldap_request *req)
+static void request_netlogon_handler(struct tevent_req *req)
 {
        struct cldap_netlogon io;
-       struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state);
+       struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
        NTSTATUS status;
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
        io.in.version = 6;
-       status = cldap_netlogon_recv(req, tmp_ctx, &io);
+       status = cldap_netlogon_recv(req,
+                                    lp_iconv_convenience(state->tctx->lp_ctx),
+                                    tmp_ctx, &io);
+       talloc_free(req);
        if (NT_STATUS_IS_OK(status)) {
                state->pass_count++;
        } else {
@@ -58,10 +62,13 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
        int timelimit = torture_setting_int(tctx, "timelimit", 10);
        struct cldap_netlogon search;
        struct bench_state *state;
+       NTSTATUS status;
 
-       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       status = cldap_socket_init(tctx, tctx->ev, NULL, NULL, &cldap);
+       torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
 
        state = talloc_zero(tctx, struct bench_state);
+       state->tctx = tctx;
 
        ZERO_STRUCT(search);
        search.in.dest_address = address;
@@ -72,11 +79,11 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
        printf("Running CLDAP/netlogon for %d seconds\n", timelimit);
        while (timeval_elapsed(&tv) < timelimit) {
                while (num_sent - (state->pass_count+state->fail_count) < 10) {
-                       struct cldap_request *req;
-                       req = cldap_netlogon_send(cldap, &search);
+                       struct tevent_req *req;
+                       req = cldap_netlogon_send(state, cldap, &search);
+
+                       tevent_req_set_callback(req, request_netlogon_handler, state);
 
-                       req->async.private_data = state;
-                       req->async.fn = request_netlogon_handler;
                        num_sent++;
                        if (num_sent % 50 == 0) {
                                if (torture_setting_bool(tctx, "progress", true)) {
@@ -88,11 +95,11 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
                        }
                }
 
-               event_loop_once(cldap->event_ctx);
+               tevent_loop_once(tctx->ev);
        }
 
        while (num_sent != (state->pass_count + state->fail_count)) {
-               event_loop_once(cldap->event_ctx);
+               tevent_loop_once(tctx->ev);
        }
 
        printf("%.1f queries per second (%d failures)  \n", 
@@ -103,13 +110,14 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
        return ret;
 }
 
-static void request_rootdse_handler(struct cldap_request *req)
+static void request_rootdse_handler(struct tevent_req *req)
 {
        struct cldap_search io;
-       struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state);
+       struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
        NTSTATUS status;
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
        status = cldap_search_recv(req, tmp_ctx, &io);
+       talloc_free(req);
        if (NT_STATUS_IS_OK(status)) {
                state->pass_count++;
        } else {
@@ -130,8 +138,10 @@ static bool bench_cldap_rootdse(struct torture_context *tctx, const char *addres
        int timelimit = torture_setting_int(tctx, "timelimit", 10);
        struct cldap_search search;
        struct bench_state *state;
+       NTSTATUS status;
 
-       cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       status = cldap_socket_init(tctx, tctx->ev, NULL, NULL, &cldap);
+       torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
 
        state = talloc_zero(tctx, struct bench_state);
 
@@ -145,11 +155,11 @@ static bool bench_cldap_rootdse(struct torture_context *tctx, const char *addres
        printf("Running CLDAP/rootdse for %d seconds\n", timelimit);
        while (timeval_elapsed(&tv) < timelimit) {
                while (num_sent - (state->pass_count+state->fail_count) < 10) {
-                       struct cldap_request *req;
-                       req = cldap_search_send(cldap, &search);
+                       struct tevent_req *req;
+                       req = cldap_search_send(state, cldap, &search);
+
+                       tevent_req_set_callback(req, request_rootdse_handler, state);
 
-                       req->async.private_data = state;
-                       req->async.fn = request_rootdse_handler;
                        num_sent++;
                        if (num_sent % 50 == 0) {
                                if (torture_setting_bool(tctx, "progress", true)) {
index 847b32827b8dd2739eb5d285e65f51f2132540ad..1aaf914ceb8af7e7e790eb10717e5e410be81682 100644 (file)
@@ -273,7 +273,12 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
        struct cldap_socket *cldap;
        struct cldap_netlogon search;
 
-       cldap = cldap_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+       status = cldap_socket_init(ctx, NULL, NULL, NULL, &cldap);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("failed to setup cldap socket - %s\n",
+                       nt_errstr(status));
+               return false;
+       }
 
        r.in.bind_handle                = &ctx->admin.drsuapi.bind_handle;
        r.in.level                      = 1;
@@ -311,7 +316,7 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
        search.in.acct_control = -1;
        search.in.version               = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
        search.in.map_response = true;
-       status = cldap_netlogon(cldap, ctx, &search);
+       status = cldap_netlogon(cldap, lp_iconv_convenience(tctx->lp_ctx), ctx, &search);
        if (!NT_STATUS_IS_OK(status)) {
                const char *errstr = nt_errstr(status);
                ctx->site_name = talloc_asprintf(ctx, "%s", "Default-First-Site-Name");