Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 06 Nov 1996 12:03:48 -0800
From:      Julian Elischer <julian@whistle.com>
To:        hackers@freebsd.org
Subject:   Inetd mod.. comments?
Message-ID:  <3280EF24.ABD322C@whistle.com>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

--------------2F1CF0FB237C228A31DFF4F5
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I have some patches to Inetd her that I sent out for comment.
the only comment I got was
"Gee that's neat!, I need that"

but no technical reviews or code checks..

I would like to commit this change but I don't want to do it 
without a reviewer to put on the commit message..

I include the patch (actually a slightly improved version)
again...

As I said before this provides us (whistle) with protection against
a denial of service attack.

reviews please.....

--------------2F1CF0FB237C228A31DFF4F5
Content-Type: text/plain; charset=us-ascii; name="inetd.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="inetd.patch"

Index: Makefile
===================================================================
RCS file: /cvs/freebsd/src/usr.sbin/inetd/Makefile,v
retrieving revision 1.3
diff -c -r1.3 Makefile
*** 1.3	1996/01/01 08:42:22
--- Makefile	1996/11/06 19:02:22
***************
*** 4,9 ****
--- 4,12 ----
  MAN8=	inetd.8
  MLINKS=	inetd.8 inetd.conf.5
  
+ COPTS+=	-Wall
+ COPTS+=	-DSANITY_CHECK
+ 
  DPADD+=	${LIBUTIL}
  LDADD+=	-lutil
  
Index: inetd.8
===================================================================
RCS file: /cvs/freebsd/src/usr.sbin/inetd/inetd.8,v
retrieving revision 1.9
diff -c -r1.9 inetd.8
*** 1.9	1996/08/09 22:20:23
--- inetd.8	1996/11/06 19:02:22
***************
*** 101,107 ****
  service name
  socket type
  protocol
! wait/nowait
  user
  server program
  server program arguments
--- 101,107 ----
  service name
  socket type
  protocol
! {wait|nowait}[/max-child]
  user
  server program
  server program arguments
***************
*** 260,265 ****
--- 260,274 ----
  requests until a timeout.
  TCPMUX services must use 
  .Dq nowait .
+ .Pp
+ The maximum number of outstanding child processes (or ``threads'')
+ for a ``nowait'' service may be explicitly specified by appending a
+ ``/'' followed by the number to the ``nowait'' keyword. Normally
+ (or if a value of zero is specified) there is no maximum. Otherwise,
+ once the maximum is reached, further connection attempts will be
+ queued up until an existing child process exits. This also works
+ in the case of ``wait'' mode, although a value other than one (the
+ default) might not make sense in some cases.
  .Pp
  The
  .Em user
Index: inetd.c
===================================================================
RCS file: /cvs/freebsd/src/usr.sbin/inetd/inetd.c,v
retrieving revision 1.15
diff -c -r1.15 inetd.c
*** 1.15	1996/11/01 01:42:08
--- inetd.c	1996/11/06 19:02:22
***************
*** 32,45 ****
   */
  
  #ifndef lint
! static char copyright[] =
  "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
  	The Regents of the University of California.  All rights reserved.\n";
  #endif /* not lint */
  
  #ifndef lint
  /* from: @(#)inetd.c	8.4 (Berkeley) 4/13/94"; */
! static char inetd_c_rcsid[] =
  	"$Id: inetd.c,v 1.15 1996/11/01 01:42:08 alex Exp $";
  #endif /* not lint */
  
--- 32,45 ----
   */
  
  #ifndef lint
! static char copyright[] __attribute__ ((unused)) =
  "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
  	The Regents of the University of California.  All rights reserved.\n";
  #endif /* not lint */
  
  #ifndef lint
  /* from: @(#)inetd.c	8.4 (Berkeley) 4/13/94"; */
! static char inetd_c_rcsid[] __attribute__ ((unused)) =
  	"$Id: inetd.c,v 1.15 1996/11/01 01:42:08 alex Exp $";
  #endif /* not lint */
  
***************
*** 112,117 ****
--- 112,118 ----
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <rpc/rpc.h>
+ #include <rpc/pmap_clnt.h>
  
  #include <errno.h>
  #include <fcntl.h>
***************
*** 124,139 ****
  #include <syslog.h>
  #include <unistd.h>
  #include <libutil.h>
  
  #include "pathnames.h"
  
  #define	TOOMANY		256		/* don't start more than TOOMANY */
  #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
  #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
  
  #define	SIGBLOCK	(sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
  
- 
  int	debug = 0;
  int	log = 0;
  int	nsock, maxsock;
--- 125,141 ----
  #include <syslog.h>
  #include <unistd.h>
  #include <libutil.h>
+ #include <sysexits.h>
  
  #include "pathnames.h"
  
  #define	TOOMANY		256		/* don't start more than TOOMANY */
  #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
  #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
+ #define MAX_MAXCHLD	32767		/* max allowable max children */
  
  #define	SIGBLOCK	(sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
  
  int	debug = 0;
  int	log = 0;
  int	nsock, maxsock;
***************
*** 149,155 ****
  	char	*se_service;		/* name of service */
  	int	se_socktype;		/* type of socket to use */
  	char	*se_proto;		/* protocol used */
! 	short	se_wait;		/* single threaded server */
  	short	se_checked;		/* looked at during merge */
  	char	*se_user;		/* user name to run as */
  	struct	biltin *se_bi;		/* if built-in, description */
--- 151,159 ----
  	char	*se_service;		/* name of service */
  	int	se_socktype;		/* type of socket to use */
  	char	*se_proto;		/* protocol used */
! 	short	se_maxchild;		/* max number of children */
! 	short	se_numchild;		/* current number of children */
! 	short	*se_pids;		/* array of child pids */
  	short	se_checked;		/* looked at during merge */
  	char	*se_user;		/* user name to run as */
  	struct	biltin *se_bi;		/* if built-in, description */
***************
*** 159,165 ****
  	int	se_fd;			/* open descriptor */
  	int	se_type;		/* type */
  	struct	sockaddr_in se_ctrladdr;/* bound address */
! 	int	se_rpc;			/* ==1 if RPC service */
  	int	se_rpc_prog;		/* RPC program number */
  	u_int	se_rpc_lowvers;		/* RPC low version */
  	u_int	se_rpc_highvers;	/* RPC high version */
--- 163,170 ----
  	int	se_fd;			/* open descriptor */
  	int	se_type;		/* type */
  	struct	sockaddr_in se_ctrladdr;/* bound address */
! 	u_char	se_accept;		/* i.e., wait/nowait mode */
! 	u_char	se_rpc;			/* ==1 if RPC service */
  	int	se_rpc_prog;		/* RPC program number */
  	u_int	se_rpc_lowvers;		/* RPC low version */
  	u_int	se_rpc_highvers;	/* RPC high version */
***************
*** 195,201 ****
--- 200,209 ----
  char	       *newstr __P((char *));
  char	       *nextline __P((FILE *));
  void		print_service __P((char *, struct servtab *));
+ void		addchild __P((struct servtab *, int));
  void		reapchild __P((int));
+ void		enable __P((struct servtab *));
+ void		disable __P((struct servtab *));
  void		retry __P((int));
  int		setconfig __P((void));
  void		setup __P((struct servtab *));
***************
*** 209,215 ****
  	char	*bi_service;		/* internally provided service name */
  	int	bi_socktype;		/* type of socket supported */
  	short	bi_fork;		/* 1 if should fork before call */
! 	short	bi_wait;		/* 1 if should wait for child */
  	void	(*bi_fn)();		/* function which performs it */
  } biltins[] = {
  	/* Echo received data */
--- 217,223 ----
  	char	*bi_service;		/* internally provided service name */
  	int	bi_socktype;		/* type of socket supported */
  	short	bi_fork;		/* 1 if should fork before call */
! 	short	bi_maxchild;		/* max number of children (default) */
  	void	(*bi_fn)();		/* function which performs it */
  } biltins[] = {
  	/* Echo received data */
***************
*** 298,304 ****
  			if (!inet_aton(optarg, &bind_address)) {
  				syslog(LOG_ERR,
  			         "-a %s: invalid IP address", optarg);
! 				 exit(1);
  			}
  			break;
  		case 'p':
--- 306,312 ----
  			if (!inet_aton(optarg, &bind_address)) {
  				syslog(LOG_ERR,
  			         "-a %s: invalid IP address", optarg);
! 				exit(EX_USAGE);
  			}
  			break;
  		case 'p':
***************
*** 309,315 ****
  			syslog(LOG_ERR,
  				"usage: inetd [-dl] [-a address] [-R rate]"
  				" [-p pidfile] [conf-file]");
! 			exit(1);
  		}
  	argc -= optind;
  	argv += optind;
--- 317,323 ----
  			syslog(LOG_ERR,
  				"usage: inetd [-dl] [-a address] [-R rate]"
  				" [-p pidfile] [conf-file]");
! 			exit(EX_USAGE);
  		}
  	argc -= optind;
  	argv += optind;
***************
*** 383,389 ****
  		    if (debug)
  			    fprintf(stderr, "someone wants %s\n",
  				sep->se_service);
! 		    if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
  			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
  				(int *)0);
  			    if (debug)
--- 391,397 ----
  		    if (debug)
  			    fprintf(stderr, "someone wants %s\n",
  				sep->se_service);
! 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
  			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
  				(int *)0);
  			    if (debug)
***************
*** 395,401 ****
  						sep->se_service);
  				    continue;
  			    }
! 			    if(log) {
  				i = sizeof peer;
  				if(getpeername(ctrl, (struct sockaddr *)
  						&peer, &i)) {
--- 403,409 ----
  						sep->se_service);
  				    continue;
  			    }
! 			    if (log) {
  				i = sizeof peer;
  				if(getpeername(ctrl, (struct sockaddr *)
  						&peer, &i)) {
***************
*** 456,475 ****
  		    }
  		    if (pid < 0) {
  			    syslog(LOG_ERR, "fork: %m");
! 			    if (!sep->se_wait &&
  				sep->se_socktype == SOCK_STREAM)
  				    close(ctrl);
  			    sigsetmask(0L);
  			    sleep(1);
  			    continue;
  		    }
! 		    if (pid && sep->se_wait) {
! 			    sep->se_wait = pid;
! 			    if (sep->se_fd >= 0) {
! 				FD_CLR(sep->se_fd, &allsock);
! 			        nsock--;
! 			    }
! 		    }
  		    sigsetmask(0L);
  		    if (pid == 0) {
  			    if (dofork) {
--- 464,478 ----
  		    }
  		    if (pid < 0) {
  			    syslog(LOG_ERR, "fork: %m");
! 			    if (sep->se_accept &&
  				sep->se_socktype == SOCK_STREAM)
  				    close(ctrl);
  			    sigsetmask(0L);
  			    sleep(1);
  			    continue;
  		    }
! 		    if (pid)
! 			addchild(sep, pid);
  		    sigsetmask(0L);
  		    if (pid == 0) {
  			    if (dofork) {
***************
*** 478,488 ****
  						maxsock);
  				for (tmpint = maxsock; tmpint > 2; tmpint--)
  					if (tmpint != ctrl)
! 						close(tmpint);
  			    }
! 			    if (sep->se_bi)
  				(*sep->se_bi->bi_fn)(ctrl, sep);
! 			    else {
  				if (debug)
  					fprintf(stderr, "%d execl %s\n",
  					    getpid(), sep->se_server);
--- 481,492 ----
  						maxsock);
  				for (tmpint = maxsock; tmpint > 2; tmpint--)
  					if (tmpint != ctrl)
! 						(void) close(tmpint);
  			    }
! 			    if (sep->se_bi) {
  				(*sep->se_bi->bi_fn)(ctrl, sep);
! 				/* NOTREACHED */
! 			    } else {
  				if (debug)
  					fprintf(stderr, "%d execl %s\n",
  					    getpid(), sep->se_server);
***************
*** 497,522 ****
  						sep->se_user);
  					if (sep->se_socktype != SOCK_STREAM)
  						recv(0, buf, sizeof (buf), 0);
! 					_exit(1);
  				}
  				if (setsid() < 0) {
  					syslog(LOG_ERR,
  						"%s: can't setsid(): %m",
  						 sep->se_service);
! 					/* _exit(1); not fatal yet */
  				}
  				if (pwd->pw_uid) {
  					if (setlogin(sep->se_user) < 0) {
  						syslog(LOG_ERR,
  						 "%s: can't setlogin(%s): %m",
  						 sep->se_service, sep->se_user);
! 						/* _exit(1); not fatal yet */
  					}
  					if (setgid(pwd->pw_gid) < 0) {
  						syslog(LOG_ERR,
  						  "%s: can't set gid %d: %m",
  						  sep->se_service, pwd->pw_gid);
! 						_exit(1);
  					}
  					(void) initgroups(pwd->pw_name,
  							pwd->pw_gid);
--- 501,526 ----
  						sep->se_user);
  					if (sep->se_socktype != SOCK_STREAM)
  						recv(0, buf, sizeof (buf), 0);
! 					_exit(EX_NOUSER);
  				}
  				if (setsid() < 0) {
  					syslog(LOG_ERR,
  						"%s: can't setsid(): %m",
  						 sep->se_service);
! 					/* _exit(EX_OSERR); not fatal yet */
  				}
  				if (pwd->pw_uid) {
  					if (setlogin(sep->se_user) < 0) {
  						syslog(LOG_ERR,
  						 "%s: can't setlogin(%s): %m",
  						 sep->se_service, sep->se_user);
! 						/* _exit(EX_OSERR); not yet */
  					}
  					if (setgid(pwd->pw_gid) < 0) {
  						syslog(LOG_ERR,
  						  "%s: can't set gid %d: %m",
  						  sep->se_service, pwd->pw_gid);
! 						_exit(EX_OSERR);
  					}
  					(void) initgroups(pwd->pw_name,
  							pwd->pw_gid);
***************
*** 524,530 ****
  						syslog(LOG_ERR,
  						  "%s: can't set uid %d: %m",
  						  sep->se_service, pwd->pw_uid);
! 						_exit(1);
  					}
  				}
  				execv(sep->se_server, sep->se_argv);
--- 528,534 ----
  						syslog(LOG_ERR,
  						  "%s: can't set uid %d: %m",
  						  sep->se_service, pwd->pw_uid);
! 						_exit(EX_OSERR);
  					}
  				}
  				execv(sep->se_server, sep->se_argv);
***************
*** 532,551 ****
  					recv(0, buf, sizeof (buf), 0);
  				syslog(LOG_ERR,
  				    "cannot execute %s: %m", sep->se_server);
! 				_exit(1);
  			    }
  		    }
! 		    if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
  			    close(ctrl);
  		}
  	}
  }
  
  void
  reapchild(signo)
  	int signo;
  {
! 	int status;
  	pid_t pid;
  	struct servtab *sep;
  
--- 536,581 ----
  					recv(0, buf, sizeof (buf), 0);
  				syslog(LOG_ERR,
  				    "cannot execute %s: %m", sep->se_server);
! 				_exit(EX_OSERR);
  			    }
  		    }
! 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
  			    close(ctrl);
  		}
  	}
  }
  
+ /*
+  * Record a new child pid for this service. If we've reached the
+  * limit on children, then stop accepting incoming requests.
+  */
+ 
+ void
+ addchild(struct servtab *sep, pid_t pid)
+ {
+ #ifdef SANITY_CHECK
+ 	if (sep->se_numchild >= sep->se_maxchild) {
+ 		syslog(LOG_ERR, "%s: %d >= %d",
+ 		    __FUNCTION__, sep->se_numchild, sep->se_maxchild);
+ 		exit(EX_SOFTWARE);
+ 	}
+ #endif
+ 	if (sep->se_maxchild == 0)
+ 		return;
+ 	sep->se_pids[sep->se_numchild++] = pid;
+ 	if (sep->se_numchild == sep->se_maxchild)
+ 		disable(sep);
+ }
+ 
+ /*
+  * Some child process has exited. See if it's on somebody's list.
+  */
+ 
  void
  reapchild(signo)
  	int signo;
  {
! 	int k, status;
  	pid_t pid;
  	struct servtab *sep;
  
***************
*** 556,574 ****
  		if (debug)
  			fprintf(stderr, "%d reaped, status %#x\n",
  				pid, status);
! 		for (sep = servtab; sep; sep = sep->se_next)
! 			if (sep->se_wait == pid) {
! 				if (status)
! 					syslog(LOG_WARNING,
! 					    "%s: exit status 0x%x",
! 					    sep->se_server, status);
! 				if (debug)
! 					fprintf(stderr, "restored %s, fd %d\n",
! 					    sep->se_service, sep->se_fd);
! 				FD_SET(sep->se_fd, &allsock);
! 				nsock++;
! 				sep->se_wait = 1;
! 			}
  	}
  }
  
--- 586,606 ----
  		if (debug)
  			fprintf(stderr, "%d reaped, status %#x\n",
  				pid, status);
! 		for (sep = servtab; sep; sep = sep->se_next) {
! 			for (k = 0; k < sep->se_numchild; k++)
! 				if (sep->se_pids[k] == pid)
! 					break;
! 			if (k == sep->se_numchild)
! 				continue;
! 			if (sep->se_numchild == sep->se_maxchild)
! 				enable(sep);
! 			sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
! 			if (status)
! 				syslog(LOG_WARNING,
! 				    "%s[%d]: exit status 0x%x",
! 				    sep->se_server, pid, status);
! 			break;
! 		}
  	}
  }
  
***************
*** 576,582 ****
  config(signo)
  	int signo;
  {
! 	struct servtab *sep, *cp, **sepp;
  	struct passwd *pwd;
  	long omask;
  
--- 608,614 ----
  config(signo)
  	int signo;
  {
! 	struct servtab *sep, *new, **sepp;
  	struct passwd *pwd;
  	long omask;
  
***************
*** 586,628 ****
  	}
  	for (sep = servtab; sep; sep = sep->se_next)
  		sep->se_checked = 0;
! 	while (cp = getconfigent()) {
! 		if ((pwd = getpwnam(cp->se_user)) == NULL) {
  			syslog(LOG_ERR,
  				"%s/%s: No such user '%s', service ignored",
! 				cp->se_service, cp->se_proto, cp->se_user);
  			continue;
  		}
  		for (sep = servtab; sep; sep = sep->se_next)
! 			if (strcmp(sep->se_service, cp->se_service) == 0 &&
! 			    strcmp(sep->se_proto, cp->se_proto) == 0)
  				break;
  		if (sep != 0) {
  			int i;
  
  			omask = sigblock(SIGBLOCK);
! 			/*
! 			 * sep->se_wait may be holding the pid of a daemon
! 			 * that we're waiting for.  If so, don't overwrite
! 			 * it unless the config file explicitly says don't
! 			 * wait.
! 			 */
! 			if (cp->se_bi == 0 &&
! 			    (sep->se_wait == 1 || cp->se_wait == 0))
! 				sep->se_wait = cp->se_wait;
! #define SWAP(a, b) { char *c = a; a = b; b = c; }
! 			if (cp->se_user)
! 				SWAP(sep->se_user, cp->se_user);
! 			if (cp->se_server)
! 				SWAP(sep->se_server, cp->se_server);
  			for (i = 0; i < MAXARGV; i++)
! 				SWAP(sep->se_argv[i], cp->se_argv[i]);
  			sigsetmask(omask);
! 			freeconfig(cp);
  			if (debug)
  				print_service("REDO", sep);
  		} else {
! 			sep = enter(cp);
  			if (debug)
  				print_service("ADD ", sep);
  		}
--- 618,674 ----
  	}
  	for (sep = servtab; sep; sep = sep->se_next)
  		sep->se_checked = 0;
! 	while ((new = getconfigent())) {
! 		if ((pwd = getpwnam(new->se_user)) == NULL) {
  			syslog(LOG_ERR,
  				"%s/%s: No such user '%s', service ignored",
! 				new->se_service, new->se_proto, new->se_user);
  			continue;
  		}
  		for (sep = servtab; sep; sep = sep->se_next)
! 			if (strcmp(sep->se_service, new->se_service) == 0 &&
! 			    strcmp(sep->se_proto, new->se_proto) == 0)
  				break;
  		if (sep != 0) {
  			int i;
  
+ #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
  			omask = sigblock(SIGBLOCK);
! 			/* copy over outstanding child pids */
! 			if (sep->se_maxchild && new->se_maxchild) {
! 				new->se_numchild = sep->se_numchild;
! 				if (new->se_numchild > new->se_maxchild)
! 					new->se_numchild = new->se_maxchild;
! 				memcpy(new->se_pids, sep->se_pids,
! 				    new->se_numchild * sizeof(*new->se_pids));
! 			}
! 			SWAP(sep->se_pids, new->se_pids);
! 			sep->se_maxchild = new->se_maxchild;
! 			sep->se_numchild = new->se_numchild;
! 			/* might need to turn on or off service now */
! 			if (sep->se_fd >= 0) {
! 			      if (sep->se_maxchild
! 				  && sep->se_numchild == sep->se_maxchild) {
! 				      if (FD_ISSET(sep->se_fd, &allsock))
! 					  disable(sep);
! 			      } else {
! 				      if (!FD_ISSET(sep->se_fd, &allsock))
! 					  enable(sep);
! 			      }
! 			}
! 			sep->se_accept = new->se_accept;
! 			if (new->se_user)
! 				SWAP(sep->se_user, new->se_user);
! 			if (new->se_server)
! 				SWAP(sep->se_server, new->se_server);
  			for (i = 0; i < MAXARGV; i++)
! 				SWAP(sep->se_argv[i], new->se_argv[i]);
  			sigsetmask(omask);
! 			freeconfig(new);
  			if (debug)
  				print_service("REDO", sep);
  		} else {
! 			sep = enter(new);
  			if (debug)
  				print_service("ADD ", sep);
  		}
***************
*** 673,679 ****
  	 */
  	omask = sigblock(SIGBLOCK);
  	sepp = &servtab;
! 	while (sep = *sepp) {
  		if (sep->se_checked) {
  			sepp = &sep->se_next;
  			continue;
--- 719,725 ----
  	 */
  	omask = sigblock(SIGBLOCK);
  	sepp = &servtab;
! 	while ((sep = *sepp)) {
  		if (sep->se_checked) {
  			sepp = &sep->se_next;
  			continue;
***************
*** 727,733 ****
  
  	timingout = 0;
  	for (sep = servtab; sep; sep = sep->se_next)
! 		if (sep->se_fd == -1)
  			setup(sep);
  }
  
--- 773,779 ----
  
  	timingout = 0;
  	for (sep = servtab; sep; sep = sep->se_next)
! 		if (sep->se_fd == -1 && !ISMUX(sep))
  			setup(sep);
  }
  
***************
*** 796,805 ****
          }
  	if (sep->se_socktype == SOCK_STREAM)
  		listen(sep->se_fd, 64);
! 	FD_SET(sep->se_fd, &allsock);
! 	nsock++;
! 	if (sep->se_fd > maxsock)
! 		maxsock = sep->se_fd;
  	if (debug) {
  		fprintf(stderr, "registered %s on %d\n",
  			sep->se_server, sep->se_fd);
--- 842,848 ----
          }
  	if (sep->se_socktype == SOCK_STREAM)
  		listen(sep->se_fd, 64);
! 	enable(sep);
  	if (debug) {
  		fprintf(stderr, "registered %s on %d\n",
  			sep->se_server, sep->se_fd);
***************
*** 814,831 ****
  	struct servtab *sep;
  {
  	if (sep->se_fd >= 0) {
! 		nsock--;
! 		FD_CLR(sep->se_fd, &allsock);
  		(void) close(sep->se_fd);
  		sep->se_fd = -1;
  	}
  	sep->se_count = 0;
! 	/*
! 	 * Don't keep the pid of this running deamon: when reapchild()
! 	 * reaps this pid, it would erroneously increment nsock.
! 	 */
! 	if (sep->se_wait > 1)
! 		sep->se_wait = 1;
  }
  
  struct servtab *
--- 857,869 ----
  	struct servtab *sep;
  {
  	if (sep->se_fd >= 0) {
! 		if (FD_ISSET(sep->se_fd, &allsock))
! 			disable(sep);
  		(void) close(sep->se_fd);
  		sep->se_fd = -1;
  	}
  	sep->se_count = 0;
! 	sep->se_numchild = 0;	/* forget about any existing children */
  }
  
  struct servtab *
***************
*** 838,844 ****
  	sep = (struct servtab *)malloc(sizeof (*sep));
  	if (sep == (struct servtab *)0) {
  		syslog(LOG_ERR, "Out of memory.");
! 		exit(-1);
  	}
  	*sep = *cp;
  	sep->se_fd = -1;
--- 876,882 ----
  	sep = (struct servtab *)malloc(sizeof (*sep));
  	if (sep == (struct servtab *)0) {
  		syslog(LOG_ERR, "Out of memory.");
! 		exit(EX_OSERR);
  	}
  	*sep = *cp;
  	sep->se_fd = -1;
***************
*** 849,854 ****
--- 887,954 ----
  	return (sep);
  }
  
+ void
+ enable(struct servtab *sep)
+ {
+ 	if (debug)
+ 		fprintf(stderr,
+ 		    "enabling %s, fd %d", sep->se_service, sep->se_fd);
+ #ifdef SANITY_CHECK
+ 	if (sep->se_fd < 0) {
+ 		syslog(LOG_ERR,
+ 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
+ 		exit(EX_SOFTWARE);
+ 	}
+ 	if (ISMUX(sep)) {
+ 		syslog(LOG_ERR,
+ 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
+ 		exit(EX_SOFTWARE);
+ 	}
+ 	if (FD_ISSET(sep->se_fd, &allsock)) {
+ 		syslog(LOG_ERR,
+ 		    "%s: %s: not off", __FUNCTION__, sep->se_service);
+ 		exit(EX_SOFTWARE);
+ 	}
+ #endif
+ 	FD_SET(sep->se_fd, &allsock);
+ 	nsock++;
+ 	if (sep->se_fd > maxsock)
+ 		maxsock = sep->se_fd;
+ }
+ 
+ void
+ disable(struct servtab *sep)
+ {
+ 	if (debug)
+ 		fprintf(stderr,
+ 		    "disabling %s, fd %d", sep->se_service, sep->se_fd);
+ #ifdef SANITY_CHECK
+ 	if (sep->se_fd < 0) {
+ 		syslog(LOG_ERR,
+ 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
+ 		exit(EX_SOFTWARE);
+ 	}
+ 	if (ISMUX(sep)) {
+ 		syslog(LOG_ERR,
+ 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
+ 		exit(EX_SOFTWARE);
+ 	}
+ 	if (!FD_ISSET(sep->se_fd, &allsock)) {
+ 		syslog(LOG_ERR,
+ 		    "%s: %s: not on", __FUNCTION__, sep->se_service);
+ 		exit(EX_SOFTWARE);
+ 	}
+ 	if (nsock == 0) {
+ 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
+ 		exit(EX_SOFTWARE);
+ 	}
+ #endif
+ 	FD_CLR(sep->se_fd, &allsock);
+ 	nsock--;
+ 	if (sep->se_fd == maxsock)
+ 		maxsock--;
+ }
+ 
  FILE	*fconfig = NULL;
  struct	servtab serv;
  char	line[LINE_MAX];
***************
*** 879,885 ****
  {
  	struct servtab *sep = &serv;
  	int argc;
! 	char *cp, *arg;
  	char *versp;
  	static char TCPMUX_TOKEN[] = "tcpmux/";
  #define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
--- 979,985 ----
  {
  	struct servtab *sep = &serv;
  	int argc;
! 	char *cp, *arg, *s;
  	char *versp;
  	static char TCPMUX_TOKEN[] = "tcpmux/";
  #define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
***************
*** 959,972 ****
                  }
          }
  	arg = sskip(&cp);
! 	sep->se_wait = strcmp(arg, "wait") == 0;
  	if (ISMUX(sep)) {
  		/*
! 		 * Silently enforce "nowait" for TCPMUX services since
! 		 * they don't have an assigned port to listen on.
  		 */
! 		sep->se_wait = 0;
! 
  		if (strcmp(sep->se_proto, "tcp")) {
  			syslog(LOG_ERR,
  				"%s: bad protocol for tcpmux service %s",
--- 1059,1094 ----
                  }
          }
  	arg = sskip(&cp);
! 	if (!strncmp(arg, "wait", 4))
! 		sep->se_accept = 0;
! 	else if (!strncmp(arg, "nowait", 6))
! 		sep->se_accept = 1;
! 	else {
! 		syslog(LOG_ERR,
! 			"%s: bad wait/nowait for service %s",
! 			CONFIG, sep->se_service);
! 		goto more;
! 	}
! 	sep->se_maxchild = -1;
! 	if ((s = strchr(arg, '/')) != NULL) {
! 		char *eptr;
! 		u_long val;
! 
! 		val = strtoul(s + 1, &eptr, 10);
! 		if (eptr == s + 1 || *eptr || val > MAX_MAXCHLD) {
! 			syslog(LOG_ERR,
! 				"%s: bad max-child for service %s",
! 				CONFIG, sep->se_service);
! 			goto more;
! 		}
! 		sep->se_maxchild = val;
! 	}
  	if (ISMUX(sep)) {
  		/*
! 		 * Silently enforce "nowait" mode for TCPMUX services
! 		 * since they don't have an assigned port to listen on.
  		 */
! 		sep->se_accept = 1;
  		if (strcmp(sep->se_proto, "tcp")) {
  			syslog(LOG_ERR,
  				"%s: bad protocol for tcpmux service %s",
***************
*** 994,1007 ****
  				sep->se_service);
  			goto more;
  		}
  		sep->se_bi = bi;
- 		sep->se_wait = bi->bi_wait;
  	} else
  		sep->se_bi = NULL;
  	argc = 0;
  	for (arg = skip(&cp); cp; arg = skip(&cp))
! 		if (argc < MAXARGV)
  			sep->se_argv[argc++] = newstr(arg);
  	while (argc <= MAXARGV)
  		sep->se_argv[argc++] = NULL;
  	return (sep);
--- 1116,1147 ----
  				sep->se_service);
  			goto more;
  		}
+ 		sep->se_accept = 1;	/* force accept mode for built-ins */
  		sep->se_bi = bi;
  	} else
  		sep->se_bi = NULL;
+ 	if (sep->se_maxchild < 0)	/* apply default max-children */
+ 		if (sep->se_bi)
+ 			sep->se_maxchild = sep->se_bi->bi_maxchild;
+ 		else
+ 			sep->se_maxchild = sep->se_accept ? 0 : 1;
+ 	if (sep->se_maxchild) {
+ 		sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
+ 		if (sep->se_pids == NULL) {
+ 			syslog(LOG_ERR, "Out of memory.");
+ 			exit(EX_OSERR);
+ 		}
+ 	}
  	argc = 0;
  	for (arg = skip(&cp); cp; arg = skip(&cp))
! 		if (argc < MAXARGV) {
  			sep->se_argv[argc++] = newstr(arg);
+ 		} else {
+ 			syslog(LOG_ERR,
+ 				"%s: too many arguments for service %s",
+ 				CONFIG, sep->se_service);
+ 			goto more;
+ 		}
  	while (argc <= MAXARGV)
  		sep->se_argv[argc++] = NULL;
  	return (sep);
***************
*** 1021,1026 ****
--- 1161,1168 ----
  		free(cp->se_user);
  	if (cp->se_server)
  		free(cp->se_server);
+ 	if (cp->se_pids)
+ 		free(cp->se_pids);
  	for (i = 0; i < MAXARGV; i++)
  		if (cp->se_argv[i])
  			free(cp->se_argv[i]);
***************
*** 1040,1046 ****
  	cp = skip(cpp);
  	if (cp == NULL) {
  		syslog(LOG_ERR, "%s: syntax error", CONFIG);
! 		exit(-1);
  	}
  	return (cp);
  }
--- 1182,1188 ----
  	cp = skip(cpp);
  	if (cp == NULL) {
  		syslog(LOG_ERR, "%s: syntax error", CONFIG);
! 		exit(EX_DATAERR);
  	}
  	return (cp);
  }
***************
*** 1062,1068 ****
  		c = getc(fconfig);
  		(void) ungetc(c, fconfig);
  		if (c == ' ' || c == '\t')
! 			if (cp = nextline(fconfig))
  				goto again;
  		*cpp = (char *)0;
  		return ((char *)0);
--- 1204,1210 ----
  		c = getc(fconfig);
  		(void) ungetc(c, fconfig);
  		if (c == ' ' || c == '\t')
! 			if ((cp = nextline(fconfig)))
  				goto again;
  		*cpp = (char *)0;
  		return ((char *)0);
***************
*** 1100,1109 ****
  newstr(cp)
  	char *cp;
  {
! 	if (cp = strdup(cp ? cp : ""))
  		return (cp);
  	syslog(LOG_ERR, "strdup: %m");
! 	exit(-1);
  }
  
  #ifdef OLD_SETPROCTITLE
--- 1242,1251 ----
  newstr(cp)
  	char *cp;
  {
! 	if ((cp = strdup(cp ? cp : "")))
  		return (cp);
  	syslog(LOG_ERR, "strdup: %m");
! 	exit(EX_OSERR);
  }
  
  #ifdef OLD_SETPROCTITLE
***************
*** 1439,1456 ****
  	char *action;
  	struct servtab *sep;
  {
! 	if(sep->se_rpc)
! 		fprintf(stderr,
! 	    		"%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
! 	    		action, sep->se_service, sep->se_proto,
! 	    		sep->se_wait, sep->se_user, (int)sep->se_bi,
! 			sep->se_server);
! 	else
! 		fprintf(stderr,
! 			"%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
! 			action, sep->se_service, sep->se_proto,
! 			sep->se_wait, sep->se_user, (int)sep->se_bi,
! 			sep->se_server);
  }
  
  /*
--- 1581,1591 ----
  	char *action;
  	struct servtab *sep;
  {
! 	fprintf(stderr,
! 	    "%s: %s proto=%s accept=%d max=%d user=%s builtin=%x server=%s\n",
! 	    action, sep->se_service, sep->se_proto,
! 	    sep->se_accept, sep->se_maxchild, sep->se_user,
! 	    (int)sep->se_bi, sep->se_server);
  }
  
  /*

--------------2F1CF0FB237C228A31DFF4F5--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3280EF24.ABD322C>