To: | krb5-bugs@mit.edu |
Subject: | feature: krb5kdc as a wait service. |
Date: | Wed, 22 Apr 2009 00:41:34 -0400 |
From: | Roland Dowdeswell <elric@imrryr.org> |
Sometimes it is nice to be able to start daemons as a wait service from
inetd or similar program. This provides some benefits mainly revolving
around being restarted if things go awry.
I attach a small patch which allows for krb5kdc to be started as
a TCP or UDP wait service.
--
Roland Dowdeswell http://Imrryr.ORG/~elric/
Index: main.c
===================================================================
RCS file: /ms/dev/kerberos/mitkrb5/cvs-dirs/mitkrb5-1.4/mitkrb5/src/kdc/main.c,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -r1.2 -r1.4
--- main.c 29 Mar 2005 14:43:21 -0000 1.2
+++ main.c 29 Jan 2007 19:06:18 -0000 1.4
@@ -66,6 +66,7 @@
void finish_realms (char *);
static int nofork = 0;
+static int nowait = 1;
static int rkey_init_done = 0;
#ifdef POSIX_SIGNALS
@@ -464,7 +465,7 @@
* Loop through the option list. Each time we encounter a realm name,
* use the previously scanned options to fill in for defaults.
*/
- while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:n4:X3")) != -1) {
+ while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:nw4:X3")) != -1) {
switch(c) {
case 'r': /* realm name for db */
if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
@@ -513,6 +514,10 @@
default_tcp_ports = strdup(optarg);
#endif
break;
+ case 'w':
+ nowait = 0;
+ nofork = 1;
+ break;
case '4':
#ifdef KRB5_KRB4_COMPAT
if (v4mode)
@@ -670,7 +675,13 @@
return 1;
}
- if ((retval = setup_network(argv[0]))) {
+ if (nowait && (retval = setup_network(argv[0]))) {
+ com_err(argv[0], retval, "while initializing network");
+ finish_realms(argv[0]);
+ return 1;
+ }
+
+ if (!nowait && (retval = setup_network_inetd_wait(*argv))) {
com_err(argv[0], retval, "while initializing network");
finish_realms(argv[0]);
return 1;
Index: network.c
===================================================================
RCS file: /ms/dev/kerberos/mitkrb5/cvs-dirs/mitkrb5-1.4/mitkrb5/src/kdc/network.c,v
retrieving revision 1.5
retrieving revision 1.7
diff -u -r1.5 -r1.7
--- network.c 21 Jul 2005 13:12:34 -0000 1.5
+++ network.c 1 Feb 2007 01:18:56 -0000 1.7
@@ -63,6 +63,14 @@
#include <sys/filio.h> /* FIONBIO */
#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
#include "fake-addrinfo.h"
/* Misc utility routines. */
@@ -675,6 +683,51 @@
return 0;
}
+
+
+krb5_error_code
+setup_network_inetd_wait(const char *prog)
+{
+ socklen_t len;
+ struct socksetup data;
+ int devnull = open(_PATH_DEVNULL, O_RDWR, 0);
+ int fd;
+ int type;
+
+ data.prog = prog;
+ data.retval = 0;
+
+ fd = dup(STDIN_FILENO);
+
+ /*
+ * Unfortunately, we duplicate code from daemon(3) but can't
+ * reuse it. We definitely want to bounce the fds about 2 for
+ * obvious reasons.
+ */
+ (void) chdir("/");
+ if (devnull != -1) {
+ (void) dup2(devnull, 0);
+ (void) dup2(devnull, 1);
+ (void) dup2(devnull, 2);
+ if (devnull > 2)
+ (void) close(devnull);
+ }
+
+ len = sizeof(type);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)) {
+ krb5_klog_syslog(LOG_ERR, "getsockopt(2) error: %m");
+ return -1; /* XXXrcd: wrong error. */
+ }
+
+ FD_SET(fd, &sstate.rfds);
+ if (fd >= sstate.max)
+ sstate.max = fd + 1;
+ krb5_klog_syslog(LOG_INFO, "listening on fd %d (inetd, type %d)", fd, type);
+ if (type == SOCK_DGRAM)
+ return !add_udp_fd(&data, fd);
+ return !add_tcp_listener_fd(&data, fd);
+}
+
static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
{
inetd or similar program. This provides some benefits mainly revolving
around being restarted if things go awry.
I attach a small patch which allows for krb5kdc to be started as
a TCP or UDP wait service.
--
Roland Dowdeswell http://Imrryr.ORG/~elric/
Index: main.c
===================================================================
RCS file: /ms/dev/kerberos/mitkrb5/cvs-dirs/mitkrb5-1.4/mitkrb5/src/kdc/main.c,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -r1.2 -r1.4
--- main.c 29 Mar 2005 14:43:21 -0000 1.2
+++ main.c 29 Jan 2007 19:06:18 -0000 1.4
@@ -66,6 +66,7 @@
void finish_realms (char *);
static int nofork = 0;
+static int nowait = 1;
static int rkey_init_done = 0;
#ifdef POSIX_SIGNALS
@@ -464,7 +465,7 @@
* Loop through the option list. Each time we encounter a realm name,
* use the previously scanned options to fill in for defaults.
*/
- while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:n4:X3")) != -1) {
+ while ((c = getopt(argc, argv, "r:d:mM:k:R:e:p:s:nw4:X3")) != -1) {
switch(c) {
case 'r': /* realm name for db */
if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
@@ -513,6 +514,10 @@
default_tcp_ports = strdup(optarg);
#endif
break;
+ case 'w':
+ nowait = 0;
+ nofork = 1;
+ break;
case '4':
#ifdef KRB5_KRB4_COMPAT
if (v4mode)
@@ -670,7 +675,13 @@
return 1;
}
- if ((retval = setup_network(argv[0]))) {
+ if (nowait && (retval = setup_network(argv[0]))) {
+ com_err(argv[0], retval, "while initializing network");
+ finish_realms(argv[0]);
+ return 1;
+ }
+
+ if (!nowait && (retval = setup_network_inetd_wait(*argv))) {
com_err(argv[0], retval, "while initializing network");
finish_realms(argv[0]);
return 1;
Index: network.c
===================================================================
RCS file: /ms/dev/kerberos/mitkrb5/cvs-dirs/mitkrb5-1.4/mitkrb5/src/kdc/network.c,v
retrieving revision 1.5
retrieving revision 1.7
diff -u -r1.5 -r1.7
--- network.c 21 Jul 2005 13:12:34 -0000 1.5
+++ network.c 1 Feb 2007 01:18:56 -0000 1.7
@@ -63,6 +63,14 @@
#include <sys/filio.h> /* FIONBIO */
#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
#include "fake-addrinfo.h"
/* Misc utility routines. */
@@ -675,6 +683,51 @@
return 0;
}
+
+
+krb5_error_code
+setup_network_inetd_wait(const char *prog)
+{
+ socklen_t len;
+ struct socksetup data;
+ int devnull = open(_PATH_DEVNULL, O_RDWR, 0);
+ int fd;
+ int type;
+
+ data.prog = prog;
+ data.retval = 0;
+
+ fd = dup(STDIN_FILENO);
+
+ /*
+ * Unfortunately, we duplicate code from daemon(3) but can't
+ * reuse it. We definitely want to bounce the fds about 2 for
+ * obvious reasons.
+ */
+ (void) chdir("/");
+ if (devnull != -1) {
+ (void) dup2(devnull, 0);
+ (void) dup2(devnull, 1);
+ (void) dup2(devnull, 2);
+ if (devnull > 2)
+ (void) close(devnull);
+ }
+
+ len = sizeof(type);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)) {
+ krb5_klog_syslog(LOG_ERR, "getsockopt(2) error: %m");
+ return -1; /* XXXrcd: wrong error. */
+ }
+
+ FD_SET(fd, &sstate.rfds);
+ if (fd >= sstate.max)
+ sstate.max = fd + 1;
+ krb5_klog_syslog(LOG_INFO, "listening on fd %d (inetd, type %d)", fd, type);
+ if (type == SOCK_DGRAM)
+ return !add_udp_fd(&data, fd);
+ return !add_tcp_listener_fd(&data, fd);
+}
+
static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
{