Merge users/raeburn/branches/network-merge
authorKen Raeburn <raeburn@mit.edu>
Wed, 17 Mar 2010 06:00:56 +0000 (06:00 +0000)
committerKen Raeburn <raeburn@mit.edu>
Wed, 17 Mar 2010 06:00:56 +0000 (06:00 +0000)
Re-integrates the forked versions of network.c in kdc and
kadmin/server.  Server-specific initialization and SIGHUP-reset code
is moved into other source files; the more generic network-servicing
code is merged and moved into apputils library already used by both
programs.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23811 dc483132-0cff-0310-8789-dd5450dbe970

20 files changed:
src/include/net-server.h [new file with mode: 0644]
src/kadmin/server/Makefile.in
src/kadmin/server/deps
src/kadmin/server/misc.c
src/kadmin/server/misc.h
src/kadmin/server/ovsec_kadmd.c
src/kadmin/server/schpw.c
src/kdc/Makefile.in
src/kdc/deps
src/kdc/dispatch.c
src/kdc/extern.c
src/kdc/extern.h
src/kdc/kdc_util.c
src/kdc/kdc_util.h
src/kdc/main.c
src/kdc/network.c [deleted file]
src/lib/apputils/Makefile.in
src/lib/apputils/deps
src/lib/apputils/dummy.c [deleted file]
src/lib/apputils/net-server.c [moved from src/kadmin/server/network.c with 90% similarity]

diff --git a/src/include/net-server.h b/src/include/net-server.h
new file mode 100644 (file)
index 0000000..02f35e1
--- /dev/null
@@ -0,0 +1,50 @@
+/* */
+
+#ifndef NET_SERVER_H
+#define NET_SERVER_H
+
+typedef struct _krb5_fulladdr {
+    krb5_address *      address;
+    krb5_ui_4           port;
+} krb5_fulladdr;
+
+/* exported from network.c */
+extern volatile int signal_requests_exit, signal_requests_reset;
+void init_addr(krb5_fulladdr *, struct sockaddr *);
+krb5_error_code add_udp_port(int port);
+krb5_error_code add_tcp_port(int port);
+krb5_error_code add_rpc_service(int port, u_long prognum, u_long versnum,
+                                void (*dispatch)());
+krb5_error_code setup_network(void *handle, const char *prog);
+krb5_error_code listen_and_process(void *handle, const char *prog,
+                                  void (*reset)(void));
+void closedown_network(void);
+
+/* to be supplied by the server application */
+
+/*
+ * Two routines for processing an incoming message and getting a
+ * result to send back.
+ *
+ * The first, dispatch(), is for normal processing of a request.  The
+ * second, make_toolong_error(), is obviously for generating an error
+ * to send back when the incoming message is bigger than
+ * listen_and_process can accept.
+ */
+krb5_error_code dispatch (void *handle,
+                         struct sockaddr *local_addr,
+                         const krb5_fulladdr *remote_addr,
+                         krb5_data *request,
+                         krb5_data **response,
+                         int is_tcp);
+krb5_error_code make_toolong_error (void *handle, krb5_data **);
+
+/*
+ * Contexts are needed in lots of places.  Opaque application-provided
+ * handles are passed around in lots of place, but contexts are not.
+ * For now, we'll require that the application provide us an easy way
+ * to get at a context; eventually it should probably be explicity.
+ */
+krb5_context get_context(void *handle);
+
+#endif /* NET_SERVER_H */
index ec30c77691ec86c27b44ec15a2e1a026e389509c..d3111da4a119407e911a9a75acba968c297469c9 100644 (file)
@@ -11,13 +11,13 @@ PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
 PROG = kadmind
-OBJS = kadm_rpc_svc.o server_stubs.o ovsec_kadmd.o schpw.o misc.o ipropd_svc.o network.o
-SRCS = kadm_rpc_svc.c server_stubs.c ovsec_kadmd.c schpw.c misc.c ipropd_svc.c network.c
+OBJS = kadm_rpc_svc.o server_stubs.o ovsec_kadmd.o schpw.o misc.o ipropd_svc.o
+SRCS = kadm_rpc_svc.c server_stubs.c ovsec_kadmd.c schpw.c misc.c ipropd_svc.c
 
 all:: $(PROG)
 
 $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
-       $(CC_LINK) -o $(PROG) $(OBJS) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) $(APPUTILS_LIB)
+       $(CC_LINK) -o $(PROG) $(OBJS) $(APPUTILS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
 
 install::
        $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(SERVER_BINDIR)/$(PROG)
index e306438180a4dba0a858ebb4dcc1accd8d7b49bc..8f73320f4812e83775e30ce731b059d381158989 100644 (file)
@@ -14,7 +14,7 @@ $(OUTPRE)kadm_rpc_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \
   $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \
   $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
-  kadm_rpc_svc.c misc.h
+  $(top_srcdir)/include/net-server.h kadm_rpc_svc.c misc.h
 $(OUTPRE)server_stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \
   $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \
@@ -28,7 +28,8 @@ $(OUTPRE)server_stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
   $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
   $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \
-  $(top_srcdir)/include/krb5.h misc.h server_stubs.c
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/net-server.h \
+  misc.h server_stubs.c
 $(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \
   $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
@@ -52,15 +53,17 @@ $(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_kt.h \
   $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/gssapi/generic/gssapiP_generic.h \
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/net-server.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  $(top_srcdir)/lib/gssapi/generic/gssapiP_generic.h \
   $(top_srcdir)/lib/gssapi/generic/gssapi_ext.h $(top_srcdir)/lib/gssapi/generic/gssapi_generic.h \
   $(top_srcdir)/lib/gssapi/krb5/gssapiP_krb5.h misc.h \
   ovsec_kadmd.c
 $(OUTPRE)schpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
-  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
-  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
+  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
+  $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
   $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \
   $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
@@ -74,8 +77,8 @@ $(OUTPRE)schpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  misc.h schpw.c
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h misc.h schpw.c
 $(OUTPRE)misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
   $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
@@ -94,8 +97,8 @@ $(OUTPRE)misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  misc.c misc.h
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h misc.c misc.h
 $(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \
   $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
@@ -112,27 +115,5 @@ $(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-platform.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \
-  $(top_srcdir)/lib/kadm5/srv/server_acl.h ipropd_svc.c \
-  misc.h
-$(OUTPRE)network.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
-  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \
-  $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
-  $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \
-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \
-  $(top_srcdir)/include/cm.h $(top_srcdir)/include/fake-addrinfo.h \
-  $(top_srcdir)/include/foreachaddr.h $(top_srcdir)/include/gssrpc/auth.h \
-  $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
-  $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \
-  $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
-  $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
-  $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \
-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
-  $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h misc.h network.c
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/lib/kadm5/srv/server_acl.h \
+  ipropd_svc.c misc.h
index 375fbd151446b813320cb0470472a8855190090e..b9212fa0f2a27c17006a8909d44a7db72bc6a103 100644 (file)
@@ -9,6 +9,7 @@
 #include    <kadm5/server_internal.h>
 #include    <kadm5/server_acl.h>
 #include    "misc.h"
+#include    "net-server.h"
 
 /*
  * Function: chpass_principal_wrapper_3
@@ -224,3 +225,47 @@ trunc_name(size_t *len, char **dots)
     *dots = *len > MAXPRINCLEN ? "..." : "";
     *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len;
 }
+
+krb5_error_code
+make_toolong_error (void *handle, krb5_data **out)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
+
+    retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec);
+    if (retval)
+        return retval;
+    errpkt.error = KRB_ERR_FIELD_TOOLONG;
+    retval = krb5_build_principal(server_handle->context, &errpkt.server,
+                                  strlen(server_handle->params.realm),
+                                  server_handle->params.realm,
+                                  "kadmin", "changepw", NULL);
+    if (retval)
+        return retval;
+    errpkt.client = NULL;
+    errpkt.cusec = 0;
+    errpkt.ctime = 0;
+    errpkt.text.length = 0;
+    errpkt.text.data = 0;
+    errpkt.e_data.length = 0;
+    errpkt.e_data.data = 0;
+    scratch = malloc(sizeof(*scratch));
+    if (scratch == NULL)
+        return ENOMEM;
+    retval = krb5_mk_error(server_handle->context, &errpkt, scratch);
+    if (retval) {
+        free(scratch);
+        return retval;
+    }
+
+    *out = scratch;
+    return 0;
+}
+
+krb5_context get_context(void *handle)
+{
+    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
+    return server_handle->context;
+}
index 10e6054dbbaf4fa9180416e16a73c2e3fcf22e88..35f299401b8c3d9cf9d162196d53bfd2ed55976a 100644 (file)
@@ -7,10 +7,7 @@
 #ifndef _MISC_H
 #define _MISC_H 1
 
-typedef struct _krb5_fulladdr {
-    krb5_address *      address;
-    krb5_ui_4           port;
-} krb5_fulladdr;
+#include "net-server.h"         /* for krb5_fulladdr */
 
 void
 log_badauth(OM_uint32 major, OM_uint32 minor,
@@ -64,18 +61,13 @@ gss_to_krb5_name_1(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name,
                    krb5_principal *princ, gss_buffer_t gss_str);
 
 
-extern volatile int signal_request_exit;
-extern volatile int signal_request_hup;
-
 void reset_db(void);
 
 void log_badauth(OM_uint32 major, OM_uint32 minor,
                  struct sockaddr_in *addr, char *data);
 
 /* network.c */
-krb5_error_code setup_network(void *handle, const char *prog);
-krb5_error_code listen_and_process(void *handle, const char *prog);
-krb5_error_code closedown_network(void *handle, const char *prog);
+#include "net-server.h"
 
 
 void
index bcc4f16cd62cd802715f058d89e8b6a263ba6f92..417363794ce8d16d799f18a269cc9ad04eb3033b 100644 (file)
@@ -72,8 +72,6 @@ void    request_pure_clear(int);
 extern int daemon(int, int);
 #endif
 
-volatile int    signal_request_exit = 0;
-volatile int    signal_request_hup = 0;
 void    setup_signal_handlers(iprop_role iproprole);
 void    request_exit(int);
 void    request_hup(int);
@@ -383,7 +381,20 @@ int main(int argc, char *argv[])
         exit(1);
     }
 
-    if ((ret = setup_network(global_server_handle, whoami))) {
+#define server_handle ((kadm5_server_handle_t)global_server_handle)
+    if ((ret = add_udp_port(server_handle->params.kpasswd_port))
+        || (ret = add_tcp_port(server_handle->params.kpasswd_port))
+        || (ret = add_rpc_service(server_handle->params.kadmind_port,
+                                  KADM, KADMVERS, kadm_1))
+#ifndef DISABLE_IPROP
+        || (server_handle->params.iprop_enabled
+            ? (ret = add_rpc_service(server_handle->params.iprop_port,
+                                     KRB5_IPROP_PROG, KRB5_IPROP_VERS,
+                                     krb5_iprop_prog_1))
+            : 0)
+#endif
+#undef server_handle
+        || (ret = setup_network(global_server_handle, whoami))) {
         const char *e_txt = krb5_get_error_message (context, ret);
         krb5_klog_syslog(LOG_ERR, "%s: %s while initializing network, aborting",
                          whoami, e_txt);
@@ -632,13 +643,13 @@ kterr:
     if (nofork)
         fprintf(stderr, "%s: starting...\n", whoami);
 
-    listen_and_process(global_server_handle, whoami);
+    listen_and_process(global_server_handle, whoami, reset_db);
     krb5_klog_syslog(LOG_INFO, "finished, exiting");
 
     /* Clean up memory, etc */
     svcauth_gssapi_unset_names();
     kadm5_destroy(global_server_handle);
-    closedown_network(global_server_handle, whoami);
+    closedown_network();
     kadm5int_acl_finish(context, 0);
     if(gss_changepw_name) {
         (void) gss_release_name(&OMret, &gss_changepw_name);
@@ -765,12 +776,12 @@ void request_pure_clear(int signum)
  * Requires:
  * Effects:
  * Modifies:
- *      sets signal_request_hup to one
+ *      sets signal_requests_reset to one
  */
 
 void request_hup(int signum)
 {
-    signal_request_hup = 1;
+    signal_requests_reset = 1;
     return;
 }
 
@@ -783,7 +794,7 @@ void request_hup(int signum)
  * Requires:
  * Effects:
  *
- * Currently, just sets signal_request_reset to 0.  The kdb and adb
+ * Currently, just sets signal_requests_reset to 0.  The kdb and adb
  * libraries used to be sufficiently broken that it was prudent to
  * close and reopen the databases periodically.  They are no longer
  * that broken, so this function is not necessary.
@@ -815,17 +826,17 @@ void reset_db(void)
  * Arguments:
  * Requires:
  * Effects:
- *      modifies signal_request_exit which ideally makes the server exit
+ *      modifies signal_requests_exit which ideally makes the server exit
  *      at some point.
  *
  * Modifies:
- *      signal_request_exit
+ *      signal_requests_exit
  */
 
 void request_exit(int signum)
 {
     krb5_klog_syslog(LOG_DEBUG, "Got signal to request exit");
-    signal_request_exit = 1;
+    signal_requests_exit = 1;
     return;
 }
 
index c1b22173250a0edd06a9480d3e78ef82866e303b..1124445b4fd98b9a398a75fd8a216da99defa716 100644 (file)
@@ -6,6 +6,8 @@
 #include <stdio.h>
 #include <errno.h>
 
+#include "kadm5/server_internal.h" /* XXX for kadm5_server_handle_t */
+
 #include "misc.h"
 
 #ifndef GETSOCKNAME_ARG3_TYPE
@@ -476,3 +478,60 @@ bailout:
 
     return(ret);
 }
+
+/* Dispatch routine for set/change password */
+krb5_error_code
+dispatch(void *handle,
+         struct sockaddr *local_saddr, const krb5_fulladdr *remote_faddr,
+         krb5_data *request, krb5_data **response, int is_tcp)
+{
+    krb5_error_code ret;
+    krb5_keytab kt = NULL;
+    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
+    krb5_fulladdr local_faddr;
+    krb5_address **local_kaddrs = NULL, local_kaddr_buf;
+
+    *response = NULL;
+
+    if (local_saddr == NULL) {
+        ret = krb5_os_localaddr(server_handle->context, &local_kaddrs);
+        if (ret != 0)
+            goto cleanup;
+
+        local_faddr.address = local_kaddrs[0];
+        local_faddr.port = 0;
+    } else {
+        local_faddr.address = &local_kaddr_buf;
+        init_addr(&local_faddr, local_saddr);
+    }
+
+    ret = krb5_kt_resolve(server_handle->context, "KDB:", &kt);
+    if (ret != 0) {
+        krb5_klog_syslog(LOG_ERR, "chpw: Couldn't open admin keytab %s",
+                         krb5_get_error_message(server_handle->context, ret));
+        goto cleanup;
+    }
+
+    *response = (krb5_data *)malloc(sizeof(krb5_data));
+    if (*response == NULL) {
+        ret = ENOMEM;
+        goto cleanup;
+    }
+
+    ret = process_chpw_request(server_handle->context,
+                               handle,
+                               server_handle->params.realm,
+                               kt,
+                               &local_faddr,
+                               remote_faddr,
+                               request,
+                               *response);
+
+cleanup:
+    if (local_kaddrs != NULL)
+        krb5_free_addresses(server_handle->context, local_kaddrs);
+
+    krb5_kt_close(server_handle->context, kt);
+
+    return ret;
+}
index 5c0343d96793efc2e8343fc9bae1d86364e04a52..49e4a35a481c733fc8f8c860cc10baf8bfb7c638 100644 (file)
@@ -26,7 +26,6 @@ SRCS= \
        $(srcdir)/kdc_util.c \
        $(srcdir)/kdc_preauth.c \
        $(srcdir)/main.c \
-       $(srcdir)/network.c \
        $(srcdir)/policy.c \
        $(srcdir)/extern.c \
        $(srcdir)/replay.c \
@@ -41,7 +40,6 @@ OBJS= \
        kdc_util.o \
        kdc_preauth.o \
        main.o \
-       network.o \
        policy.o \
        extern.o \
        replay.o \
@@ -61,7 +59,7 @@ kdc5_err.h: kdc5_err.et
 kdc5_err.o: kdc5_err.h
 
 krb5kdc: $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB)
-       $(CC_LINK) -o krb5kdc $(OBJS) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) $(APPUTILS_LIB)
+       $(CC_LINK) -o krb5kdc $(OBJS) $(APPUTILS_LIB) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS)
 
 rtest: $(RT_OBJS) $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS)
        $(CC_LINK) -o rtest $(RT_OBJS) $(KDB5_LIBS) $(KADM_COMM_LIBS) $(KRB5_BASE_LIBS)
index bd3b4e021f1b01f1e042427e9153f7a73ab93a09..636090565291439470a7660b66a773ed9a8e22c4 100644 (file)
@@ -11,9 +11,9 @@ $(OUTPRE)dispatch.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
   $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h dispatch.c extern.h \
-  kdc_util.h
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/net-server.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  dispatch.c extern.h kdc_util.h
 $(OUTPRE)do_as_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm.h \
@@ -24,8 +24,9 @@ $(OUTPRE)do_as_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  do_as_req.c extern.h kdc_util.h policy.h
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h do_as_req.c extern.h \
+  kdc_util.h policy.h
 $(OUTPRE)do_tgs_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \
@@ -35,9 +36,9 @@ $(OUTPRE)do_tgs_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
   $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h do_tgs_req.c extern.h \
-  kdc_util.h policy.h
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/net-server.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  do_tgs_req.c extern.h kdc_util.h policy.h
 $(OUTPRE)fast_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
@@ -47,8 +48,9 @@ $(OUTPRE)fast_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  extern.h fast_util.c kdc_util.h
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h extern.h fast_util.c \
+  kdc_util.h
 $(OUTPRE)kdc_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm.h \
@@ -59,8 +61,9 @@ $(OUTPRE)kdc_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  extern.h kdc_util.c kdc_util.h
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h extern.h kdc_util.c \
+  kdc_util.h
 $(OUTPRE)kdc_preauth.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../include/krb5/preauth_plugin.h \
@@ -71,8 +74,9 @@ $(OUTPRE)kdc_preauth.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  extern.h kdc_preauth.c kdc_util.h
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h extern.h kdc_preauth.c \
+  kdc_util.h
 $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm.h \
@@ -83,22 +87,9 @@ $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/kdb_kt.h $(top_srcdir)/include/krb5.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h extern.h kdc5_err.h \
-  kdc_util.h main.c
-$(OUTPRE)network.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \
-  $(top_srcdir)/include/cm.h $(top_srcdir)/include/fake-addrinfo.h \
-  $(top_srcdir)/include/foreachaddr.h $(top_srcdir)/include/k5-buf.h \
-  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
-  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
-  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
-  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
-  $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/net-server.h \
   $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  extern.h kdc5_err.h kdc_util.h network.c
+  extern.h kdc5_err.h kdc_util.h main.c
 $(OUTPRE)policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
@@ -108,8 +99,9 @@ $(OUTPRE)policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  extern.h kdc_util.h policy.c
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h extern.h kdc_util.h \
+  policy.c
 $(OUTPRE)extern.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
@@ -130,8 +122,9 @@ $(OUTPRE)replay.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
-  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  extern.h kdc_util.h replay.c
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h extern.h kdc_util.h \
+  replay.c
 $(OUTPRE)kdc_authdata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \
@@ -141,6 +134,6 @@ $(OUTPRE)kdc_authdata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
   $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h extern.h kdc_authdata.c \
-  kdc_util.h
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/net-server.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  extern.h kdc_authdata.c kdc_util.h
index a8d95229d133db80274b860e5823bb6c091ffae2..207fa390ad17309de493736f19b246d90134a4c5 100644 (file)
 
 static krb5_int32 last_usec = 0, last_os_random = 0;
 
+static krb5_error_code make_too_big_error (krb5_data **out);
+
 krb5_error_code
-dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response)
+dispatch(void *cb, struct sockaddr *local_saddr, const krb5_fulladdr *from,
+         krb5_data *pkt, krb5_data **response, int is_tcp)
 {
 
     krb5_error_code retval;
@@ -55,6 +58,9 @@ dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response)
         const char *name = 0;
         char buf[46];
 
+        if (is_tcp == 0 && (*response)->length > max_dgram_reply_size)
+            goto too_big_for_udp;
+
         name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype),
                           from->address->contents, buf, sizeof (buf));
         if (name == 0)
@@ -109,5 +115,49 @@ dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response)
         kdc_insert_lookaside(pkt, *response);
 #endif
 
+    if (is_tcp == 0 && (*response)->length > max_dgram_reply_size) {
+    too_big_for_udp:
+        krb5_free_data(kdc_context, *response);
+        retval = make_too_big_error(response);
+        if (retval) {
+            krb5_klog_syslog(LOG_ERR,
+                             "error constructing KRB_ERR_RESPONSE_TOO_BIG error: %s",
+                             error_message(retval));
+        }
+    }
+
     return retval;
 }
+
+static krb5_error_code
+make_too_big_error (krb5_data **out)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+
+    *out = NULL;
+    memset(&errpkt, 0, sizeof(errpkt));
+
+    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
+    if (retval)
+        return retval;
+    errpkt.error = KRB_ERR_RESPONSE_TOO_BIG;
+    errpkt.server = tgs_server;
+    errpkt.client = NULL;
+    errpkt.text.length = 0;
+    errpkt.text.data = 0;
+    errpkt.e_data.length = 0;
+    errpkt.e_data.data = 0;
+    scratch = malloc(sizeof(*scratch));
+    if (scratch == NULL)
+        return ENOMEM;
+    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    if (retval) {
+        free(scratch);
+        return retval;
+    }
+
+    *out = scratch;
+    return 0;
+}
index 763adf57d728842454e0084e66da571e389b5ac5..effa42579a7c8dddea58350efafb739f7603863e 100644 (file)
@@ -40,6 +40,3 @@ krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */
 krb5_rcache     kdc_rcache = (krb5_rcache) NULL;
 krb5_keyblock   psr_key;
 krb5_int32      max_dgram_reply_size = MAX_DGRAM_SIZE;
-
-volatile int signal_requests_exit = 0;  /* gets set when signal hits */
-volatile int signal_requests_hup = 0;   /* ditto */
index 2f5dc0b9cd0b889897c9ceee34130c143d30520b..41ed439b84f77f5a6bde1f41ec7a272d17dabd82 100644 (file)
@@ -106,7 +106,4 @@ extern const int        kdc_modifies_kdb;
 extern krb5_int32       max_dgram_reply_size; /* maximum datagram size */
 
 extern const int        vague_errors;
-
-extern volatile int signal_requests_exit;
-extern volatile int signal_requests_hup;
 #endif /* __KRB5_KDC_EXTERN__ */
index d63bba2532250137ace56a2a157ba8d561059b3e..6fa2d73a2f68449691bffc3c1429b32dfefdb54a 100644 (file)
@@ -63,6 +63,7 @@
 #include <syslog.h>
 #include "adm.h"
 #include "adm_proto.h"
+#include "net-server.h"
 #include <limits.h>
 
 #ifdef USE_RCACHE
@@ -2771,3 +2772,50 @@ krb5int_get_domain_realm_mapping(krb5_context context,
     *realmsp = retrealms;
     return 0;
 }
+
+krb5_error_code
+make_toolong_error (void *handle, krb5_data **out)
+{
+    krb5_error errpkt;
+    krb5_error_code retval;
+    krb5_data *scratch;
+
+    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
+    if (retval)
+        return retval;
+    errpkt.error = KRB_ERR_FIELD_TOOLONG;
+    errpkt.server = tgs_server;
+    errpkt.client = NULL;
+    errpkt.cusec = 0;
+    errpkt.ctime = 0;
+    errpkt.text.length = 0;
+    errpkt.text.data = 0;
+    errpkt.e_data.length = 0;
+    errpkt.e_data.data = 0;
+    scratch = malloc(sizeof(*scratch));
+    if (scratch == NULL)
+        return ENOMEM;
+    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+    if (retval) {
+        free(scratch);
+        return retval;
+    }
+
+    *out = scratch;
+    return 0;
+}
+
+krb5_context get_context(void *handle)
+{
+    return kdc_context;
+}
+
+void reset_for_hangup()
+{
+    int k;
+
+    for (k = 0; k < kdc_numrealms; k++)
+        krb5_db_invoke(kdc_realmlist[k]->realm_context,
+                       KRB5_KDB_METHOD_REFRESH_POLICY,
+                       NULL, NULL);
+}
index 03ecaf7c1cca02e3cc569ec52f34fde4c62fdb40..d6a2d720c9f36c1b6590f6d88f5af46adc4be11b 100644 (file)
 #define __KRB5_KDC_UTIL__
 
 #include "kdb.h"
-
-typedef struct _krb5_fulladdr {
-    krb5_address *      address;
-    krb5_ui_4           port;
-} krb5_fulladdr;
+#include "net-server.h"
 
 krb5_error_code check_hot_list (krb5_ticket *);
 krb5_boolean realm_compare (krb5_const_principal, krb5_const_principal);
@@ -137,9 +133,12 @@ process_tgs_req (krb5_data *,
                  krb5_data ** );
 /* dispatch.c */
 krb5_error_code
-dispatch (krb5_data *,
+dispatch (void *,
+          struct sockaddr *,
           const krb5_fulladdr *,
-          krb5_data **);
+          krb5_data *,
+          krb5_data **,
+          int);
 
 /* main.c */
 krb5_error_code kdc_initialize_rcache (krb5_context, char *);
@@ -153,11 +152,6 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
 #endif
 ;
 
-/* network.c */
-krb5_error_code listen_and_process (void);
-krb5_error_code setup_network (void);
-krb5_error_code closedown_network (void);
-
 /* policy.c */
 int
 against_local_policy_as (krb5_kdc_req *, krb5_db_entry,
@@ -240,6 +234,8 @@ void kdc_insert_lookaside (krb5_data *, krb5_data *);
 void kdc_free_lookaside(krb5_context);
 
 /* kdc_util.c */
+void reset_for_hangup(void);
+
 krb5_error_code
 get_principal_locked (krb5_context kcontext,
                       krb5_const_principal search_for,
index 9d8022a789b13bc472525706e973a84b9569aaad..eaa70626fa502518b637a586f3b6da8d03263682 100644 (file)
@@ -60,6 +60,7 @@
 #include <errno.h>
 #include <netdb.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include "k5-int.h"
 #include "com_err.h"
@@ -69,6 +70,7 @@
 #include "extern.h"
 #include "kdc5_err.h"
 #include "kdb_kt.h"
+#include "net-server.h"
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -519,7 +521,7 @@ request_exit(int signo)
 static krb5_sigtype
 request_hup(int signo)
 {
-    signal_requests_hup = 1;
+    signal_requests_reset = 1;
 
 #ifdef POSIX_SIGTYPE
     return;
@@ -865,6 +867,7 @@ int main(int argc, char **argv)
     krb5_error_code     retval;
     krb5_context        kcontext;
     int errout = 0;
+    int i;
 
     if (strrchr(argv[0], '/'))
         argv[0] = strrchr(argv[0], '/')+1;
@@ -915,7 +918,40 @@ int main(int argc, char **argv)
         return 1;
     }
 
-    if ((retval = setup_network())) {
+    /* Handle each realm's ports */
+    for (i=0; i<kdc_numrealms; i++) {
+        char *cp = kdc_realmlist[i]->realm_ports;
+        int port;
+        while (cp && *cp) {
+            if (*cp == ',' || isspace((int) *cp)) {
+                cp++;
+                continue;
+            }
+            port = strtol(cp, &cp, 10);
+            if (cp == 0)
+                break;
+            retval = add_udp_port(port);
+            if (retval)
+                goto net_init_error;
+        }
+
+        cp = kdc_realmlist[i]->realm_tcp_ports;
+        while (cp && *cp) {
+            if (*cp == ',' || isspace((int) *cp)) {
+                cp++;
+                continue;
+            }
+            port = strtol(cp, &cp, 10);
+            if (cp == 0)
+                break;
+            retval = add_tcp_port(port);
+            if (retval)
+                goto net_init_error;
+        }
+    }
+
+    if ((retval = setup_network(NULL, kdc_progname))) {
+    net_init_error:
         kdc_err(kcontext, retval, "while initializing network");
         finish_realms();
         return 1;
@@ -936,14 +972,11 @@ int main(int argc, char **argv)
     krb5_klog_syslog(LOG_INFO, "commencing operation");
     if (nofork)
         fprintf(stderr, "%s: starting...\n", kdc_progname);
-    if ((retval = listen_and_process())) {
+    if ((retval = listen_and_process(0, kdc_progname, reset_for_hangup))) {
         kdc_err(kcontext, retval, "while processing network requests");
         errout++;
     }
-    if ((retval = closedown_network())) {
-        kdc_err(kcontext, retval, "while shutting down network");
-        errout++;
-    }
+    closedown_network();
     krb5_klog_syslog(LOG_INFO, "shutting down");
     unload_preauth_plugins(kcontext);
     unload_authdata_plugins(kcontext);
diff --git a/src/kdc/network.c b/src/kdc/network.c
deleted file mode 100644 (file)
index dfb478c..0000000
+++ /dev/null
@@ -1,1764 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * kdc/network.c
- *
- * Copyright 1990,2000,2007,2008,2009 by the Massachusetts Institute of Technology.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- *
- * Network code for Kerberos v5 KDC.
- */
-
-#include "k5-int.h"
-#include "kdc_util.h"
-#include "extern.h"
-#include "kdc5_err.h"
-#include "adm_proto.h"
-#include <sys/ioctl.h>
-#include <syslog.h>
-
-#include <stddef.h>
-#include <ctype.h>
-#include "port-sockets.h"
-#include "socket-utils.h"
-
-#ifdef HAVE_NETINET_IN_H
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#ifdef HAVE_SYS_SOCKIO_H
-/* for SIOCGIFCONF, etc. */
-#include <sys/sockio.h>
-#endif
-#include <sys/time.h>
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <arpa/inet.h>
-
-#ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>          /* FIONBIO */
-#endif
-
-#include "fake-addrinfo.h"
-
-/* Misc utility routines.  */
-static void
-set_sa_port(struct sockaddr *addr, int port)
-{
-    switch (addr->sa_family) {
-    case AF_INET:
-        sa2sin(addr)->sin_port = port;
-        break;
-#ifdef KRB5_USE_INET6
-    case AF_INET6:
-        sa2sin6(addr)->sin6_port = port;
-        break;
-#endif
-    default:
-        break;
-    }
-}
-
-static int ipv6_enabled()
-{
-#ifdef KRB5_USE_INET6
-    static int result = -1;
-    if (result == -1) {
-        int s;
-        s = socket(AF_INET6, SOCK_STREAM, 0);
-        if (s >= 0) {
-            result = 1;
-            close(s);
-        } else
-            result = 0;
-    }
-    return result;
-#else
-    return 0;
-#endif
-}
-
-static int
-setreuseaddr(int sock, int value)
-{
-    return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
-}
-
-#if defined(KRB5_USE_INET6) && defined(IPV6_V6ONLY)
-static int
-setv6only(int sock, int value)
-{
-    return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value));
-}
-#endif
-
-/* Use RFC 3542 API below, but fall back from IPV6_RECVPKTINFO to
-   IPV6_PKTINFO for RFC 2292 implementations.  */
-#ifndef IPV6_RECVPKTINFO
-#define IPV6_RECVPKTINFO IPV6_PKTINFO
-#endif
-/* Parallel, though not standardized.  */
-#ifndef IP_RECVPKTINFO
-#define IP_RECVPKTINFO IP_PKTINFO
-#endif
-
-static int
-set_pktinfo(int sock, int family)
-{
-    int sockopt = 1;
-    int option = 0, proto = 0;
-
-    switch (family) {
-#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
-    case AF_INET:
-        proto = IPPROTO_IP;
-        option = IP_RECVPKTINFO;
-        break;
-#endif
-#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
-    case AF_INET6:
-        proto = IPPROTO_IPV6;
-        option = IPV6_RECVPKTINFO;
-        break;
-#endif
-    default:
-        return EINVAL;
-    }
-    if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt)))
-        return errno;
-    return 0;
-}
-
-\f
-static const char *paddr (struct sockaddr *sa)
-{
-    static char buf[100];
-    char portbuf[10];
-    if (getnameinfo(sa, socklen(sa),
-                    buf, sizeof(buf), portbuf, sizeof(portbuf),
-                    NI_NUMERICHOST|NI_NUMERICSERV))
-        strlcpy(buf, "<unprintable>", sizeof(buf));
-    else {
-        unsigned int len = sizeof(buf) - strlen(buf);
-        char *p = buf + strlen(buf);
-        if (len > 2+strlen(portbuf)) {
-            *p++ = '.';
-            len--;
-            strncpy(p, portbuf, len);
-        }
-    }
-    return buf;
-}
-
-/* KDC data.  */
-
-enum conn_type {
-    CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP,
-    CONN_ROUTING
-};
-
-/* Per-connection info.  */
-struct connection {
-    int fd;
-    enum conn_type type;
-    void (*service)(struct connection *, int);
-    union {
-        /* Type-specific information.  */
-        struct {
-            /* connection */
-            struct sockaddr_storage addr_s;
-            socklen_t addrlen;
-            char addrbuf[56];
-            krb5_fulladdr faddr;
-            krb5_address kaddr;
-            /* incoming */
-            size_t bufsiz;
-            size_t offset;
-            char *buffer;
-            size_t msglen;
-            /* outgoing */
-            krb5_data *response;
-            unsigned char lenbuf[4];
-            sg_buf sgbuf[2];
-            sg_buf *sgp;
-            int sgnum;
-            /* crude denial-of-service avoidance support */
-            time_t start_time;
-        } tcp;
-    } u;
-};
-
-\f
-#define SET(TYPE) struct { TYPE *data; int n, max; }
-
-/* Start at the top and work down -- this should allow for deletions
-   without disrupting the iteration, since we delete by overwriting
-   the element to be removed with the last element.  */
-#define FOREACH_ELT(set,idx,vvar)                                       \
-    for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--)
-
-#define GROW_SET(set, incr, tmpptr)                                     \
-    (((int)(set.max + incr) < set.max                                   \
-      || (((size_t)((int)(set.max + incr) * sizeof(set.data[0]))        \
-           / sizeof(set.data[0]))                                       \
-          != (set.max + incr)))                                         \
-     ? 0                          /* overflow */                        \
-     : ((tmpptr = realloc(set.data,                                     \
-                          (int)(set.max + incr) * sizeof(set.data[0]))) \
-        ? (set.data = tmpptr, set.max += incr, 1)                       \
-        : 0))
-
-/* 1 = success, 0 = failure */
-#define ADD(set, val, tmpptr)                           \
-    ((set.n < set.max || GROW_SET(set, 10, tmpptr))     \
-     ? (set.data[set.n++] = val, 1)                     \
-     : 0)
-
-#define DEL(set, idx)                           \
-    (set.data[idx] = set.data[--set.n], 0)
-
-#define FREE_SET_DATA(set)                                      \
-    (free(set.data), set.data = 0, set.max = 0, set.n = 0)
-
-
-/* Set<struct connection *> connections; */
-static SET(struct connection *) connections;
-#define n_sockets       connections.n
-#define conns           connections.data
-
-/* Set<u_short> udp_port_data, tcp_port_data; */
-/*
- * N.B.: The Emacs cc-mode indentation code seems to get confused if
- * the macro argument here is one word only.  So use "unsigned short"
- * instead of the "u_short" we were using before.
- */
-static SET(unsigned short) udp_port_data, tcp_port_data;
-
-#include "cm.h"
-
-static struct select_state sstate;
-
-static krb5_error_code add_udp_port(int port)
-{
-    int i;
-    void *tmp;
-    u_short val;
-    u_short s_port = port;
-
-    if (s_port != port)
-        return EINVAL;
-
-    FOREACH_ELT (udp_port_data, i, val)
-        if (s_port == val)
-            return 0;
-    if (!ADD(udp_port_data, s_port, tmp))
-        return ENOMEM;
-    return 0;
-}
-
-static krb5_error_code add_tcp_port(int port)
-{
-    int i;
-    void *tmp;
-    u_short val;
-    u_short s_port = port;
-
-    if (s_port != port)
-        return EINVAL;
-
-    FOREACH_ELT (tcp_port_data, i, val)
-        if (s_port == val)
-            return 0;
-    if (!ADD(tcp_port_data, s_port, tmp))
-        return ENOMEM;
-    return 0;
-}
-
-\f
-#define USE_AF AF_INET
-#define USE_TYPE SOCK_DGRAM
-#define USE_PROTO 0
-#define SOCKET_ERRNO errno
-#include "foreachaddr.h"
-
-struct socksetup {
-    krb5_error_code retval;
-    int udp_flags;
-#define UDP_DO_IPV4 1
-#define UDP_DO_IPV6 2
-};
-
-static struct connection *
-add_fd (struct socksetup *data, int sock, enum conn_type conntype,
-        void (*service)(struct connection *, int))
-{
-    struct connection *newconn;
-    void *tmp;
-
-#ifndef _WIN32
-    if (sock >= FD_SETSIZE) {
-        data->retval = EMFILE;  /* XXX */
-        kdc_err(NULL, 0, "file descriptor number %d too high", sock);
-        return 0;
-    }
-#endif
-    newconn = malloc(sizeof(*newconn));
-    if (newconn == 0) {
-        data->retval = ENOMEM;
-        kdc_err(NULL, ENOMEM, "cannot allocate storage for connection info");
-        return 0;
-    }
-    if (!ADD(connections, newconn, tmp)) {
-        data->retval = ENOMEM;
-        kdc_err(NULL, ENOMEM, "cannot save socket info");
-        free(newconn);
-        return 0;
-    }
-
-    memset(newconn, 0, sizeof(*newconn));
-    newconn->type = conntype;
-    newconn->fd = sock;
-    newconn->service = service;
-    return newconn;
-}
-
-static void process_packet(struct connection *, int);
-static void accept_tcp_connection(struct connection *, int);
-static void process_tcp_connection(struct connection *, int);
-
-static struct connection *
-add_udp_fd (struct socksetup *data, int sock, int pktinfo)
-{
-    return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : CONN_UDP,
-                  process_packet);
-}
-
-static struct connection *
-add_tcp_listener_fd (struct socksetup *data, int sock)
-{
-    return add_fd(data, sock, CONN_TCP_LISTENER, accept_tcp_connection);
-}
-
-static struct connection *
-add_tcp_data_fd (struct socksetup *data, int sock)
-{
-    return add_fd(data, sock, CONN_TCP, process_tcp_connection);
-}
-
-static void
-delete_fd (struct connection *xconn)
-{
-    struct connection *conn;
-    int i;
-
-    FOREACH_ELT(connections, i, conn)
-        if (conn == xconn) {
-            DEL(connections, i);
-            break;
-        }
-    free(xconn);
-}
-
-static const int one = 1;
-
-static int
-setnbio(int sock)
-{
-    return ioctlsocket(sock, FIONBIO, (const void *)&one);
-}
-
-static int
-setkeepalive(int sock)
-{
-    return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
-}
-\f
-static int
-setnolinger(int s)
-{
-    static const struct linger ling = { 0, 0 };
-    return setsockopt(s, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
-}
-
-/* Returns -1 or socket fd.  */
-static int
-setup_a_tcp_listener(struct socksetup *data, struct sockaddr *addr)
-{
-    int sock;
-
-    sock = socket(addr->sa_family, SOCK_STREAM, 0);
-    if (sock == -1) {
-        kdc_err(NULL, errno, "Cannot create TCP server socket on %s",
-                paddr(addr));
-        return -1;
-    }
-    set_cloexec_fd(sock);
-#ifndef _WIN32
-    if (sock >= FD_SETSIZE) {
-        close(sock);
-        kdc_err(NULL, 0, "TCP socket fd number %d (for %s) too high",
-                sock, paddr(addr));
-        return -1;
-    }
-#endif
-    if (setreuseaddr(sock, 1) < 0)
-        kdc_err(NULL, errno, "Cannot enable SO_REUSEADDR on fd %d", sock);
-#ifdef KRB5_USE_INET6
-    if (addr->sa_family == AF_INET6) {
-#ifdef IPV6_V6ONLY
-        if (setv6only(sock, 1))
-            kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", sock);
-        else
-            kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock);
-#else
-        krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support");
-#endif /* IPV6_V6ONLY */
-    }
-#endif /* KRB5_USE_INET6 */
-    if (bind(sock, addr, socklen(addr)) == -1) {
-        kdc_err(NULL, errno, "Cannot bind TCP server socket on %s",
-                paddr(addr));
-        close(sock);
-        return -1;
-    }
-    if (listen(sock, 5) < 0) {
-        kdc_err(NULL, errno, "Cannot listen on TCP server socket on %s",
-                paddr(addr));
-        close(sock);
-        return -1;
-    }
-    if (setnbio(sock)) {
-        kdc_err(NULL, errno,
-                "cannot set listening tcp socket on %s non-blocking",
-                paddr(addr));
-        close(sock);
-        return -1;
-    }
-    if (setnolinger(sock)) {
-        kdc_err(NULL, errno, "disabling SO_LINGER on TCP socket on %s",
-                paddr(addr));
-        close(sock);
-        return -1;
-    }
-    return sock;
-}
-
-static int
-setup_tcp_listener_ports(struct socksetup *data)
-{
-    struct sockaddr_in sin4;
-#ifdef KRB5_USE_INET6
-    struct sockaddr_in6 sin6;
-#endif
-    int i, port;
-
-    memset(&sin4, 0, sizeof(sin4));
-    sin4.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
-    sin4.sin_len = sizeof(sin4);
-#endif
-    sin4.sin_addr.s_addr = INADDR_ANY;
-
-#ifdef KRB5_USE_INET6
-    memset(&sin6, 0, sizeof(sin6));
-    sin6.sin6_family = AF_INET6;
-#ifdef SIN6_LEN
-    sin6.sin6_len = sizeof(sin6);
-#endif
-    sin6.sin6_addr = in6addr_any;
-#endif
-
-    FOREACH_ELT (tcp_port_data, i, port) {
-        int s4, s6;
-
-        set_sa_port((struct sockaddr *)&sin4, htons(port));
-        if (!ipv6_enabled()) {
-            s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
-            if (s4 < 0)
-                return -1;
-            s6 = -1;
-        } else {
-#ifndef KRB5_USE_INET6
-            abort();
-#else
-            s4 = s6 = -1;
-
-            set_sa_port((struct sockaddr *)&sin6, htons(port));
-
-            s6 = setup_a_tcp_listener(data, (struct sockaddr *)&sin6);
-            if (s6 < 0)
-                return -1;
-
-            s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
-#endif /* KRB5_USE_INET6 */
-        }
-
-        /* Sockets are created, prepare to listen on them.  */
-        if (s4 >= 0) {
-            if (add_tcp_listener_fd(data, s4) == NULL)
-                close(s4);
-            else {
-                FD_SET(s4, &sstate.rfds);
-                if (s4 >= sstate.max)
-                    sstate.max = s4 + 1;
-                krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s",
-                                 s4, paddr((struct sockaddr *)&sin4));
-            }
-        }
-#ifdef KRB5_USE_INET6
-        if (s6 >= 0) {
-            if (add_tcp_listener_fd(data, s6) == NULL) {
-                close(s6);
-                s6 = -1;
-            } else {
-                FD_SET(s6, &sstate.rfds);
-                if (s6 >= sstate.max)
-                    sstate.max = s6 + 1;
-                krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s",
-                                 s6, paddr((struct sockaddr *)&sin6));
-            }
-            if (s4 < 0)
-                krb5_klog_syslog(LOG_INFO,
-                                 "assuming IPv6 socket accepts IPv4");
-        }
-#endif
-    }
-    return 0;
-}
-
-#if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))
-union pktinfo {
-#ifdef HAVE_STRUCT_IN6_PKTINFO
-    struct in6_pktinfo pi6;
-#endif
-#ifdef HAVE_STRUCT_IN_PKTINFO
-    struct in_pktinfo pi4;
-#endif
-    char c;
-};
-
-static int
-setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
-                 char *haddrbuf, int pktinfo);
-
-static void
-setup_udp_pktinfo_ports(struct socksetup *data)
-{
-#ifdef IP_PKTINFO
-    {
-        struct sockaddr_in sa;
-        int r;
-
-        memset(&sa, 0, sizeof(sa));
-        sa.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
-        sa.sin_len = sizeof(sa);
-#endif
-        r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4);
-        if (r == 0)
-            data->udp_flags &= ~UDP_DO_IPV4;
-    }
-#endif
-#ifdef IPV6_PKTINFO
-    {
-        struct sockaddr_in6 sa;
-        int r;
-
-        memset(&sa, 0, sizeof(sa));
-        sa.sin6_family = AF_INET6;
-#ifdef HAVE_SA_LEN
-        sa.sin6_len = sizeof(sa);
-#endif
-        r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6);
-        if (r == 0)
-            data->udp_flags &= ~UDP_DO_IPV6;
-    }
-#endif
-}
-#else /* no pktinfo compile-time support */
-static void
-setup_udp_pktinfo_ports(struct socksetup *data)
-{
-}
-#endif
-
-static int
-setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
-                 char *haddrbuf, int pktinfo)
-{
-    int sock = -1, i, r;
-    u_short port;
-
-    FOREACH_ELT (udp_port_data, i, port) {
-        sock = socket (addr->sa_family, SOCK_DGRAM, 0);
-        if (sock == -1) {
-            data->retval = errno;
-            kdc_err(NULL, data->retval,
-                    "Cannot create server socket for port %d address %s",
-                    port, haddrbuf);
-            return 1;
-        }
-        set_cloexec_fd(sock);
-#ifdef KRB5_USE_INET6
-        if (addr->sa_family == AF_INET6) {
-#ifdef IPV6_V6ONLY
-            if (setv6only(sock, 1))
-                kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed",
-                        sock);
-            else
-                kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock);
-#else
-            krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support");
-#endif /* IPV6_V6ONLY */
-        }
-#endif
-        set_sa_port(addr, htons(port));
-        if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) {
-            data->retval = errno;
-            kdc_err(NULL, data->retval,
-                    "Cannot bind server socket to port %d address %s",
-                    port, haddrbuf);
-            close(sock);
-            return 1;
-        }
-#if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO)))
-        assert(pktinfo == 0);
-#endif
-        if (pktinfo) {
-            r = set_pktinfo(sock, addr->sa_family);
-            if (r) {
-                kdc_err(NULL, r,
-                        "Cannot request packet info for udp socket address %s port %d",
-                        haddrbuf, port);
-                close(sock);
-                return 1;
-            }
-        }
-        krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s%s", sock,
-                          paddr((struct sockaddr *)addr),
-                          pktinfo ? " (pktinfo)" : "");
-        if (add_udp_fd (data, sock, pktinfo) == 0) {
-            close(sock);
-            return 1;
-        }
-        FD_SET (sock, &sstate.rfds);
-        if (sock >= sstate.max)
-            sstate.max = sock + 1;
-    }
-    return 0;
-}
-
-static int
-setup_udp_port(void *P_data, struct sockaddr *addr)
-{
-    struct socksetup *data = P_data;
-    char haddrbuf[NI_MAXHOST];
-    int err;
-
-    if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4))
-        return 0;
-#ifdef AF_INET6
-    if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6))
-        return 0;
-#endif
-    err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf),
-                      0, 0, NI_NUMERICHOST);
-    if (err)
-        strlcpy(haddrbuf, "<unprintable>", sizeof(haddrbuf));
-
-    switch (addr->sa_family) {
-    case AF_INET:
-        break;
-#ifdef AF_INET6
-    case AF_INET6:
-#ifdef KRB5_USE_INET6
-        break;
-#else
-        {
-            static int first = 1;
-            if (first) {
-                krb5_klog_syslog (LOG_INFO, "skipping local ipv6 addresses");
-                first = 0;
-            }
-            return 0;
-        }
-#endif
-#endif
-#ifdef AF_LINK /* some BSD systems, AIX */
-    case AF_LINK:
-        return 0;
-#endif
-#ifdef AF_DLI /* Direct Link Interface - DEC Ultrix/OSF1 link layer? */
-    case AF_DLI:
-        return 0;
-#endif
-#ifdef AF_APPLETALK
-    case AF_APPLETALK:
-        return 0;
-#endif
-    default:
-        krb5_klog_syslog (LOG_INFO,
-                          "skipping unrecognized local address family %d",
-                          addr->sa_family);
-        return 0;
-    }
-    return setup_udp_port_1(data, addr, haddrbuf, 0);
-}
-
-#if 1
-static void klog_handler(const void *data, size_t len)
-{
-    static char buf[BUFSIZ];
-    static int bufoffset;
-    void *p;
-
-#define flush_buf()                             \
-    (bufoffset                                  \
-     ? (((buf[0] == 0 || buf[0] == '\n')        \
-         ? (fork()==0?abort():(void)0)          \
-         : (void)0),                            \
-        krb5_klog_syslog(LOG_INFO, "%s", buf),  \
-        memset(buf, 0, sizeof(buf)),            \
-        bufoffset = 0)                          \
-     : 0)
-
-    p = memchr(data, 0, len);
-    if (p)
-        len = (const char *)p - (const char *)data;
-scan_for_newlines:
-    if (len == 0)
-        return;
-    p = memchr(data, '\n', len);
-    if (p) {
-        if (p != data)
-            klog_handler(data, (size_t)((const char *)p - (const char *)data));
-        flush_buf();
-        len -= ((const char *)p - (const char *)data) + 1;
-        data = 1 + (const char *)p;
-        goto scan_for_newlines;
-    } else if (len > sizeof(buf) - 1 || len + bufoffset > sizeof(buf) - 1) {
-        size_t x = sizeof(buf) - len - 1;
-        klog_handler(data, x);
-        flush_buf();
-        len -= x;
-        data = (const char *)data + x;
-        goto scan_for_newlines;
-    } else {
-        memcpy(buf + bufoffset, data, len);
-        bufoffset += len;
-    }
-}
-#endif
-
-static int network_reconfiguration_needed = 0;
-
-#ifdef HAVE_STRUCT_RT_MSGHDR
-#include <net/route.h>
-
-static char *rtm_type_name(int type)
-{
-    switch (type) {
-    case RTM_ADD: return "RTM_ADD";
-    case RTM_DELETE: return "RTM_DELETE";
-    case RTM_NEWADDR: return "RTM_NEWADDR";
-    case RTM_DELADDR: return "RTM_DELADDR";
-    case RTM_IFINFO: return "RTM_IFINFO";
-    case RTM_OLDADD: return "RTM_OLDADD";
-    case RTM_OLDDEL: return "RTM_OLDDEL";
-    case RTM_RESOLVE: return "RTM_RESOLVE";
-#ifdef RTM_NEWMADDR
-    case RTM_NEWMADDR: return "RTM_NEWMADDR";
-    case RTM_DELMADDR: return "RTM_DELMADDR";
-#endif
-    case RTM_MISS: return "RTM_MISS";
-    case RTM_REDIRECT: return "RTM_REDIRECT";
-    case RTM_LOSING: return "RTM_LOSING";
-    case RTM_GET: return "RTM_GET";
-    default: return "?";
-    }
-}
-
-static void process_routing_update(struct connection *conn, int selflags)
-{
-    int n_read;
-    struct rt_msghdr rtm;
-
-    while ((n_read = read(conn->fd, &rtm, sizeof(rtm))) > 0) {
-        if (n_read < sizeof(rtm)) {
-            /* Quick hack to figure out if the interesting
-               fields are present in a short read.
-
-               A short read seems to be normal for some message types.
-               Only complain if we don't have the critical initial
-               header fields.  */
-#define RS(FIELD) (offsetof(struct rt_msghdr, FIELD) + sizeof(rtm.FIELD))
-            if (n_read < RS(rtm_type) ||
-                n_read < RS(rtm_version) ||
-                n_read < RS(rtm_msglen)) {
-                krb5_klog_syslog(LOG_ERR,
-                                 "short read (%d/%d) from routing socket",
-                                 n_read, (int) sizeof(rtm));
-                return;
-            }
-        }
-#if 0
-        krb5_klog_syslog(LOG_INFO,
-                         "got routing msg type %d(%s) v%d",
-                         rtm.rtm_type, rtm_type_name(rtm.rtm_type),
-                         rtm.rtm_version);
-#endif
-        if (rtm.rtm_msglen > sizeof(rtm)) {
-            /* It appears we get a partial message and the rest is
-               thrown away?  */
-        } else if (rtm.rtm_msglen != n_read) {
-            krb5_klog_syslog(LOG_ERR,
-                             "read %d from routing socket but msglen is %d",
-                             n_read, rtm.rtm_msglen);
-        }
-        switch (rtm.rtm_type) {
-        case RTM_ADD:
-        case RTM_DELETE:
-        case RTM_NEWADDR:
-        case RTM_DELADDR:
-        case RTM_IFINFO:
-        case RTM_OLDADD:
-        case RTM_OLDDEL:
-            /*
-             * Some flags indicate routing table updates that don't
-             * indicate local address changes.  They may come from
-             * redirects, or ARP, etc.
-             *
-             * This set of symbols is just an initial guess based on
-             * some messages observed in real life; working out which
-             * other flags also indicate messages we should ignore,
-             * and which flags are portable to all system and thus
-             * don't need to be conditionalized, is left as a future
-             * exercise.
-             */
-#ifdef RTF_DYNAMIC
-            if (rtm.rtm_flags & RTF_DYNAMIC)
-                break;
-#endif
-#ifdef RTF_CLONED
-            if (rtm.rtm_flags & RTF_CLONED)
-                break;
-#endif
-#ifdef RTF_LLINFO
-            if (rtm.rtm_flags & RTF_LLINFO)
-                break;
-#endif
-#if 0
-            krb5_klog_syslog(LOG_DEBUG,
-                             "network reconfiguration message (%s) received",
-                             rtm_type_name(rtm.rtm_type));
-#endif
-            network_reconfiguration_needed = 1;
-            break;
-        case RTM_RESOLVE:
-#ifdef RTM_NEWMADDR
-        case RTM_NEWMADDR:
-        case RTM_DELMADDR:
-#endif
-        case RTM_MISS:
-        case RTM_REDIRECT:
-        case RTM_LOSING:
-        case RTM_GET:
-            /* Not interesting.  */
-#if 0
-            krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting");
-#endif
-            break;
-        default:
-            krb5_klog_syslog(LOG_INFO,
-                             "unhandled routing message type %d, will reconfigure just for the fun of it",
-                             rtm.rtm_type);
-            network_reconfiguration_needed = 1;
-            break;
-        }
-    }
-}
-
-static void
-setup_routing_socket(struct socksetup *data)
-{
-    int sock = socket(PF_ROUTE, SOCK_RAW, 0);
-    if (sock < 0) {
-        int e = errno;
-        krb5_klog_syslog(LOG_INFO, "couldn't set up routing socket: %s",
-                         strerror(e));
-    } else {
-        krb5_klog_syslog(LOG_INFO, "routing socket is fd %d", sock);
-        add_fd(data, sock, CONN_ROUTING, process_routing_update);
-        setnbio(sock);
-        FD_SET(sock, &sstate.rfds);
-    }
-}
-#endif
-
-/* XXX */
-extern int krb5int_debug_sendto_kdc;
-extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t);
-
-krb5_error_code
-setup_network()
-{
-    struct socksetup setup_data;
-    krb5_error_code retval;
-    char *cp;
-    int i, port;
-
-    FD_ZERO(&sstate.rfds);
-    FD_ZERO(&sstate.wfds);
-    FD_ZERO(&sstate.xfds);
-    sstate.max = 0;
-
-/*    krb5int_debug_sendto_kdc = 1; */
-    krb5int_sendtokdc_debug_handler = klog_handler;
-
-    /* Handle each realm's ports */
-    for (i=0; i<kdc_numrealms; i++) {
-        cp = kdc_realmlist[i]->realm_ports;
-        while (cp && *cp) {
-            if (*cp == ',' || isspace((int) *cp)) {
-                cp++;
-                continue;
-            }
-            port = strtol(cp, &cp, 10);
-            if (cp == 0)
-                break;
-            retval = add_udp_port(port);
-            if (retval)
-                return retval;
-        }
-
-        cp = kdc_realmlist[i]->realm_tcp_ports;
-        while (cp && *cp) {
-            if (*cp == ',' || isspace((int) *cp)) {
-                cp++;
-                continue;
-            }
-            port = strtol(cp, &cp, 10);
-            if (cp == 0)
-                break;
-            retval = add_tcp_port(port);
-            if (retval)
-                return retval;
-        }
-    }
-
-    setup_data.retval = 0;
-    krb5_klog_syslog (LOG_INFO, "setting up network...");
-#ifdef HAVE_STRUCT_RT_MSGHDR
-    setup_routing_socket(&setup_data);
-#endif
-    /* To do: Use RFC 2292 interface (or follow-on) and IPV6_PKTINFO,
-       so we might need only one UDP socket; fall back to binding
-       sockets on each address only if IPV6_PKTINFO isn't
-       supported.  */
-    setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6;
-    setup_udp_pktinfo_ports(&setup_data);
-    if (setup_data.udp_flags) {
-        if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
-            return setup_data.retval;
-        }
-    }
-    setup_tcp_listener_ports(&setup_data);
-    krb5_klog_syslog (LOG_INFO, "set up %d sockets", n_sockets);
-    if (n_sockets == 0) {
-        kdc_err(NULL, 0, "no sockets set up?");
-        exit (1);
-    }
-
-    return 0;
-}
-
-static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
-{
-    switch (sa->sa_family) {
-    case AF_INET:
-        faddr->address->addrtype = ADDRTYPE_INET;
-        faddr->address->length = 4;
-        faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr;
-        faddr->port = ntohs(sa2sin(sa)->sin_port);
-        break;
-#ifdef KRB5_USE_INET6
-    case AF_INET6:
-        if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) {
-            faddr->address->addrtype = ADDRTYPE_INET;
-            faddr->address->length = 4;
-            faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr;
-        } else {
-            faddr->address->addrtype = ADDRTYPE_INET6;
-            faddr->address->length = 16;
-            faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr;
-        }
-        faddr->port = ntohs(sa2sin6(sa)->sin6_port);
-        break;
-#endif
-    default:
-        faddr->address->addrtype = -1;
-        faddr->address->length = 0;
-        faddr->address->contents = 0;
-        faddr->port = 0;
-        break;
-    }
-}
-
-/*
- * This holds whatever additional information might be needed to
- * properly send back to the client from the correct local address.
- *
- * In this case, we only need one datum so far: On Mac OS X, the
- * kernel doesn't seem to like sending from link-local addresses
- * unless we specify the correct interface.
- */
-
-union aux_addressing_info {
-    int ipv6_ifindex;
-};
-
-static int
-recv_from_to(int s, void *buf, size_t len, int flags,
-             struct sockaddr *from, socklen_t *fromlen,
-             struct sockaddr *to, socklen_t *tolen,
-             union aux_addressing_info *auxaddr)
-{
-#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
-    if (to && tolen) {
-        /* Clobber with something recognizeable in case we try to use
-           the address.  */
-        memset(to, 0x40, *tolen);
-        *tolen = 0;
-    }
-    return recvfrom(s, buf, len, flags, from, fromlen);
-#else
-    int r;
-    struct iovec iov;
-    char cmsg[CMSG_SPACE(sizeof(union pktinfo))];
-    struct cmsghdr *cmsgptr;
-    struct msghdr msg;
-
-    if (!to || !tolen)
-        return recvfrom(s, buf, len, flags, from, fromlen);
-
-    /* Clobber with something recognizeable in case we can't extract
-       the address but try to use it anyways.  */
-    memset(to, 0x40, *tolen);
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
-    memset(&msg, 0, sizeof(msg));
-    msg.msg_name = from;
-    msg.msg_namelen = *fromlen;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = cmsg;
-    msg.msg_controllen = sizeof(cmsg);
-
-    r = recvmsg(s, &msg, flags);
-    if (r < 0)
-        return r;
-    *fromlen = msg.msg_namelen;
-
-    /* On Darwin (and presumably all *BSD with KAME stacks),
-       CMSG_FIRSTHDR doesn't check for a non-zero controllen.  RFC
-       3542 recommends making this check, even though the (new) spec
-       for CMSG_FIRSTHDR says it's supposed to do the check.  */
-    if (msg.msg_controllen) {
-        cmsgptr = CMSG_FIRSTHDR(&msg);
-        while (cmsgptr) {
-#ifdef IP_PKTINFO
-            if (cmsgptr->cmsg_level == IPPROTO_IP
-                && cmsgptr->cmsg_type == IP_PKTINFO
-                && *tolen >= sizeof(struct sockaddr_in)) {
-                struct in_pktinfo *pktinfo;
-                memset(to, 0, sizeof(struct sockaddr_in));
-                pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
-                ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr;
-                ((struct sockaddr_in *)to)->sin_family = AF_INET;
-                *tolen = sizeof(struct sockaddr_in);
-                return r;
-            }
-#endif
-#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO)&& defined(HAVE_STRUCT_IN6_PKTINFO)
-            if (cmsgptr->cmsg_level == IPPROTO_IPV6
-                && cmsgptr->cmsg_type == IPV6_PKTINFO
-                && *tolen >= sizeof(struct sockaddr_in6)) {
-                struct in6_pktinfo *pktinfo;
-                memset(to, 0, sizeof(struct sockaddr_in6));
-                pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
-                ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr;
-                ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6;
-                *tolen = sizeof(struct sockaddr_in6);
-                auxaddr->ipv6_ifindex = pktinfo->ipi6_ifindex;
-                return r;
-            }
-#endif
-            cmsgptr = CMSG_NXTHDR(&msg, cmsgptr);
-        }
-    }
-    /* No info about destination addr was available.  */
-    *tolen = 0;
-    return r;
-#endif
-}
-
-static int
-send_to_from(int s, void *buf, size_t len, int flags,
-             const struct sockaddr *to, socklen_t tolen,
-             const struct sockaddr *from, socklen_t fromlen,
-             union aux_addressing_info *auxaddr)
-{
-#if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
-    return sendto(s, buf, len, flags, to, tolen);
-#else
-    struct iovec iov;
-    struct msghdr msg;
-    struct cmsghdr *cmsgptr;
-    char cbuf[CMSG_SPACE(sizeof(union pktinfo))];
-
-    if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) {
-    use_sendto:
-        return sendto(s, buf, len, flags, to, tolen);
-    }
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
-    /* Truncation?  */
-    if (iov.iov_len != len)
-        return EINVAL;
-    memset(cbuf, 0, sizeof(cbuf));
-    memset(&msg, 0, sizeof(msg));
-    msg.msg_name = (void *) to;
-    msg.msg_namelen = tolen;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = cbuf;
-    /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL
-       on Linux.  */
-    msg.msg_controllen = sizeof(cbuf);
-    cmsgptr = CMSG_FIRSTHDR(&msg);
-    msg.msg_controllen = 0;
-
-    switch (from->sa_family) {
-#if defined(IP_PKTINFO)
-    case AF_INET:
-        if (fromlen != sizeof(struct sockaddr_in))
-            goto use_sendto;
-        cmsgptr->cmsg_level = IPPROTO_IP;
-        cmsgptr->cmsg_type = IP_PKTINFO;
-        cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
-        {
-            struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
-            const struct sockaddr_in *from4 = (const struct sockaddr_in *)from;
-            p->ipi_spec_dst = from4->sin_addr;
-        }
-        msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
-        break;
-#endif
-#if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
-    case AF_INET6:
-        if (fromlen != sizeof(struct sockaddr_in6))
-            goto use_sendto;
-        cmsgptr->cmsg_level = IPPROTO_IPV6;
-        cmsgptr->cmsg_type = IPV6_PKTINFO;
-        cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
-        {
-            struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
-            const struct sockaddr_in6 *from6 = (const struct sockaddr_in6 *)from;
-            p->ipi6_addr = from6->sin6_addr;
-            /*
-             * Because of the possibility of asymmetric routing, we
-             * normally don't want to specify an interface.  However,
-             * Mac OS X doesn't like sending from a link-local address
-             * (which can come up in testing at least, if you wind up
-             * with a "foo.local" name) unless we do specify the
-             * interface.
-             */
-            if (IN6_IS_ADDR_LINKLOCAL(&from6->sin6_addr))
-                p->ipi6_ifindex = auxaddr->ipv6_ifindex;
-            /* otherwise, already zero */
-        }
-        msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
-        break;
-#endif
-    default:
-        goto use_sendto;
-    }
-    return sendmsg(s, &msg, flags);
-#endif
-}
-
-static krb5_error_code
-make_too_big_error (krb5_data **out)
-{
-    krb5_error errpkt;
-    krb5_error_code retval;
-    krb5_data *scratch;
-
-    *out = NULL;
-    memset(&errpkt, 0, sizeof(errpkt));
-
-    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
-    if (retval)
-        return retval;
-    errpkt.error = KRB_ERR_RESPONSE_TOO_BIG;
-    errpkt.server = tgs_server;
-    errpkt.client = NULL;
-    errpkt.text.length = 0;
-    errpkt.text.data = 0;
-    errpkt.e_data.length = 0;
-    errpkt.e_data.data = 0;
-    scratch = malloc(sizeof(*scratch));
-    if (scratch == NULL)
-        return ENOMEM;
-    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
-    if (retval) {
-        free(scratch);
-        return retval;
-    }
-
-    *out = scratch;
-    return 0;
-}
-
-static void process_packet(struct connection *conn, int selflags)
-{
-    int cc;
-    socklen_t saddr_len, daddr_len;
-    krb5_fulladdr faddr;
-    krb5_error_code retval;
-    struct sockaddr_storage saddr, daddr;
-    krb5_address addr;
-    krb5_data request;
-    krb5_data *response;
-    char pktbuf[MAX_DGRAM_SIZE];
-    int port_fd = conn->fd;
-    union aux_addressing_info auxaddr;
-
-    response = NULL;
-    saddr_len = sizeof(saddr);
-    daddr_len = sizeof(daddr);
-    memset(&auxaddr, 0, sizeof(auxaddr));
-    cc = recv_from_to(port_fd, pktbuf, sizeof(pktbuf), 0,
-                      (struct sockaddr *)&saddr, &saddr_len,
-                      (struct sockaddr *)&daddr, &daddr_len,
-                      &auxaddr);
-    if (cc == -1) {
-        if (errno != EINTR
-            /* This is how Linux indicates that a previous
-               transmission was refused, e.g., if the client timed out
-               before getting the response packet.  */
-            && errno != ECONNREFUSED
-        )
-            kdc_err(NULL, errno, "while receiving from network");
-        return;
-    }
-    if (!cc)
-        return;         /* zero-length packet? */
-
-#if 0
-    if (daddr_len > 0) {
-        char addrbuf[100];
-        if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf),
-                        0, 0, NI_NUMERICHOST))
-            strlcpy(addrbuf, "?", sizeof(addrbuf));
-        kdc_err(NULL, 0, "pktinfo says local addr is %s", addrbuf);
-    }
-#endif
-
-    request.length = cc;
-    request.data = pktbuf;
-    faddr.address = &addr;
-    init_addr(&faddr, ss2sa(&saddr));
-    /* this address is in net order */
-    if ((retval = dispatch(&request, &faddr, &response))) {
-        kdc_err(NULL, retval, "while dispatching (udp)");
-        return;
-    }
-    if (response == NULL)
-        return;
-    if (response->length > max_dgram_reply_size) {
-        krb5_free_data(kdc_context, response);
-        retval = make_too_big_error(&response);
-        if (retval) {
-            krb5_klog_syslog(LOG_ERR,
-                             "error constructing KRB_ERR_RESPONSE_TOO_BIG error: %s",
-                             error_message(retval));
-            return;
-        }
-    }
-    cc = send_to_from(port_fd, response->data, (socklen_t) response->length, 0,
-                      (struct sockaddr *)&saddr, saddr_len,
-                      (struct sockaddr *)&daddr, daddr_len,
-                      &auxaddr);
-    if (cc == -1) {
-        /*
-         * Note that the local address (daddr*) has no port number
-         * info associated with it.
-         */
-        char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV];
-        char daddrbuf[NI_MAXHOST];
-        int e = errno;
-        krb5_free_data(kdc_context, response);
-        if (getnameinfo((struct sockaddr *)&daddr, daddr_len,
-                        daddrbuf, sizeof(daddrbuf), 0, 0,
-                        NI_NUMERICHOST) != 0) {
-            strlcpy(daddrbuf, "?", sizeof(daddrbuf));
-        }
-        if (getnameinfo((struct sockaddr *)&saddr, saddr_len,
-                        saddrbuf, sizeof(saddrbuf), sportbuf, sizeof(sportbuf),
-                        NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
-            strlcpy(saddrbuf, "?", sizeof(saddrbuf));
-            strlcpy(sportbuf, "?", sizeof(sportbuf));
-        }
-        kdc_err(NULL, e, "while sending reply to %s/%s from %s",
-                saddrbuf, sportbuf, daddrbuf);
-        return;
-    }
-    if (cc != response->length) {
-        kdc_err(NULL, 0, "short reply write %d vs %d\n",
-                response->length, cc);
-    }
-    krb5_free_data(kdc_context, response);
-    return;
-}
-
-static int tcp_data_counter;
-static int max_tcp_data_connections = 30;
-
-static void kill_tcp_connection(struct connection *);
-
-static void accept_tcp_connection(struct connection *conn, int selflags)
-{
-    int s;
-    struct sockaddr_storage addr_s;
-    struct sockaddr *addr = (struct sockaddr *)&addr_s;
-    socklen_t addrlen = sizeof(addr_s);
-    struct socksetup sockdata;
-    struct connection *newconn;
-    char tmpbuf[10];
-
-    s = accept(conn->fd, addr, &addrlen);
-    if (s < 0)
-        return;
-    set_cloexec_fd(s);
-#ifndef _WIN32
-    if (s >= FD_SETSIZE) {
-        close(s);
-        return;
-    }
-#endif
-    setnbio(s), setnolinger(s), setkeepalive(s);
-
-    sockdata.retval = 0;
-
-    newconn = add_tcp_data_fd(&sockdata, s);
-    if (newconn == NULL)
-        return;
-
-    if (getnameinfo((struct sockaddr *)&addr_s, addrlen,
-                    newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf),
-                    tmpbuf, sizeof(tmpbuf),
-                    NI_NUMERICHOST | NI_NUMERICSERV))
-        strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(newconn->u.tcp.addrbuf));
-    else {
-        char *p, *end;
-        p = newconn->u.tcp.addrbuf;
-        end = p + sizeof(newconn->u.tcp.addrbuf);
-        p += strlen(p);
-        if (end - p > 2 + strlen(tmpbuf)) {
-            *p++ = '.';
-            strlcpy(p, tmpbuf, end - p);
-        }
-    }
-#if 0
-    krb5_klog_syslog(LOG_INFO, "accepted TCP connection on socket %d from %s",
-                     s, newconn->u.tcp.addrbuf);
-#endif
-
-    newconn->u.tcp.addr_s = addr_s;
-    newconn->u.tcp.addrlen = addrlen;
-    newconn->u.tcp.bufsiz = 1024 * 1024;
-    newconn->u.tcp.buffer = malloc(newconn->u.tcp.bufsiz);
-    newconn->u.tcp.start_time = time(0);
-
-    if (++tcp_data_counter > max_tcp_data_connections) {
-        struct connection *oldest_tcp = NULL;
-        struct connection *c;
-        int i;
-
-        krb5_klog_syslog(LOG_INFO, "too many connections");
-
-        FOREACH_ELT (connections, i, c) {
-            if (c->type != CONN_TCP)
-                continue;
-            if (c == newconn)
-                continue;
-#if 0
-            krb5_klog_syslog(LOG_INFO, "fd %d started at %ld", c->fd,
-                             c->u.tcp.start_time);
-#endif
-            if (oldest_tcp == NULL
-                || oldest_tcp->u.tcp.start_time > c->u.tcp.start_time)
-                oldest_tcp = c;
-        }
-        if (oldest_tcp != NULL) {
-            krb5_klog_syslog(LOG_INFO, "dropping tcp fd %d from %s",
-                             oldest_tcp->fd, oldest_tcp->u.tcp.addrbuf);
-            kill_tcp_connection(oldest_tcp);
-        }
-    }
-    if (newconn->u.tcp.buffer == 0) {
-        kdc_err(NULL, errno, "allocating buffer for new TCP session from %s",
-                newconn->u.tcp.addrbuf);
-        delete_fd(newconn);
-        close(s);
-        tcp_data_counter--;
-        return;
-    }
-    newconn->u.tcp.offset = 0;
-    newconn->u.tcp.faddr.address = &newconn->u.tcp.kaddr;
-    init_addr(&newconn->u.tcp.faddr, ss2sa(&newconn->u.tcp.addr_s));
-    SG_SET(&newconn->u.tcp.sgbuf[0], newconn->u.tcp.lenbuf, 4);
-    SG_SET(&newconn->u.tcp.sgbuf[1], 0, 0);
-
-    FD_SET(s, &sstate.rfds);
-    if (sstate.max <= s)
-        sstate.max = s + 1;
-}
-
-static void
-kill_tcp_connection(struct connection *conn)
-{
-    if (conn->u.tcp.response)
-        krb5_free_data(kdc_context, conn->u.tcp.response);
-    if (conn->u.tcp.buffer)
-        free(conn->u.tcp.buffer);
-    FD_CLR(conn->fd, &sstate.rfds);
-    FD_CLR(conn->fd, &sstate.wfds);
-    if (sstate.max == conn->fd + 1)
-        while (sstate.max > 0
-               && ! FD_ISSET(sstate.max-1, &sstate.rfds)
-               && ! FD_ISSET(sstate.max-1, &sstate.wfds)
-               /* && ! FD_ISSET(sstate.max-1, &sstate.xfds) */
-        )
-            sstate.max--;
-    close(conn->fd);
-    conn->fd = -1;
-    delete_fd(conn);
-    tcp_data_counter--;
-}
-
-static krb5_error_code
-make_toolong_error (krb5_data **out)
-{
-    krb5_error errpkt;
-    krb5_error_code retval;
-    krb5_data *scratch;
-
-    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
-    if (retval)
-        return retval;
-    errpkt.error = KRB_ERR_FIELD_TOOLONG;
-    errpkt.server = tgs_server;
-    errpkt.client = NULL;
-    errpkt.cusec = 0;
-    errpkt.ctime = 0;
-    errpkt.text.length = 0;
-    errpkt.text.data = 0;
-    errpkt.e_data.length = 0;
-    errpkt.e_data.data = 0;
-    scratch = malloc(sizeof(*scratch));
-    if (scratch == NULL)
-        return ENOMEM;
-    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
-    if (retval) {
-        free(scratch);
-        return retval;
-    }
-
-    *out = scratch;
-    return 0;
-}
-
-static void
-queue_tcp_outgoing_response(struct connection *conn)
-{
-    store_32_be(conn->u.tcp.response->length, conn->u.tcp.lenbuf);
-    SG_SET(&conn->u.tcp.sgbuf[1], conn->u.tcp.response->data,
-           conn->u.tcp.response->length);
-    conn->u.tcp.sgp = conn->u.tcp.sgbuf;
-    conn->u.tcp.sgnum = 2;
-    FD_SET(conn->fd, &sstate.wfds);
-}
-
-static void
-process_tcp_connection(struct connection *conn, int selflags)
-{
-    if (selflags & SSF_WRITE) {
-        ssize_t nwrote;
-        SOCKET_WRITEV_TEMP tmp;
-
-        nwrote = SOCKET_WRITEV(conn->fd, conn->u.tcp.sgp, conn->u.tcp.sgnum,
-                               tmp);
-        if (nwrote < 0) {
-            goto kill_tcp_connection;
-        }
-        if (nwrote == 0)
-            /* eof */
-            goto kill_tcp_connection;
-        while (nwrote) {
-            sg_buf *sgp = conn->u.tcp.sgp;
-            if (nwrote < SG_LEN(sgp)) {
-                SG_ADVANCE(sgp, nwrote);
-                nwrote = 0;
-            } else {
-                nwrote -= SG_LEN(sgp);
-                conn->u.tcp.sgp++;
-                conn->u.tcp.sgnum--;
-                if (conn->u.tcp.sgnum == 0 && nwrote != 0)
-                    abort();
-            }
-        }
-        if (conn->u.tcp.sgnum == 0) {
-            /* finished sending */
-            /* We should go back to reading, though if we sent a
-               FIELD_TOOLONG error in reply to a length with the high
-               bit set, RFC 4120 says we have to close the TCP
-               stream.  */
-            goto kill_tcp_connection;
-        }
-    } else if (selflags & SSF_READ) {
-        /* Read message length and data into one big buffer, already
-           allocated at connect time.  If we have a complete message,
-           we stop reading, so we should only be here if there is no
-           data in the buffer, or only an incomplete message.  */
-        size_t len;
-        ssize_t nread;
-        if (conn->u.tcp.offset < 4) {
-            /* msglen has not been computed */
-            /* XXX Doing at least two reads here, letting the kernel
-               worry about buffering.  It'll be faster when we add
-               code to manage the buffer here.  */
-            len = 4 - conn->u.tcp.offset;
-            nread = SOCKET_READ(conn->fd,
-                                conn->u.tcp.buffer + conn->u.tcp.offset, len);
-            if (nread < 0)
-                /* error */
-                goto kill_tcp_connection;
-            if (nread == 0)
-                /* eof */
-                goto kill_tcp_connection;
-            conn->u.tcp.offset += nread;
-            if (conn->u.tcp.offset == 4) {
-                unsigned char *p = (unsigned char *)conn->u.tcp.buffer;
-                conn->u.tcp.msglen = load_32_be(p);
-                if (conn->u.tcp.msglen > conn->u.tcp.bufsiz - 4) {
-                    krb5_error_code err;
-                    /* message too big */
-                    krb5_klog_syslog(LOG_ERR, "TCP client %s wants %lu bytes, cap is %lu",
-                                     conn->u.tcp.addrbuf, (unsigned long) conn->u.tcp.msglen,
-                                     (unsigned long) conn->u.tcp.bufsiz - 4);
-                    /* XXX Should return an error.  */
-                    err = make_toolong_error (&conn->u.tcp.response);
-                    if (err) {
-                        krb5_klog_syslog(LOG_ERR,
-                                         "error constructing KRB_ERR_FIELD_TOOLONG error! %s",
-                                         error_message(err));
-                        goto kill_tcp_connection;
-                    }
-                    goto have_response;
-                }
-            }
-        } else {
-            /* msglen known */
-            krb5_data request;
-            krb5_error_code err;
-
-            len = conn->u.tcp.msglen - (conn->u.tcp.offset - 4);
-            nread = SOCKET_READ(conn->fd,
-                                conn->u.tcp.buffer + conn->u.tcp.offset, len);
-            if (nread < 0)
-                /* error */
-                goto kill_tcp_connection;
-            if (nread == 0)
-                /* eof */
-                goto kill_tcp_connection;
-            conn->u.tcp.offset += nread;
-            if (conn->u.tcp.offset < conn->u.tcp.msglen + 4)
-                return;
-            /* have a complete message, and exactly one message */
-            request.length = conn->u.tcp.msglen;
-            request.data = conn->u.tcp.buffer + 4;
-            err = dispatch(&request, &conn->u.tcp.faddr,
-                           &conn->u.tcp.response);
-            if (err) {
-                kdc_err(NULL, err, "while dispatching (tcp)");
-                goto kill_tcp_connection;
-            }
-        have_response:
-            queue_tcp_outgoing_response(conn);
-            FD_CLR(conn->fd, &sstate.rfds);
-        }
-    } else
-        abort();
-
-    return;
-
-kill_tcp_connection:
-    kill_tcp_connection(conn);
-}
-
-static void service_conn(struct connection *conn, int selflags)
-{
-    conn->service(conn, selflags);
-}
-
-/* from sendto_kdc.c */
-static int getcurtime(struct timeval *tvp)
-{
-#ifdef _WIN32
-    struct _timeb tb;
-    _ftime(&tb);
-    tvp->tv_sec = tb.time;
-    tvp->tv_usec = tb.millitm * 1000;
-    return 0;
-#else
-    return gettimeofday(tvp, 0) ? errno : 0;
-#endif
-}
-
-krb5_error_code
-listen_and_process()
-{
-    int                 nfound;
-    /* This struct contains 3 fd_set objects; on some platforms, they
-       can be rather large.  Making this static avoids putting all
-       that junk on the stack.  */
-    static struct select_state sout;
-    int                 i, sret, netchanged = 0;
-    krb5_error_code     err;
-
-    if (conns == (struct connection **) NULL)
-        return KDC5_NONET;
-
-    while (!signal_requests_exit) {
-        if (signal_requests_hup) {
-            int k;
-
-            krb5_klog_reopen(kdc_context);
-            for (k = 0; k < kdc_numrealms; k++)
-                krb5_db_invoke(kdc_realmlist[k]->realm_context,
-                               KRB5_KDB_METHOD_REFRESH_POLICY,
-                               NULL, NULL);
-            signal_requests_hup = 0;
-        }
-
-        if (network_reconfiguration_needed) {
-            /* No point in re-logging what we've just logged.  */
-            if (netchanged == 0)
-                krb5_klog_syslog(LOG_INFO, "network reconfiguration needed");
-            /* It might be tidier to add a timer-callback interface to
-               the control loop here, but for this one use, it's not a
-               big deal.  */
-            err = getcurtime(&sstate.end_time);
-            if (err) {
-                kdc_err(NULL, err, "while getting the time");
-                continue;
-            }
-            sstate.end_time.tv_sec += 3;
-            netchanged = 1;
-        } else
-            sstate.end_time.tv_sec = sstate.end_time.tv_usec = 0;
-
-        err = krb5int_cm_call_select(&sstate, &sout, &sret);
-        if (err) {
-            if (err != EINTR)
-                kdc_err(NULL, err, "while selecting for network input(1)");
-            continue;
-        }
-        if (sret == 0 && netchanged) {
-            network_reconfiguration_needed = 0;
-            closedown_network();
-            err = setup_network();
-            if (err) {
-                kdc_err(NULL, err, "while reinitializing network");
-                return err;
-            }
-            netchanged = 0;
-        }
-        if (sret == -1) {
-            if (errno != EINTR)
-                kdc_err(NULL, errno, "while selecting for network input(2)");
-            continue;
-        }
-        nfound = sret;
-        for (i=0; i<n_sockets && nfound > 0; i++) {
-            int sflags = 0;
-            if (conns[i]->fd < 0)
-                abort();
-            if (FD_ISSET(conns[i]->fd, &sout.rfds))
-                sflags |= SSF_READ, nfound--;
-            if (FD_ISSET(conns[i]->fd, &sout.wfds))
-                sflags |= SSF_WRITE, nfound--;
-            if (sflags)
-                service_conn(conns[i], sflags);
-        }
-    }
-    krb5_klog_syslog(LOG_INFO, "shutdown signal received");
-    return 0;
-}
-
-krb5_error_code
-closedown_network()
-{
-    int i;
-    struct connection *conn;
-
-    if (conns == (struct connection **) NULL)
-        return KDC5_NONET;
-
-    FOREACH_ELT (connections, i, conn) {
-        if (conn->fd >= 0) {
-            krb5_klog_syslog(LOG_INFO, "closing down fd %d", conn->fd);
-            (void) close(conn->fd);
-        }
-        DEL (connections, i);
-        /* There may also be per-connection data in the tcp structure
-           (tcp.buffer, tcp.response) that we're not freeing here.
-           That should only happen if we quit with a connection in
-           progress.  */
-        free(conn);
-    }
-    FREE_SET_DATA(connections);
-    FREE_SET_DATA(udp_port_data);
-    FREE_SET_DATA(tcp_port_data);
-
-    return 0;
-}
-
-#endif /* INET */
index 37a77bcb82bf6730798c7424e5f843e593ab3104..58273248b26d7c21844d39060d1f77bd92f8e13a 100644 (file)
@@ -13,9 +13,7 @@ DEFS=
 ##DOS##XTRA=
 ##DOS##OBJFILE=$(OUTPRE)apputils.lst
 
-# LIBOBJS may or may not contain daemon.o; dummy.o is just here to
-# avoid having an empty library.
-STLIBOBJS=dummy.o @LIBOBJS@
+STLIBOBJS=net-server.o @LIBOBJS@
 STOBJLISTS=OBJS.ST
 LIBBASE=apputils
 
@@ -28,7 +26,7 @@ LINTFILES= daemon.c
 LIBOBJS=$(OUTPRE)daemon.$(OBJEXT)
 
 SRCS=  $(srcdir)/daemon.c \
-       $(srcdir)/dummy.c
+       $(srcdir)/net-server.c
 
 @libpriv_frag@
 @lib_frag@
index c7385886aad7697e0da70c1886b9da698b0b23c9..6e2aab590896344e339acf6647e30a7379175ced 100644 (file)
@@ -11,4 +11,22 @@ daemon.so daemon.po $(OUTPRE)daemon.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
   $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
   $(top_srcdir)/include/socket-utils.h daemon.c
-dummy.so dummy.po $(OUTPRE)dummy.$(OBJEXT): dummy.c
+net-server.so net-server.po $(OUTPRE)net-server.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/cm.h \
+  $(top_srcdir)/include/fake-addrinfo.h $(top_srcdir)/include/foreachaddr.h \
+  $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \
+  $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \
+  $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \
+  $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \
+  $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+  $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h net-server.c
diff --git a/src/lib/apputils/dummy.c b/src/lib/apputils/dummy.c
deleted file mode 100644 (file)
index d5b6cc0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-int lib_server_dummy = 0;
similarity index 90%
rename from src/kadmin/server/network.c
rename to src/lib/apputils/net-server.c
index c8ce4f1eb37a117d67c58d60dba00dbc187c5edb..18582e2722a1a1f4e12f51c17a37e5bfd845b691 100644 (file)
@@ -1,8 +1,8 @@
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
- * kadmin/server/network.c
+ * lib/apputils/net-server.c
  *
- * Copyright 1990,2000,2007,2008,2009 by the Massachusetts Institute of Technology.
+ * Copyright 1990,2000,2007,2008,2009,2010 by the Massachusetts Institute of Technology.
  *
  * Export of this software from the United States of America may
  *   require a specific license from the United States Government.
  * or implied warranty.
  *
  *
- * Network code for Kerberos v5 kadmin server (based on KDC code).
+ * Network code for Kerberos v5 servers (kdc, kadmind).
  */
 
 #include "k5-int.h"
-#include "com_err.h"
-#include "kadm5/admin.h"
-#include "kadm5/server_internal.h"
-#include "kadm5/kadm_rpc.h"
-#include "iprop.h"
 #include "adm_proto.h"
-#include "misc.h"
 #include <sys/ioctl.h>
 #include <syslog.h>
 
 #include <stddef.h>
-#include <ctype.h>
 #include "port-sockets.h"
 #include "socket-utils.h"
 
+#include <gssrpc/rpc.h>
+
 #ifdef HAVE_NETINET_IN_H
 #include <sys/types.h>
 #include <netinet/in.h>
 #endif
 
 #include "fake-addrinfo.h"
+#include "net-server.h"
 
 /* XXX */
 #define KDC5_NONET                               (-1779992062L)
 
+volatile int signal_requests_exit = 0, signal_requests_reset = 0;
+
+static void closedown_network_sockets(void);
+
 /* Misc utility routines.  */
 static void
 set_sa_port(struct sockaddr *addr, int port)
@@ -179,7 +179,7 @@ static const char *paddr (struct sockaddr *sa)
     return buf;
 }
 
-/* kadmin data.  */
+/* KDC data.  */
 
 enum conn_type {
     CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP,
@@ -281,7 +281,7 @@ static SET(struct rpc_svc_data) rpc_svc_data;
 static struct select_state sstate;
 static fd_set rpc_listenfds;
 
-static krb5_error_code add_udp_port(int port)
+krb5_error_code add_udp_port(int port)
 {
     int i;
     void *tmp;
@@ -299,7 +299,7 @@ static krb5_error_code add_udp_port(int port)
     return 0;
 }
 
-static krb5_error_code add_tcp_port(int port)
+krb5_error_code add_tcp_port(int port)
 {
     int i;
     void *tmp;
@@ -317,8 +317,8 @@ static krb5_error_code add_tcp_port(int port)
     return 0;
 }
 
-static krb5_error_code add_rpc_service(int port, u_long prognum, u_long versnum,
-                                       void (*dispatch)())
+krb5_error_code add_rpc_service(int port, u_long prognum, u_long versnum,
+                                void (*dispatch)())
 {
     int i;
     void *tmp;
@@ -370,7 +370,7 @@ add_fd (struct socksetup *data, int sock, enum conn_type conntype,
         return 0;
     }
 #endif
-    newconn = (struct connection *)malloc(sizeof(*newconn));
+    newconn = malloc(sizeof(*newconn));
     if (newconn == NULL) {
         data->retval = ENOMEM;
         com_err(data->prog, ENOMEM,
@@ -964,7 +964,6 @@ static void process_routing_update(void *handle, struct connection *conn,
     int n_read;
     struct rt_msghdr rtm;
 
-    krb5_klog_syslog(LOG_INFO, "routing socket readable");
     while ((n_read = read(conn->fd, &rtm, sizeof(rtm))) > 0) {
         if (n_read < sizeof(rtm)) {
             /* Quick hack to figure out if the interesting
@@ -983,10 +982,12 @@ static void process_routing_update(void *handle, struct connection *conn,
                 return;
             }
         }
+#if 0
         krb5_klog_syslog(LOG_INFO,
                          "got routing msg type %d(%s) v%d",
                          rtm.rtm_type, rtm_type_name(rtm.rtm_type),
                          rtm.rtm_version);
+#endif
         if (rtm.rtm_msglen > sizeof(rtm)) {
             /* It appears we get a partial message and the rest is
                thrown away?  */
@@ -1003,7 +1004,35 @@ static void process_routing_update(void *handle, struct connection *conn,
         case RTM_IFINFO:
         case RTM_OLDADD:
         case RTM_OLDDEL:
-            krb5_klog_syslog(LOG_INFO, "reconfiguration needed");
+            /*
+             * Some flags indicate routing table updates that don't
+             * indicate local address changes.  They may come from
+             * redirects, or ARP, etc.
+             *
+             * This set of symbols is just an initial guess based on
+             * some messages observed in real life; working out which
+             * other flags also indicate messages we should ignore,
+             * and which flags are portable to all system and thus
+             * don't need to be conditionalized, is left as a future
+             * exercise.
+             */
+#ifdef RTF_DYNAMIC
+            if (rtm.rtm_flags & RTF_DYNAMIC)
+                break;
+#endif
+#ifdef RTF_CLONED
+            if (rtm.rtm_flags & RTF_CLONED)
+                break;
+#endif
+#ifdef RTF_LLINFO
+            if (rtm.rtm_flags & RTF_LLINFO)
+                break;
+#endif
+#if 0
+            krb5_klog_syslog(LOG_DEBUG,
+                             "network reconfiguration message (%s) received",
+                             rtm_type_name(rtm.rtm_type));
+#endif
             network_reconfiguration_needed = 1;
             break;
         case RTM_RESOLVE:
@@ -1016,10 +1045,14 @@ static void process_routing_update(void *handle, struct connection *conn,
         case RTM_LOSING:
         case RTM_GET:
             /* Not interesting.  */
+#if 0
             krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting");
+#endif
             break;
         default:
-            krb5_klog_syslog(LOG_INFO, "unhandled routing message type, will reconfigure just for the fun of it");
+            krb5_klog_syslog(LOG_INFO,
+                             "unhandled routing message type %d, will reconfigure just for the fun of it",
+                             rtm.rtm_type);
             network_reconfiguration_needed = 1;
             break;
         }
@@ -1051,8 +1084,6 @@ krb5_error_code
 setup_network(void *handle, const char *prog)
 {
     struct socksetup setup_data;
-    krb5_error_code retval;
-    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
 
     FD_ZERO(&sstate.rfds);
     FD_ZERO(&sstate.wfds);
@@ -1062,30 +1093,6 @@ setup_network(void *handle, const char *prog)
 /*    krb5int_debug_sendto_kdc = 1; */
     krb5int_sendtokdc_debug_handler = klog_handler;
 
-    retval = add_udp_port(server_handle->params.kpasswd_port);
-    if (retval)
-        return retval;
-
-    retval = add_tcp_port(server_handle->params.kpasswd_port);
-    if (retval)
-        return retval;
-
-    retval = add_rpc_service(server_handle->params.kadmind_port,
-                             KADM, KADMVERS,
-                             kadm_1);
-    if (retval)
-        return retval;
-
-#ifndef DISABLE_IPROP
-    if (server_handle->params.iprop_enabled) {
-        retval = add_rpc_service(server_handle->params.iprop_port,
-                                 KRB5_IPROP_PROG, KRB5_IPROP_VERS,
-                                 krb5_iprop_prog_1);
-        if (retval)
-            return retval;
-    }
-#endif /* DISABLE_IPROP */
-
     setup_data.prog = prog;
     setup_data.retval = 0;
     krb5_klog_syslog (LOG_INFO, "setting up network...");
@@ -1114,7 +1121,7 @@ setup_network(void *handle, const char *prog)
     return 0;
 }
 
-static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
+void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
 {
     switch (sa->sa_family) {
     case AF_INET:
@@ -1332,63 +1339,6 @@ send_to_from(int s, void *buf, size_t len, int flags,
 #endif
 }
 
-/* Dispatch routine for set/change password */
-static krb5_error_code
-dispatch(void *handle,
-         struct sockaddr *local_saddr, krb5_fulladdr *remote_faddr,
-         krb5_data *request, krb5_data **response)
-{
-    krb5_error_code ret;
-    krb5_keytab kt = NULL;
-    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
-    krb5_fulladdr local_faddr;
-    krb5_address **local_kaddrs = NULL, local_kaddr_buf;
-
-    *response = NULL;
-
-    if (local_saddr == NULL) {
-        ret = krb5_os_localaddr(server_handle->context, &local_kaddrs);
-        if (ret != 0)
-            goto cleanup;
-
-        local_faddr.address = local_kaddrs[0];
-        local_faddr.port = 0;
-    } else {
-        local_faddr.address = &local_kaddr_buf;
-        init_addr(&local_faddr, local_saddr);
-    }
-
-    ret = krb5_kt_resolve(server_handle->context, "KDB:", &kt);
-    if (ret != 0) {
-        krb5_klog_syslog(LOG_ERR, "chpw: Couldn't open admin keytab %s",
-                         krb5_get_error_message(server_handle->context, ret));
-        goto cleanup;
-    }
-
-    *response = (krb5_data *)malloc(sizeof(krb5_data));
-    if (*response == NULL) {
-        ret = ENOMEM;
-        goto cleanup;
-    }
-
-    ret = process_chpw_request(server_handle->context,
-                               handle,
-                               server_handle->params.realm,
-                               kt,
-                               &local_faddr,
-                               remote_faddr,
-                               request,
-                               *response);
-
-cleanup:
-    if (local_kaddrs != NULL)
-        krb5_free_addresses(server_handle->context, local_kaddrs);
-
-    krb5_kt_close(server_handle->context, kt);
-
-    return ret;
-}
-
 static void process_packet(void *handle,
                            struct connection *conn, const char *prog,
                            int selflags)
@@ -1404,7 +1354,6 @@ static void process_packet(void *handle,
     char pktbuf[MAX_DGRAM_SIZE];
     int port_fd = conn->fd;
     union aux_addressing_info auxaddr;
-    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
 
     response = NULL;
     saddr_len = sizeof(saddr);
@@ -1453,7 +1402,7 @@ static void process_packet(void *handle,
     faddr.address = &addr;
     init_addr(&faddr, ss2sa(&saddr));
     /* this address is in net order */
-    if ((retval = dispatch(handle, ss2sa(&daddr), &faddr, &request, &response))) {
+    if ((retval = dispatch(handle, ss2sa(&daddr), &faddr, &request, &response, 0))) {
         com_err(prog, retval, "while dispatching (udp)");
         return;
     }
@@ -1471,7 +1420,7 @@ static void process_packet(void *handle,
         char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV];
         char daddrbuf[NI_MAXHOST];
         int e = errno;
-        krb5_free_data(server_handle->context, response);
+        krb5_free_data(get_context(handle), response);
         if (getnameinfo((struct sockaddr *)&daddr, daddr_len,
                         daddrbuf, sizeof(daddrbuf), 0, 0,
                         NI_NUMERICHOST) != 0) {
@@ -1491,7 +1440,7 @@ static void process_packet(void *handle,
         com_err(prog, 0, "short reply write %d vs %d\n",
                 response->length, cc);
     }
-    krb5_free_data(server_handle->context, response);
+    krb5_free_data(get_context(handle), response);
     return;
 }
 
@@ -1613,13 +1562,11 @@ static void accept_tcp_connection(void *handle,
 static void
 kill_tcp_or_rpc_connection(void *handle, struct connection *conn, int isForcedClose)
 {
-    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
-
     assert(conn->type == CONN_TCP || conn->type == CONN_RPC);
     assert(conn->fd != -1);
 
     if (conn->u.tcp.response)
-        krb5_free_data(server_handle->context, conn->u.tcp.response);
+        krb5_free_data(get_context(handle), conn->u.tcp.response);
     if (conn->u.tcp.buffer)
         free(conn->u.tcp.buffer);
     FD_CLR(conn->fd, &sstate.rfds);
@@ -1657,44 +1604,6 @@ kill_tcp_or_rpc_connection(void *handle, struct connection *conn, int isForcedCl
     tcp_or_rpc_data_counter--;
 }
 
-static krb5_error_code
-make_toolong_error (void *handle, krb5_data **out)
-{
-    krb5_error errpkt;
-    krb5_error_code retval;
-    krb5_data *scratch;
-    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
-
-    retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec);
-    if (retval)
-        return retval;
-    errpkt.error = KRB_ERR_FIELD_TOOLONG;
-    retval = krb5_build_principal(server_handle->context, &errpkt.server,
-                                  strlen(server_handle->params.realm),
-                                  server_handle->params.realm,
-                                  "kadmin", "changepw", NULL);
-    if (retval)
-        return retval;
-    errpkt.client = NULL;
-    errpkt.cusec = 0;
-    errpkt.ctime = 0;
-    errpkt.text.length = 0;
-    errpkt.text.data = 0;
-    errpkt.e_data.length = 0;
-    errpkt.e_data.data = 0;
-    scratch = malloc(sizeof(*scratch));
-    if (scratch == NULL)
-        return ENOMEM;
-    retval = krb5_mk_error(server_handle->context, &errpkt, scratch);
-    if (retval) {
-        free(scratch);
-        return retval;
-    }
-
-    *out = scratch;
-    return 0;
-}
-
 static void
 queue_tcp_outgoing_response(struct connection *conn)
 {
@@ -1819,7 +1728,7 @@ process_tcp_connection(void *handle,
             }
 
             err = dispatch(handle, local_saddrp, &conn->u.tcp.faddr,
-                           &request, &conn->u.tcp.response);
+                           &request, &conn->u.tcp.response, 1);
             if (err) {
                 com_err(prog, err, "while dispatching (tcp)");
                 goto kill_tcp_connection;
@@ -1858,7 +1767,8 @@ static int getcurtime(struct timeval *tvp)
 }
 
 krb5_error_code
-listen_and_process(void *handle, const char *prog)
+listen_and_process(void *handle, const char *prog,
+                   void (*reset)(void))
 {
     int                 nfound;
     /* This struct contains 3 fd_set objects; on some platforms, they
@@ -1867,29 +1777,21 @@ listen_and_process(void *handle, const char *prog)
     static struct select_state sout;
     int                 i, sret, netchanged = 0;
     krb5_error_code     err;
-    kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
 
     if (conns == (struct connection **) NULL)
         return KDC5_NONET;
 
-    while (!signal_request_exit) {
-        if (signal_request_hup) {
-            krb5_klog_reopen(server_handle->context);
-            reset_db();
-            signal_request_hup = 0;
-        }
-#ifdef PURIFY
-        if (signal_pure_report) {
-            purify_new_reports();
-            signal_pure_report = 0;
+    while (!signal_requests_exit) {
+        if (signal_requests_reset) {
+            krb5_klog_reopen(get_context(handle));
+            reset();
+            signal_requests_reset = 0;
         }
-        if (signal_pure_clear) {
-            purify_clear_new_reports();
-            signal_pure_clear = 0;
-        }
-#endif /* PURIFY */
+
         if (network_reconfiguration_needed) {
-            krb5_klog_syslog(LOG_INFO, "network reconfiguration needed");
+            /* No point in re-logging what we've just logged.  */
+            if (netchanged == 0)
+                krb5_klog_syslog(LOG_INFO, "network reconfiguration needed");
             /* It might be tidier to add a timer-callback interface to
                the control loop here, but for this one use, it's not a
                big deal.  */
@@ -1911,7 +1813,7 @@ listen_and_process(void *handle, const char *prog)
         }
         if (sret == 0 && netchanged) {
             network_reconfiguration_needed = 0;
-            closedown_network(handle, prog);
+            closedown_network_sockets();
             err = setup_network(handle, prog);
             if (err) {
                 com_err(prog, err, "while reinitializing network");
@@ -1941,14 +1843,14 @@ listen_and_process(void *handle, const char *prog)
     return 0;
 }
 
-krb5_error_code
-closedown_network(void *handle, const char *prog)
+static void
+closedown_network_sockets()
 {
     int i;
     struct connection *conn;
 
     if (conns == (struct connection **) NULL)
-        return KDC5_NONET;
+        return;
 
     FOREACH_ELT (connections, i, conn) {
         if (conn->fd >= 0) {
@@ -1974,12 +1876,16 @@ closedown_network(void *handle, const char *prog)
            progress.  */
         free(conn);
     }
+}
+
+void
+closedown_network()
+{
+    closedown_network_sockets();
     FREE_SET_DATA(connections);
     FREE_SET_DATA(udp_port_data);
     FREE_SET_DATA(tcp_port_data);
     FREE_SET_DATA(rpc_svc_data);
-
-    return 0;
 }
 
 static void accept_rpc_connection(void *handle, struct connection *conn,