r7264: fix up the socket handling for abartlet. Still only udp, but it won't
authorAndrew Tridgell <tridge@samba.org>
Sat, 4 Jun 2005 05:35:27 +0000 (05:35 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:33 +0000 (13:17 -0500)
be hard to do tcp as well.
(This used to be commit 7cbb95d3f55dbaf9ca606655377682841e4c534d)

source4/kdc/config.mk
source4/kdc/hdb-ldb.c
source4/kdc/kdc.c
source4/kdc/kdc.h

index c6c4f4c5c10721bc13e5e75f84b93a0af452f036..220b7e633c9239eabe5bb5b3956ee0bd4be9bc0c 100644 (file)
@@ -1,12 +1,12 @@
-# CLDAP server subsystem
+# KDC server subsystem
 
 #######################
-# Start SUBSYSTEM CLDAPD
+# Start SUBSYSTEM KDC
 [SUBSYSTEM::KDC]
 INIT_OBJ_FILES = \
                kdc/kdc.o \
                kdc/hdb-ldb.o
 REQUIRED_SUBSYSTEMS = \
                SOCKET
-# End SUBSYSTEM CLDAPD
+# End SUBSYSTEM KDC
 #######################
index 601821fc42dc8fb0ef06b346e994d012158681e5..caa5a5c801c59a43c162ba705565e0799a0675c4 100644 (file)
 #include "includes.h"
 #include "kdc.h"
 #include "ads.h"
-#include <hdb.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <ldb.h>
-#include <talloc.h>
-
-#include <ctype.h>
+#include "hdb.h"
+#include "lib/ldb/include/ldb.h"
+#include "system/iconv.h"
 
 
 static const char * const krb5_attrs[] = {
index 1f807e90ac529179698a3f55aa41a5fd6db12f8f..21461c0f0986b435518a2670cf170ad52b381cb3 100644 (file)
 #include "lib/socket/socket.h"
 #include "kdc/kdc.h"
 #include "system/network.h"
+#include "dlinklist.h"
 
-/* 
- */
+/*
+  handle fd send events on a KDC socket
+*/
+static void kdc_send_handler(struct kdc_socket *kdc_socket)
+{
+       while (kdc_socket->send_queue) {
+               struct kdc_reply *rep = kdc_socket->send_queue;
+               NTSTATUS status;
+               size_t sendlen;
+
+               status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen, 0,
+                                      rep->dest_address, rep->dest_port);
+               if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+                       break;
+               }
+               
+               DLIST_REMOVE(kdc_socket->send_queue, rep);
+               talloc_free(rep);
+       }
 
-static void kdc_recv_handler(struct event_context *ev, struct fd_event *fde,
-                            struct kdc_socket *kdc_socket)
+       if (kdc_socket->send_queue == NULL) {
+               EVENT_FD_NOT_WRITEABLE(kdc_socket->fde);
+       }
+}
+
+
+/*
+  handle fd recv events on a KDC socket
+*/
+static void kdc_recv_handler(struct kdc_socket *kdc_socket)
 {
-       TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket);
        NTSTATUS status;
+       TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket);
        DATA_BLOB blob;
+       struct kdc_reply *rep;
        krb5_data reply;
        size_t nread, dsize;
        const char *src_addr;
        int src_port;
        struct sockaddr_in src_sock_addr;
        struct ipv4_addr addr;
-       
+
        status = socket_pending(kdc_socket->sock, &dsize);
        if (!NT_STATUS_IS_OK(status)) {
                talloc_free(tmp_ctx);
                return;
        }
-       
-       blob = data_blob_talloc(tmp_ctx, NULL, dsize);
+
+       blob = data_blob_talloc(kdc_socket, NULL, dsize);
        if (blob.data == NULL) {
+               /* hope this is a temporary low memory condition */
                talloc_free(tmp_ctx);
                return;
        }
-       
+
        status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread, 0,
                                 &src_addr, &src_port);
        if (!NT_STATUS_IS_OK(status)) {
@@ -84,18 +112,28 @@ static void kdc_recv_handler(struct event_context *ev, struct fd_event *fde,
                                          blob.data, blob.length, 
                                          &reply,
                                          src_addr,
-                                         &src_sock_addr) != -1) {
-               size_t sendlen = reply.length;
-               DATA_BLOB reply_blob;
-               reply_blob.data = reply.data;
-               reply_blob.length = reply.length;
-
-               /* Send the reply on it's way */
-               socket_sendto(kdc_socket->sock, &reply_blob, &sendlen, 0,
-                             src_addr, src_port);
+                                         (struct sockaddr *)&src_sock_addr) == -1) {
+               talloc_free(tmp_ctx);
+               return;
+       }
 
-               krb5_data_free(&reply);
+       /* queue a pending reply */
+       rep = talloc(kdc_socket, struct kdc_reply);
+       if (rep == NULL) {
+               talloc_free(tmp_ctx);
+               return;
+       }
+       rep->dest_address = talloc_steal(rep, src_addr);
+       rep->dest_port    = src_port;
+       rep->packet       = data_blob_talloc(rep, reply.data, reply.length);
+       if (rep->packet.data == NULL) {
+               talloc_free(rep);
+               talloc_free(tmp_ctx);
+               return;
        }
+
+       DLIST_ADD_END(kdc_socket->send_queue, rep, struct kdc_reply *);
+       EVENT_FD_WRITEABLE(kdc_socket->fde);
        talloc_free(tmp_ctx);
 }
 
@@ -107,12 +145,13 @@ static void kdc_socket_handler(struct event_context *ev, struct fd_event *fde,
 {
        struct kdc_socket *kdc_socket = talloc_get_type(private, struct kdc_socket);
        if (flags & EVENT_FD_WRITE) {
-               /* not sure on write events yet */
+               kdc_send_handler(kdc_socket);
        } else if (flags & EVENT_FD_READ) {
-               kdc_recv_handler(ev, fde, kdc_socket);
+               kdc_recv_handler(kdc_socket);
        }
 }
 
+
 /*
   start listening on the given address
 */
@@ -131,15 +170,14 @@ static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address)
        }
 
        kdc_socket->kdc = kdc;
+       kdc_socket->send_queue = NULL;
 
        talloc_steal(kdc_socket, kdc_socket->sock);
 
        kdc_socket->fde = event_add_fd(kdc->task->event_ctx, kdc, 
-                                      socket_get_fd(kdc_socket->sock), 0,
+                                      socket_get_fd(kdc_socket->sock), EVENT_FD_READ,
                                       kdc_socket_handler, kdc_socket);
 
-       EVENT_FD_READABLE(kdc_socket->fde);
-
        status = socket_listen(kdc_socket->sock, address, lp_krb5_port(), 0, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Failed to bind to %s:%d - %s\n", 
index 2289b504ccfa5f3a44f6f24b79708cec9e06f170..2e81679e576887528e0092f882eb8c46f89dbf1b 100644 (file)
 
 krb5_error_code hdb_ldb_create(krb5_context context, struct HDB **db, const char *arg);
 
+/* hold all the info needed to send a reply */
+struct kdc_reply {
+       struct kdc_reply *next, *prev;
+       const char *dest_address;
+       int dest_port;
+       DATA_BLOB packet;
+};
+
 /*
-  top level context structure for the cldap server
+  top level context structure for the kdc server
 */
 struct kdc_server {
        struct task_server *task;
@@ -36,16 +44,13 @@ struct kdc_server {
        krb5_context krb5_context;
 };
 
+/* hold information about one kdc socket */
 struct kdc_socket {
        struct socket_context *sock;
-       struct event_context *event_ctx;
-       
        struct kdc_server *kdc;
-
-       /* the fd event */
        struct fd_event *fde;
 
-       /* a queue of outgoing replies */
+       /* a queue of outgoing replies that have been deferred */
        struct kdc_reply *send_queue;
-
 };
+