r6744: added support for reply packets in libcli/cldap/
authorAndrew Tridgell <tridge@samba.org>
Thu, 12 May 2005 08:25:35 +0000 (08:25 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:16:40 +0000 (13:16 -0500)
(This used to be commit 992858e1b91c3ff05077afa8a7abe155198597d4)

source4/libcli/cldap/cldap.c
source4/libcli/cldap/cldap.h

index 75ce0a67db8526fb277dfe91f52dc7a73b224624..2f4d1e73a91a97f23aac9fd15285eca542e00d53 100644 (file)
@@ -51,7 +51,7 @@ static int cldap_request_destructor(void *ptr)
        if (req->state == CLDAP_REQUEST_SEND) {
                DLIST_REMOVE(req->cldap->send_queue, req);
        }
-       if (req->message_id != 0) {
+       if (!req->is_reply && req->message_id != 0) {
                idr_remove(req->cldap->idr, req->message_id);
                req->message_id = 0;
        }
@@ -191,13 +191,17 @@ static void cldap_socket_send(struct cldap_socket *cldap)
 
                DLIST_REMOVE(cldap->send_queue, req);
 
-               req->state = CLDAP_REQUEST_WAIT;
+               if (req->is_reply) {
+                       talloc_free(req);
+               } else {
+                       req->state = CLDAP_REQUEST_WAIT;
 
-               req->te = event_add_timed(cldap->event_ctx, req, 
-                                         timeval_current_ofs(req->timeout, 0),
-                                         cldap_request_timeout, req);
+                       req->te = event_add_timed(cldap->event_ctx, req, 
+                                                 timeval_current_ofs(req->timeout, 0),
+                                                 cldap_request_timeout, req);
 
-               EVENT_FD_READABLE(cldap->fde);
+                       EVENT_FD_READABLE(cldap->fde);
+               }
        }
 
        EVENT_FD_NOT_WRITEABLE(cldap->fde);
@@ -293,6 +297,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
        req->state       = CLDAP_REQUEST_SEND;
        req->timeout     = io->in.timeout;
        req->num_retries = io->in.retries;
+       req->is_reply    = False;
 
        req->dest_addr = talloc_strdup(req, io->in.dest_address);
        if (req->dest_addr == NULL) goto failed;
@@ -303,7 +308,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
 
        talloc_set_destructor(req, cldap_request_destructor);
 
-       msg.mem_ctx         = cldap;
+       msg.mem_ctx         = req;
        msg.messageid       = req->message_id;
        msg.type            = LDAP_TAG_SearchRequest;
        msg.num_controls    = 0;
@@ -338,6 +343,78 @@ failed:
        return NULL;
 }
 
+
+/*
+  queue a cldap reply for send
+*/
+NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
+{
+       struct ldap_message msg;
+       struct cldap_request *req;
+       DATA_BLOB blob1, blob2;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+       req = talloc_zero(cldap, struct cldap_request);
+       if (req == NULL) goto failed;
+
+       req->cldap       = cldap;
+       req->state       = CLDAP_REQUEST_SEND;
+       req->is_reply    = True;
+
+       req->dest_addr = talloc_strdup(req, io->dest_address);
+       if (req->dest_addr == NULL) goto failed;
+       req->dest_port = io->dest_port;
+
+       talloc_set_destructor(req, cldap_request_destructor);
+
+       msg.mem_ctx         = req;
+       msg.messageid       = io->messageid;
+       msg.num_controls    = 0;
+       msg.controls        = NULL;
+       
+       if (io->response) {
+               msg.type = LDAP_TAG_SearchResultEntry;
+               msg.r.SearchResultEntry = *io->response;
+
+               if (!ldap_encode(&msg, &blob1)) {
+                       DEBUG(0,("Failed to encode cldap message to %s:%d\n",
+                                req->dest_addr, req->dest_port));
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto failed;
+               }
+               talloc_steal(req, blob1.data);
+       } else {
+               blob1 = data_blob(NULL, 0);
+       }
+
+       msg.type = LDAP_TAG_SearchResultDone;
+       msg.r.SearchResultDone = *io->result;
+
+       if (!ldap_encode(&msg, &blob2)) {
+               DEBUG(0,("Failed to encode cldap message to %s:%d\n",
+                        req->dest_addr, req->dest_port));
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto failed;
+       }
+       talloc_steal(req, blob2.data);
+
+       req->encoded = data_blob_talloc(req, NULL, blob1.length + blob2.length);
+       if (req->encoded.data == NULL) goto failed;
+
+       memcpy(req->encoded.data, blob1.data, blob1.length);
+       memcpy(req->encoded.data+blob1.length, blob2.data, blob2.length);
+
+       DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *);
+
+       EVENT_FD_WRITEABLE(cldap->fde);
+
+       return NT_STATUS_OK;
+
+failed:
+       talloc_free(req);
+       return status;
+}
+
 /*
   receive a cldap reply
 */
@@ -490,3 +567,78 @@ NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
        struct cldap_request *req = cldap_netlogon_send(cldap, io);
        return cldap_netlogon_recv(req, mem_ctx, io);
 }
+
+
+/*
+  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, 
+                          uint32_t message_id,
+                          const char *src_address, int src_port)
+{
+       NTSTATUS status;
+       struct cldap_reply reply;
+       struct ldap_Result result;
+
+       reply.messageid    = message_id;
+       reply.dest_address = src_address;
+       reply.dest_port    = src_port;
+       reply.response     = NULL;
+       reply.result       = &result;
+
+       ZERO_STRUCT(result);
+
+       status = cldap_reply_send(cldap, &reply);
+
+       return status;
+}
+
+
+/*
+  send a netlogon reply 
+*/
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, 
+                             uint32_t message_id,
+                             const char *src_address, int src_port,
+                             uint32_t version,
+                             union nbt_cldap_netlogon *netlogon)
+{
+       NTSTATUS status;
+       struct cldap_reply reply;
+       struct ldap_SearchResEntry response;
+       struct ldap_Result result;
+       TALLOC_CTX *tmp_ctx = talloc_new(cldap);
+       DATA_BLOB blob;
+
+       status = ndr_push_union_blob(&blob, tmp_ctx, netlogon, version & 0xF, 
+                                    (ndr_push_flags_fn_t)ndr_push_nbt_cldap_netlogon);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
+               return status;
+       }
+
+       reply.messageid    = message_id;
+       reply.dest_address = src_address;
+       reply.dest_port    = src_port;
+       reply.response     = &response;
+       reply.result       = &result;
+
+       ZERO_STRUCT(result);
+
+       response.dn = "";
+       response.num_attributes = 1;
+       response.attributes = talloc(tmp_ctx, struct ldap_attribute);
+       NT_STATUS_HAVE_NO_MEMORY(response.attributes);
+       response.attributes->name = "netlogon";
+       response.attributes->num_values = 1;
+       response.attributes->values = &blob;
+
+       status = cldap_reply_send(cldap, &reply);
+
+       talloc_free(tmp_ctx);
+
+       return status;
+}
+
+
index 8a678b4539a54bf517c10b3268462425058a2467..fbdaada8c9e06a1f3157c53a96327a00e0adfd59 100644 (file)
@@ -46,6 +46,8 @@ struct cldap_request {
        int timeout;
        int num_retries;
 
+       BOOL is_reply;
+
        /* the ldap message_id */
        int message_id;
 
@@ -120,6 +122,19 @@ 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;
+       const char *dest_address;
+       int dest_port;
+       struct ldap_SearchResEntry *response;
+       struct ldap_Result         *result;
+};
+
+NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io);
+
 /*
   a netlogon cldap request  
 */
@@ -142,3 +157,13 @@ NTSTATUS cldap_netlogon_recv(struct cldap_request *req,
                             struct cldap_netlogon *io);
 NTSTATUS cldap_netlogon(struct cldap_socket *cldap, 
                        TALLOC_CTX *mem_ctx, struct cldap_netlogon *io);
+
+
+NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, 
+                          uint32_t message_id,
+                          const char *src_address, int src_port);
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, 
+                             uint32_t message_id,
+                             const char *src_address, int src_port,
+                             uint32_t version,
+                             union nbt_cldap_netlogon *netlogon);