changeset 71:ac96bc733e71

adding inetd mode back from 0.43
author Matt Johnston <matt@ucc.asn.au>
date Thu, 12 Aug 2004 17:18:53 +0000
parents b0316ce64e4b
children 9597c2e3b9d4
files options.h runopts.h svr-main.c svr-runopts.c
diffstat 4 files changed, 123 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/options.h	Thu Aug 12 16:41:58 2004 +0000
+++ b/options.h	Thu Aug 12 17:18:53 2004 +0000
@@ -42,6 +42,19 @@
 #define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key"
 #endif
 
+/* Set NON_INETD_MODE if you require daemon functionality (ie Dropbear listens
+ * on chosen ports and keeps accepting connections. This is the default.
+ *
+ * Set INETD_MODE if you want to be able to run Dropbear with inetd (or
+ * similar), where it will use stdin/stdout for connections, and each process
+ * lasts for a single connection. Dropbear should be invoked with the -i flag
+ * for inetd, and can only accept IPv4 connections.
+ *
+ * Both of these flags can be defined at once, don't compile without at least
+ * one of them. */
+#define NON_INETD_MODE
+#define INETD_MODE
+
 /* Setting this disables the fast exptmod bignum code. It saves ~5kB, but is
  * perhaps 20% slower for pubkey operations (it is probably worth experimenting
  * if you want to use this) */
--- a/runopts.h	Thu Aug 12 16:41:58 2004 +0000
+++ b/runopts.h	Thu Aug 12 17:18:53 2004 +0000
@@ -55,6 +55,8 @@
 	uint16_t *ports;
 	unsigned int portcount;
 
+	int inetdmode;
+
 	/* Flags indicating whether to use ipv4 and ipv6 */
 	/* not used yet
 	int ipv4;
--- a/svr-main.c	Thu Aug 12 16:41:58 2004 +0000
+++ b/svr-main.c	Thu Aug 12 17:18:53 2004 +0000
@@ -33,6 +33,9 @@
 static void sigchld_handler(int dummy);
 static void sigsegv_handler(int);
 static void sigintterm_handler(int fish);
+static void main_inetd();
+static void main_noinetd();
+static void commonsetup();
 
 static int childpipes[MAX_UNAUTH_CLIENTS];
 
@@ -44,6 +47,67 @@
 #endif
 {
 	
+
+	_dropbear_exit = svr_dropbear_exit;
+	_dropbear_log = svr_dropbear_log;
+
+	/* get commandline options */
+	svr_getopts(argc, argv);
+
+#ifdef INETD_MODE
+	/* service program mode */
+	if (svr_opts.inetdmode) {
+		main_inetd();
+		/* notreached */
+	}
+#endif
+
+#ifdef NON_INETD_MODE
+	main_noinetd();
+	/* notreached */
+#endif
+
+	dropbear_exit("Compiled without normal mode, can't run without -i\n");
+	return -1;
+}
+#endif
+
+#ifdef INETD_MODE
+static void main_inetd() {
+
+	struct sockaddr_storage remoteaddr;
+	int remoteaddrlen;
+	char * addrstring = NULL;
+
+	/* Set up handlers, syslog */
+	commonsetup();
+
+	remoteaddrlen = sizeof(remoteaddr);
+	if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) {
+		dropbear_exit("Unable to getpeername: %s", strerror(errno));
+	}
+
+	/* In case our inetd was lax in logging source addresses */
+	addrstring = getaddrstring(&remoteaddr, 1);
+	dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
+	m_free(addrstring);
+
+	/* Don't check the return value - it may just fail since inetd has
+	 * already done setsid() after forking (xinetd on Darwin appears to do
+	 * this */
+	setsid();
+
+	/* Start service program 
+	 * -1 is a dummy childpipe, just something we can close() without 
+	 * mattering. */
+	svr_session(0, -1, getaddrhostname(&remoteaddr));
+
+	/* notreached */
+}
+#endif /* INETD_MODE */
+
+#ifdef NON_INETD_MODE
+void main_noinetd() {
 	fd_set fds;
 	struct timeval seltimeout;
 	unsigned int i, j;
@@ -53,20 +117,13 @@
 	int remoteaddrlen;
 	int listensocks[MAX_LISTEN_ADDR];
 	int listensockcount = 0;
-	FILE * pidfile;
+	FILE *pidfile = NULL;
 
 	int childsock;
 	pid_t childpid;
 	int childpipe[2];
 
 	struct sigaction sa_chld;
-
-	_dropbear_exit = svr_dropbear_exit;
-	_dropbear_log = svr_dropbear_log;
-
-	/* get commandline options */
-	svr_getopts(argc, argv);
-
 	/* fork */
 	if (svr_opts.forkbg) {
 		int closefds = 0;
@@ -76,16 +133,11 @@
 		}
 #endif
 		if (daemon(0, closefds) < 0) {
-			dropbear_exit("Failed to create background process: %s",
-					strerror(errno));
+			dropbear_exit("Failed to daemonize: %s", strerror(errno));
 		}
 	}
 
-#ifndef DISABLE_SYSLOG
-	if (svr_opts.usingsyslog) {
-		startsyslog();
-	}
-#endif
+	commonsetup();
 
 	/* should be done after syslog is working */
 	if (svr_opts.forkbg) {
@@ -101,25 +153,6 @@
 		fclose(pidfile);
 	}
 
-	/* set up cleanup handler */
-	if (signal(SIGINT, sigintterm_handler) == SIG_ERR || 
-#ifndef DEBUG_VALGRIND
-		signal(SIGTERM, sigintterm_handler) == SIG_ERR ||
-#endif
-		signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
-		dropbear_exit("signal() error");
-	}
-
-	/* catch and reap zombie children */
-	sa_chld.sa_handler = sigchld_handler;
-	sa_chld.sa_flags = SA_NOCLDSTOP;
-	if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
-		dropbear_exit("signal() error");
-	}
-	if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) {
-		dropbear_exit("signal() error");
-	}
-
 	/* sockets to identify pre-authenticated clients */
 	for (i = 0; i < MAX_UNAUTH_CLIENTS; i++) {
 		childpipes[i] = -1;
@@ -186,7 +219,6 @@
 			if (!FD_ISSET(listensocks[i], &fds)) 
 				continue;
 
-			/* child connection XXX - ip6 stuff here */
 			remoteaddrlen = sizeof(remoteaddr);
 			childsock = accept(listensocks[i], 
 					(struct sockaddr*)&remoteaddr, &remoteaddrlen);
@@ -262,9 +294,9 @@
 	} /* for(;;) loop */
 
 	/* don't reach here */
-	return -1;
 }
-#endif
+#endif /* NON_INETD_MODE */
+
 
 /* catch + reap zombie children */
 static void sigchld_handler(int fish) {
@@ -292,6 +324,36 @@
 	exitflag = 1;
 }
 
+/* Things used by inetd and non-inetd modes */
+static void commonsetup() {
+
+	struct sigaction sa_chld;
+#ifndef DISABLE_SYSLOG
+	if (svr_opts.usingsyslog) {
+		startsyslog();
+	}
+#endif
+
+	/* set up cleanup handler */
+	if (signal(SIGINT, sigintterm_handler) == SIG_ERR || 
+#ifndef DEBUG_VALGRIND
+		signal(SIGTERM, sigintterm_handler) == SIG_ERR ||
+#endif
+		signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+		dropbear_exit("signal() error");
+	}
+
+	/* catch and reap zombie children */
+	sa_chld.sa_handler = sigchld_handler;
+	sa_chld.sa_flags = SA_NOCLDSTOP;
+	if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) {
+		dropbear_exit("signal() error");
+	}
+	if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) {
+		dropbear_exit("signal() error");
+	}
+}
+
 /* Set up listening sockets for all the requested ports */
 static int listensockets(int *sock, int sockcount, int *maxfd) {
 	
--- a/svr-runopts.c	Thu Aug 12 16:41:58 2004 +0000
+++ b/svr-runopts.c	Thu Aug 12 17:18:53 2004 +0000
@@ -73,8 +73,9 @@
 #endif
 					"-p port	Listen on specified tcp port, up to %d can be specified\n"
 					"		(default %d if none specified)\n"
-/*					"-4/-6		Disable listening on ipv4/ipv6 respectively\n"*/
-
+#ifdef INETD_MODE
+					"-i		Start for inetd\n"
+#endif
 					,DROPBEAR_VERSION, progname,
 #ifdef DROPBEAR_DSS
 					DSS_PRIV_FILENAME,
@@ -102,6 +103,7 @@
 	svr_opts.norootlogin = 0;
 	svr_opts.noauthpass = 0;
 	svr_opts.norootpass = 0;
+	svr_opts.inetdmode = 0;
 	opts.nolocaltcp = 0;
 	opts.noremotetcp = 0;
 	/* not yet
@@ -158,6 +160,11 @@
 					opts.noremotetcp = 1;
 					break;
 #endif
+#ifdef INETD_MODE
+				case 'i':
+					svr_opts.inetdmode = 1;
+					break;
+#endif
 				case 'p':
 					if (portnum < DROPBEAR_MAX_PORTS) {
 						portstring[portnum] = NULL;