xref: /freebsd/usr.sbin/inetd/inetd.c (revision 2ad872c5794e4c26fdf6ed219ad3f09ca0d5304a)
1 /*
2  * Copyright (c) 1983, 1991, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
37 	The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)from: inetd.c	8.4 (Berkeley) 4/13/94";
43 #endif
44 static const char rcsid[] =
45 	"$Id: inetd.c,v 1.45 1999/01/02 16:04:19 des Exp $";
46 #endif /* not lint */
47 
48 /*
49  * Inetd - Internet super-server
50  *
51  * This program invokes all internet services as needed.  Connection-oriented
52  * services are invoked each time a connection is made, by creating a process.
53  * This process is passed the connection as file descriptor 0 and is expected
54  * to do a getpeername to find out the source host and port.
55  *
56  * Datagram oriented services are invoked when a datagram
57  * arrives; a process is created and passed a pending message
58  * on file descriptor 0.  Datagram servers may either connect
59  * to their peer, freeing up the original socket for inetd
60  * to receive further messages on, or ``take over the socket'',
61  * processing all arriving datagrams and, eventually, timing
62  * out.	 The first type of server is said to be ``multi-threaded'';
63  * the second type of server ``single-threaded''.
64  *
65  * Inetd uses a configuration file which is read at startup
66  * and, possibly, at some later time in response to a hangup signal.
67  * The configuration file is ``free format'' with fields given in the
68  * order shown below.  Continuation lines for an entry must being with
69  * a space or tab.  All fields must be present in each entry.
70  *
71  *	service name			must be in /etc/services or must
72  *					name a tcpmux service
73  *	socket type			stream/dgram/raw/rdm/seqpacket
74  *	protocol			must be in /etc/protocols
75  *	wait/nowait			single-threaded/multi-threaded
76  *	user				user to run daemon as
77  *	server program			full path name
78  *	server program arguments	maximum of MAXARGS (20)
79  *
80  * TCP services without official port numbers are handled with the
81  * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
82  * requests. When a connection is made from a foreign host, the service
83  * requested is passed to tcpmux, which looks it up in the servtab list
84  * and returns the proper entry for the service. Tcpmux returns a
85  * negative reply if the service doesn't exist, otherwise the invoked
86  * server is expected to return the positive reply if the service type in
87  * inetd.conf file has the prefix "tcpmux/". If the service type has the
88  * prefix "tcpmux/+", tcpmux will return the positive reply for the
89  * process; this is for compatibility with older server code, and also
90  * allows you to invoke programs that use stdin/stdout without putting any
91  * special server code in them. Services that use tcpmux are "nowait"
92  * because they do not have a well-known port and hence cannot listen
93  * for new requests.
94  *
95  * For RPC services
96  *	service name/version		must be in /etc/rpc
97  *	socket type			stream/dgram/raw/rdm/seqpacket
98  *	protocol			must be in /etc/protocols
99  *	wait/nowait			single-threaded/multi-threaded
100  *	user				user to run daemon as
101  *	server program			full path name
102  *	server program arguments	maximum of MAXARGS
103  *
104  * Comment lines are indicated by a `#' in column 1.
105  */
106 #include <sys/param.h>
107 #include <sys/stat.h>
108 #include <sys/ioctl.h>
109 #include <sys/socket.h>
110 #include <sys/wait.h>
111 #include <sys/time.h>
112 #include <sys/resource.h>
113 
114 #include <netinet/in.h>
115 #include <netinet/tcp.h>
116 #include <arpa/inet.h>
117 #include <rpc/rpc.h>
118 #include <rpc/pmap_clnt.h>
119 
120 #include <errno.h>
121 #include <err.h>
122 #include <fcntl.h>
123 #include <grp.h>
124 #include <netdb.h>
125 #include <pwd.h>
126 #include <signal.h>
127 #include <stdio.h>
128 #include <stdlib.h>
129 #include <string.h>
130 #include <syslog.h>
131 #include <unistd.h>
132 #include <libutil.h>
133 #include <sysexits.h>
134 
135 #ifdef LOGIN_CAP
136 #include <login_cap.h>
137 
138 /* see init.c */
139 #define RESOURCE_RC "daemon"
140 
141 #endif
142 
143 #include "pathnames.h"
144 
145 #ifndef	MAXCHILD
146 #define	MAXCHILD	-1		/* maximum number of this service
147 					   < 0 = no limit */
148 #endif
149 
150 #ifndef	MAXCPM
151 #define	MAXCPM		-1		/* rate limit invocations from a
152 					   single remote address,
153 					   < 0 = no limit */
154 #endif
155 
156 #define	TOOMANY		256		/* don't start more than TOOMANY */
157 #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
158 #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
159 #define MAX_MAXCHLD	32767		/* max allowable max children */
160 
161 #define	SIGBLOCK	(sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
162 
163 int	debug = 0;
164 int	log = 0;
165 int	nsock, maxsock;
166 fd_set	allsock;
167 int	options;
168 int	timingout;
169 int	toomany = TOOMANY;
170 int	maxchild = MAXCPM;
171 int	maxcpm = MAXCHILD;
172 struct	servent *sp;
173 struct	rpcent *rpc;
174 struct	in_addr bind_address;
175 int	signalpipe[2];
176 
177 struct	servtab {
178 	char	*se_service;		/* name of service */
179 	int	se_socktype;		/* type of socket to use */
180 	char	*se_proto;		/* protocol used */
181 	int	se_maxchild;		/* max number of children */
182 	int	se_maxcpm;		/* max connects per IP per minute */
183 	int	se_numchild;		/* current number of children */
184 	pid_t	*se_pids;		/* array of child pids */
185 	char	*se_user;		/* user name to run as */
186 	char    *se_group;              /* group name to run as */
187 #ifdef  LOGIN_CAP
188 	char    *se_class;              /* login class name to run with */
189 #endif
190 	struct	biltin *se_bi;		/* if built-in, description */
191 	char	*se_server;		/* server program */
192 #define	MAXARGV 20
193 	char	*se_argv[MAXARGV+1];	/* program arguments */
194 	int	se_fd;			/* open descriptor */
195 	struct	sockaddr_in se_ctrladdr;/* bound address */
196 	u_char	se_type;		/* type: normal, mux, or mux+ */
197 	u_char	se_checked;		/* looked at during merge */
198 	u_char	se_accept;		/* i.e., wait/nowait mode */
199 	u_char	se_rpc;			/* ==1 if RPC service */
200 	int	se_rpc_prog;		/* RPC program number */
201 	u_int	se_rpc_lowvers;		/* RPC low version */
202 	u_int	se_rpc_highvers;	/* RPC high version */
203 	int	se_count;		/* number started since se_time */
204 	struct	timeval se_time;	/* start of se_count */
205 	struct	servtab *se_next;
206 } *servtab;
207 
208 #define NORM_TYPE	0
209 #define MUX_TYPE	1
210 #define MUXPLUS_TYPE	2
211 #define TTCP_TYPE	3
212 #define ISMUX(sep)	(((sep)->se_type == MUX_TYPE) || \
213 			 ((sep)->se_type == MUXPLUS_TYPE))
214 #define ISMUXPLUS(sep)	((sep)->se_type == MUXPLUS_TYPE)
215 #define ISTTCP(sep)	((sep)->se_type == TTCP_TYPE)
216 
217 
218 void		chargen_dg __P((int, struct servtab *));
219 void		chargen_stream __P((int, struct servtab *));
220 void		close_sep __P((struct servtab *));
221 void		flag_signal __P((char));
222 void		flag_config __P((int));
223 void		config __P((void));
224 void		daytime_dg __P((int, struct servtab *));
225 void		daytime_stream __P((int, struct servtab *));
226 void		discard_dg __P((int, struct servtab *));
227 void		discard_stream __P((int, struct servtab *));
228 void		echo_dg __P((int, struct servtab *));
229 void		echo_stream __P((int, struct servtab *));
230 void		endconfig __P((void));
231 struct servtab *enter __P((struct servtab *));
232 void		freeconfig __P((struct servtab *));
233 struct servtab *getconfigent __P((void));
234 void		ident_stream __P((int, struct servtab *));
235 void		machtime_dg __P((int, struct servtab *));
236 void		machtime_stream __P((int, struct servtab *));
237 char	       *newstr __P((char *));
238 char	       *nextline __P((FILE *));
239 void		print_service __P((char *, struct servtab *));
240 void		addchild __P((struct servtab *, int));
241 void		flag_reapchild __P((int));
242 void		reapchild __P((void));
243 void		enable __P((struct servtab *));
244 void		disable __P((struct servtab *));
245 void		flag_retry __P((int));
246 void		retry __P((void));
247 int		setconfig __P((void));
248 void		setup __P((struct servtab *));
249 char	       *sskip __P((char **));
250 char	       *skip __P((char **));
251 struct servtab *tcpmux __P((int));
252 int		cpmip __P((struct servtab *, int));
253 
254 void		unregisterrpc __P((register struct servtab *sep));
255 
256 struct biltin {
257 	char	*bi_service;		/* internally provided service name */
258 	int	bi_socktype;		/* type of socket supported */
259 	short	bi_fork;		/* 1 if should fork before call */
260 	int	bi_maxchild;		/* max number of children (default) */
261 	void	(*bi_fn)();		/* function which performs it */
262 } biltins[] = {
263 	/* Echo received data */
264 	{ "echo",	SOCK_STREAM,	1, 0,	echo_stream },
265 	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg },
266 
267 	/* Internet /dev/null */
268 	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream },
269 	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg },
270 
271 	/* Return 32 bit time since 1900 */
272 	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream },
273 	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg },
274 
275 	/* Return human-readable time */
276 	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream },
277 	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg },
278 
279 	/* Familiar character generator */
280 	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream },
281 	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg },
282 
283 	{ "tcpmux",	SOCK_STREAM,	1, 0,	(void (*)())tcpmux },
284 
285 	{ "ident",	SOCK_STREAM,	1, 0,	ident_stream },
286 
287 	{ NULL }
288 };
289 
290 #define NUMINT	(sizeof(intab) / sizeof(struct inent))
291 char	*CONFIG = _PATH_INETDCONF;
292 char	*pid_file = _PATH_INETDPID;
293 
294 #ifdef OLD_SETPROCTITLE
295 char	**Argv;
296 char 	*LastArg;
297 #endif
298 
299 int
300 getvalue(arg, value, whine)
301 	char *arg, *whine;
302 	int  *value;
303 {
304 	int  tmp;
305 	char *p;
306 
307 	tmp = strtol(arg, &p, 0);
308 	if (tmp < 1 || *p) {
309 		syslog(LOG_ERR, whine, arg);
310 		return 1;			/* failure */
311 	}
312 	*value = tmp;
313 	return 0;				/* success */
314 }
315 
316 int
317 main(argc, argv, envp)
318 	int argc;
319 	char *argv[], *envp[];
320 {
321 	struct servtab *sep;
322 	struct passwd *pwd;
323 	struct group *grp;
324 	struct sigaction sa, sapipe;
325 	int tmpint, ch, dofork;
326 	pid_t pid;
327 	char buf[50];
328 	struct  sockaddr_in peer;
329 	int i;
330 #ifdef LOGIN_CAP
331 	login_cap_t *lc = NULL;
332 #endif
333 
334 
335 #ifdef OLD_SETPROCTITLE
336 	Argv = argv;
337 	if (envp == 0 || *envp == 0)
338 		envp = argv;
339 	while (*envp)
340 		envp++;
341 	LastArg = envp[-1] + strlen(envp[-1]);
342 #endif
343 
344 	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
345 
346 	bind_address.s_addr = htonl(INADDR_ANY);
347 	while ((ch = getopt(argc, argv, "dlR:a:c:C:p:")) != -1)
348 		switch(ch) {
349 		case 'd':
350 			debug = 1;
351 			options |= SO_DEBUG;
352 			break;
353 		case 'l':
354 			log = 1;
355 			break;
356 		case 'R':
357 			getvalue(optarg, &toomany,
358 				"-R %s: bad value for service invocation rate");
359 			break;
360 		case 'c':
361 			getvalue(optarg, &maxchild,
362 				"-c %s: bad value for maximum children");
363 			break;
364 		case 'C':
365 			getvalue(optarg, &maxcpm,
366 				"-C %s: bad value for maximum children/minute");
367 			break;
368 		case 'a':
369 			if (!inet_aton(optarg, &bind_address)) {
370 				syslog(LOG_ERR,
371 			         "-a %s: invalid IP address", optarg);
372 				exit(EX_USAGE);
373 			}
374 			break;
375 		case 'p':
376 			pid_file = optarg;
377 			break;
378 		case '?':
379 		default:
380 			syslog(LOG_ERR,
381 				"usage: inetd [-dl] [-a address] [-R rate]"
382 				" [-c maximum] [-C rate]"
383 				" [-p pidfile] [conf-file]");
384 			exit(EX_USAGE);
385 		}
386 	argc -= optind;
387 	argv += optind;
388 
389 	if (argc > 0)
390 		CONFIG = argv[0];
391 	if (debug == 0) {
392 		FILE *fp;
393 		if (daemon(0, 0) < 0) {
394 			syslog(LOG_WARNING, "daemon(0,0) failed: %m");
395 		}
396 		/*
397 		 * In case somebody has started inetd manually, we need to
398 		 * clear the logname, so that old servers run as root do not
399 		 * get the user's logname..
400 		 */
401 		if (setlogin("") < 0) {
402 			syslog(LOG_WARNING, "cannot clear logname: %m");
403 			/* no big deal if it fails.. */
404 		}
405 		pid = getpid();
406 		fp = fopen(pid_file, "w");
407 		if (fp) {
408 			fprintf(fp, "%ld\n", (long)pid);
409 			fclose(fp);
410 		} else {
411 			syslog(LOG_WARNING, "%s: %m", pid_file);
412 		}
413 	}
414 	sa.sa_flags = 0;
415 	sigemptyset(&sa.sa_mask);
416 	sigaddset(&sa.sa_mask, SIGALRM);
417 	sigaddset(&sa.sa_mask, SIGCHLD);
418 	sigaddset(&sa.sa_mask, SIGHUP);
419 	sa.sa_handler = flag_retry;
420 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
421 	config();
422 	sa.sa_handler = flag_config;
423 	sigaction(SIGHUP, &sa, (struct sigaction *)0);
424 	sa.sa_handler = flag_reapchild;
425 	sigaction(SIGCHLD, &sa, (struct sigaction *)0);
426 	sa.sa_handler = SIG_IGN;
427 	sigaction(SIGPIPE, &sa, &sapipe);
428 
429 	{
430 		/* space for daemons to overwrite environment for ps */
431 #define	DUMMYSIZE	100
432 		char dummy[DUMMYSIZE];
433 
434 		(void)memset(dummy, 'x', DUMMYSIZE - 1);
435 		dummy[DUMMYSIZE - 1] = '\0';
436 		(void)setenv("inetd_dummy", dummy, 1);
437 	}
438 
439 	if (pipe(signalpipe) != 0) {
440 		syslog(LOG_ERR, "pipe: %%m");
441 		exit(EX_OSERR);
442 	}
443 	FD_SET(signalpipe[0], &allsock);
444 	if (signalpipe[0]>maxsock) maxsock = signalpipe[0];
445 
446 	for (;;) {
447 	    int n, ctrl;
448 	    fd_set readable;
449 
450 	    if (nsock == 0) {
451 		(void) sigblock(SIGBLOCK);
452 		while (nsock == 0)
453 		    sigpause(0L);
454 		(void) sigsetmask(0L);
455 	    }
456 	    readable = allsock;
457 	    if ((n = select(maxsock + 1, &readable, (fd_set *)0,
458 		(fd_set *)0, (struct timeval *)0)) <= 0) {
459 		    if (n < 0 && errno != EINTR) {
460 			syslog(LOG_WARNING, "select: %m");
461 			sleep(1);
462 		    }
463 		    continue;
464 	    }
465 	    /* handle any queued signal flags */
466 	    if (FD_ISSET(signalpipe[0], &readable)) {
467 		int n;
468 		if (ioctl(signalpipe[0], FIONREAD, &n) != 0) {
469 		    syslog(LOG_ERR, "ioctl: %m");
470 		    exit(EX_OSERR);
471 		}
472 		while (--n >= 0) {
473 		    char c;
474 		    if (read(signalpipe[0], &c, 1) != 1) {
475 			syslog(LOG_ERR, "read: %m");
476 			exit(EX_OSERR);
477 		    }
478 		    if (debug)
479 			warnx("Handling signal flag %c", c);
480 		    switch(c) {
481 		    case 'A': /* sigalrm */
482 			retry();
483 			break;
484 		    case 'C': /* sigchld */
485 			reapchild();
486 			break;
487 		    case 'H': /* sighup */
488 			config();
489 			break;
490 		    }
491 		}
492 	    }
493 	    for (sep = servtab; n && sep; sep = sep->se_next)
494 	        if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
495 		    n--;
496 		    if (debug)
497 			    warnx("someone wants %s", sep->se_service);
498 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
499 			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
500 				(int *)0);
501 			    if (debug)
502 				    warnx("accept, ctrl %d", ctrl);
503 			    if (ctrl < 0) {
504 				    if (errno != EINTR)
505 					    syslog(LOG_WARNING,
506 						"accept (for %s): %m",
507 						sep->se_service);
508                                       if (sep->se_accept &&
509                                           sep->se_socktype == SOCK_STREAM)
510                                               close(ctrl);
511 				    continue;
512 			    }
513 			    if (cpmip(sep, ctrl) < 0) {
514 				close(ctrl);
515 				continue;
516 			    }
517 			    if (log) {
518 				i = sizeof peer;
519 				if (getpeername(ctrl, (struct sockaddr *)
520 						&peer, &i)) {
521 					syslog(LOG_WARNING,
522 						"getpeername(for %s): %m",
523 						sep->se_service);
524 					close(ctrl);
525 					continue;
526 				}
527 				syslog(LOG_INFO,"%s from %s",
528 					sep->se_service,
529 					inet_ntoa(peer.sin_addr));
530 			    }
531 		    } else
532 			    ctrl = sep->se_fd;
533 		    (void) sigblock(SIGBLOCK);
534 		    pid = 0;
535 		    dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
536 		    if (dofork) {
537 			    if (sep->se_count++ == 0)
538 				(void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
539 			    else if (sep->se_count >= toomany) {
540 				struct timeval now;
541 
542 				(void)gettimeofday(&now, (struct timezone *)NULL);
543 				if (now.tv_sec - sep->se_time.tv_sec >
544 				    CNT_INTVL) {
545 					sep->se_time = now;
546 					sep->se_count = 1;
547 				} else {
548 					syslog(LOG_ERR,
549 			"%s/%s server failing (looping), service terminated",
550 					    sep->se_service, sep->se_proto);
551 					close_sep(sep);
552 					sigsetmask(0L);
553 					if (!timingout) {
554 						timingout = 1;
555 						alarm(RETRYTIME);
556 					}
557 					continue;
558 				}
559 			    }
560 			    pid = fork();
561 		    }
562 		    if (pid < 0) {
563 			    syslog(LOG_ERR, "fork: %m");
564 			    if (sep->se_accept &&
565 				sep->se_socktype == SOCK_STREAM)
566 				    close(ctrl);
567 			    sigsetmask(0L);
568 			    sleep(1);
569 			    continue;
570 		    }
571 		    if (pid)
572 			addchild(sep, pid);
573 		    sigsetmask(0L);
574 		    if (pid == 0) {
575 			    if (dofork) {
576 				if (debug)
577 					warnx("+ closing from %d", maxsock);
578 				for (tmpint = maxsock; tmpint > 2; tmpint--)
579 					if (tmpint != ctrl)
580 						(void) close(tmpint);
581 			    }
582 			    /*
583 			     * Call tcpmux to find the real service to exec.
584 			     */
585 			    if (sep->se_bi &&
586 				sep->se_bi->bi_fn == (void (*)()) tcpmux) {
587 				    sep = tcpmux(ctrl);
588 				    if (sep == NULL) {
589 					    close(ctrl);
590 					    _exit(0);
591 				    }
592 			    }
593 			    if (sep->se_bi) {
594 				(*sep->se_bi->bi_fn)(ctrl, sep);
595 				/* NOTREACHED */
596 			    } else {
597 				if (debug)
598 					warnx("%d execl %s",
599 						getpid(), sep->se_server);
600 				dup2(ctrl, 0);
601 				close(ctrl);
602 				dup2(0, 1);
603 				dup2(0, 2);
604 				if ((pwd = getpwnam(sep->se_user)) == NULL) {
605 					syslog(LOG_ERR,
606 					    "%s/%s: %s: No such user",
607 						sep->se_service, sep->se_proto,
608 						sep->se_user);
609 					if (sep->se_socktype != SOCK_STREAM)
610 						recv(0, buf, sizeof (buf), 0);
611 					_exit(EX_NOUSER);
612 				}
613 				grp = NULL;
614 				if (   sep->se_group != NULL
615 				    && (grp = getgrnam(sep->se_group)) == NULL
616 				   ) {
617 					syslog(LOG_ERR,
618 					    "%s/%s: %s: No such group",
619 						sep->se_service, sep->se_proto,
620 						sep->se_group);
621 					if (sep->se_socktype != SOCK_STREAM)
622 						recv(0, buf, sizeof (buf), 0);
623 					_exit(EX_NOUSER);
624 				}
625 				if (grp != NULL)
626 					pwd->pw_gid = grp->gr_gid;
627 #ifdef LOGIN_CAP
628 				if ((lc = login_getclass(sep->se_class)) == NULL) {
629 					/* error syslogged by getclass */
630 					syslog(LOG_ERR,
631 					    "%s/%s: %s: login class error",
632 						sep->se_service, sep->se_proto,
633 						sep->se_class);
634 					if (sep->se_socktype != SOCK_STREAM)
635 						recv(0, buf, sizeof (buf), 0);
636 					_exit(EX_NOUSER);
637 				}
638 #endif
639 				if (setsid() < 0) {
640 					syslog(LOG_ERR,
641 						"%s: can't setsid(): %m",
642 						 sep->se_service);
643 					/* _exit(EX_OSERR); not fatal yet */
644 				}
645 #ifdef LOGIN_CAP
646 				if (setusercontext(lc, pwd, pwd->pw_uid,
647 				    LOGIN_SETALL) != 0) {
648 					syslog(LOG_ERR,
649 					 "%s: can't setusercontext(..%s..): %m",
650 					 sep->se_service, sep->se_user);
651 					_exit(EX_OSERR);
652 				}
653 #else
654 				if (pwd->pw_uid) {
655 					if (setlogin(sep->se_user) < 0) {
656 						syslog(LOG_ERR,
657 						 "%s: can't setlogin(%s): %m",
658 						 sep->se_service, sep->se_user);
659 						/* _exit(EX_OSERR); not yet */
660 					}
661 					if (setgid(pwd->pw_gid) < 0) {
662 						syslog(LOG_ERR,
663 						  "%s: can't set gid %d: %m",
664 						  sep->se_service, pwd->pw_gid);
665 						_exit(EX_OSERR);
666 					}
667 					(void) initgroups(pwd->pw_name,
668 							pwd->pw_gid);
669 					if (setuid(pwd->pw_uid) < 0) {
670 						syslog(LOG_ERR,
671 						  "%s: can't set uid %d: %m",
672 						  sep->se_service, pwd->pw_uid);
673 						_exit(EX_OSERR);
674 					}
675 				}
676 #endif
677 				sigaction(SIGPIPE, &sapipe,
678 				    (struct sigaction *)0);
679 				execv(sep->se_server, sep->se_argv);
680 				if (sep->se_socktype != SOCK_STREAM)
681 					recv(0, buf, sizeof (buf), 0);
682 				syslog(LOG_ERR,
683 				    "cannot execute %s: %m", sep->se_server);
684 				_exit(EX_OSERR);
685 			    }
686 		    }
687 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
688 			    close(ctrl);
689 		}
690 	}
691 }
692 
693 /*
694  * Add a signal flag to the signal flag queue for later handling
695  */
696 
697 void flag_signal(c)
698     char c;
699 {
700 	if (write(signalpipe[1], &c, 1) != 1) {
701 		syslog(LOG_ERR, "write: %m");
702 		exit(EX_OSERR);
703 	}
704 }
705 
706 /*
707  * Record a new child pid for this service. If we've reached the
708  * limit on children, then stop accepting incoming requests.
709  */
710 
711 void
712 addchild(struct servtab *sep, pid_t pid)
713 {
714 #ifdef SANITY_CHECK
715 	if (sep->se_numchild >= sep->se_maxchild) {
716 		syslog(LOG_ERR, "%s: %d >= %d",
717 		    __FUNCTION__, sep->se_numchild, sep->se_maxchild);
718 		exit(EX_SOFTWARE);
719 	}
720 #endif
721 	if (sep->se_maxchild == 0)
722 		return;
723 	sep->se_pids[sep->se_numchild++] = pid;
724 	if (sep->se_numchild == sep->se_maxchild)
725 		disable(sep);
726 }
727 
728 /*
729  * Some child process has exited. See if it's on somebody's list.
730  */
731 
732 void
733 flag_reapchild(signo)
734 	int signo;
735 {
736 	flag_signal('C');
737 }
738 
739 void
740 reapchild()
741 {
742 	int k, status;
743 	pid_t pid;
744 	struct servtab *sep;
745 
746 	for (;;) {
747 		pid = wait3(&status, WNOHANG, (struct rusage *)0);
748 		if (pid <= 0)
749 			break;
750 		if (debug)
751 			warnx("%d reaped, status %#x", pid, status);
752 		for (sep = servtab; sep; sep = sep->se_next) {
753 			for (k = 0; k < sep->se_numchild; k++)
754 				if (sep->se_pids[k] == pid)
755 					break;
756 			if (k == sep->se_numchild)
757 				continue;
758 			if (sep->se_numchild == sep->se_maxchild)
759 				enable(sep);
760 			sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
761 			if (status)
762 				syslog(LOG_WARNING,
763 				    "%s[%d]: exit status 0x%x",
764 				    sep->se_server, pid, status);
765 			break;
766 		}
767 	}
768 }
769 
770 void
771 flag_config(signo)
772 	int signo;
773 {
774 	flag_signal('H');
775 }
776 
777 void config()
778 {
779 	struct servtab *sep, *new, **sepp;
780 	long omask;
781 
782 	if (!setconfig()) {
783 		syslog(LOG_ERR, "%s: %m", CONFIG);
784 		return;
785 	}
786 	for (sep = servtab; sep; sep = sep->se_next)
787 		sep->se_checked = 0;
788 	while ((new = getconfigent())) {
789 		if (getpwnam(new->se_user) == NULL) {
790 			syslog(LOG_ERR,
791 				"%s/%s: No such user '%s', service ignored",
792 				new->se_service, new->se_proto, new->se_user);
793 			continue;
794 		}
795 		if (new->se_group && getgrnam(new->se_group) == NULL) {
796 			syslog(LOG_ERR,
797 				"%s/%s: No such group '%s', service ignored",
798 				new->se_service, new->se_proto, new->se_group);
799 			continue;
800 		}
801 #ifdef LOGIN_CAP
802 		if (login_getclass(new->se_class) == NULL) {
803 			/* error syslogged by getclass */
804 			syslog(LOG_ERR,
805 				"%s/%s: %s: login class error, service ignored",
806 				new->se_service, new->se_proto, new->se_class);
807 			continue;
808 		}
809 #endif
810 		for (sep = servtab; sep; sep = sep->se_next)
811 			if (strcmp(sep->se_service, new->se_service) == 0 &&
812 			    strcmp(sep->se_proto, new->se_proto) == 0)
813 				break;
814 		if (sep != 0) {
815 			int i;
816 
817 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
818 			omask = sigblock(SIGBLOCK);
819 			/* copy over outstanding child pids */
820 			if (sep->se_maxchild && new->se_maxchild) {
821 				new->se_numchild = sep->se_numchild;
822 				if (new->se_numchild > new->se_maxchild)
823 					new->se_numchild = new->se_maxchild;
824 				memcpy(new->se_pids, sep->se_pids,
825 				    new->se_numchild * sizeof(*new->se_pids));
826 			}
827 			SWAP(sep->se_pids, new->se_pids);
828 			sep->se_maxchild = new->se_maxchild;
829 			sep->se_numchild = new->se_numchild;
830 			sep->se_maxcpm = new->se_maxcpm;
831 			/* might need to turn on or off service now */
832 			if (sep->se_fd >= 0) {
833 			      if (sep->se_maxchild
834 				  && sep->se_numchild == sep->se_maxchild) {
835 				      if (FD_ISSET(sep->se_fd, &allsock))
836 					  disable(sep);
837 			      } else {
838 				      if (!FD_ISSET(sep->se_fd, &allsock))
839 					  enable(sep);
840 			      }
841 			}
842 			sep->se_accept = new->se_accept;
843 			SWAP(sep->se_user, new->se_user);
844 			SWAP(sep->se_group, new->se_group);
845 #ifdef LOGIN_CAP
846 			SWAP(sep->se_class, new->se_class);
847 #endif
848 			SWAP(sep->se_server, new->se_server);
849 			for (i = 0; i < MAXARGV; i++)
850 				SWAP(sep->se_argv[i], new->se_argv[i]);
851 			sigsetmask(omask);
852 			freeconfig(new);
853 			if (debug)
854 				print_service("REDO", sep);
855 		} else {
856 			sep = enter(new);
857 			if (debug)
858 				print_service("ADD ", sep);
859 		}
860 		sep->se_checked = 1;
861 		if (ISMUX(sep)) {
862 			sep->se_fd = -1;
863 			continue;
864 		}
865 		if (!sep->se_rpc) {
866 			sp = getservbyname(sep->se_service, sep->se_proto);
867 			if (sp == 0) {
868 				syslog(LOG_ERR, "%s/%s: unknown service",
869 			    	sep->se_service, sep->se_proto);
870 				sep->se_checked = 0;
871 				continue;
872 			}
873 			if (sp->s_port != sep->se_ctrladdr.sin_port) {
874 				sep->se_ctrladdr.sin_family = AF_INET;
875 				sep->se_ctrladdr.sin_addr = bind_address;
876 				sep->se_ctrladdr.sin_port = sp->s_port;
877 				if (sep->se_fd >= 0)
878 					close_sep(sep);
879 			}
880 		} else {
881 			rpc = getrpcbyname(sep->se_service);
882 			if (rpc == 0) {
883 				syslog(LOG_ERR, "%s/%s unknown RPC service.",
884 					sep->se_service, sep->se_proto);
885 				if (sep->se_fd != -1)
886 					(void) close(sep->se_fd);
887 				sep->se_fd = -1;
888 					continue;
889 			}
890 			if (rpc->r_number != sep->se_rpc_prog) {
891 				if (sep->se_rpc_prog)
892 					unregisterrpc(sep);
893 				sep->se_rpc_prog = rpc->r_number;
894 				if (sep->se_fd != -1)
895 					(void) close(sep->se_fd);
896 				sep->se_fd = -1;
897 			}
898 		}
899 		if (sep->se_fd == -1)
900 			setup(sep);
901 	}
902 	endconfig();
903 	/*
904 	 * Purge anything not looked at above.
905 	 */
906 	omask = sigblock(SIGBLOCK);
907 	sepp = &servtab;
908 	while ((sep = *sepp)) {
909 		if (sep->se_checked) {
910 			sepp = &sep->se_next;
911 			continue;
912 		}
913 		*sepp = sep->se_next;
914 		if (sep->se_fd >= 0)
915 			close_sep(sep);
916 		if (debug)
917 			print_service("FREE", sep);
918 		if (sep->se_rpc && sep->se_rpc_prog > 0)
919 			unregisterrpc(sep);
920 		freeconfig(sep);
921 		free((char *)sep);
922 	}
923 	(void) sigsetmask(omask);
924 }
925 
926 void
927 unregisterrpc(sep)
928 	struct servtab *sep;
929 {
930         int i;
931         struct servtab *sepp;
932 	long omask;
933 
934 	omask = sigblock(SIGBLOCK);
935         for (sepp = servtab; sepp; sepp = sepp->se_next) {
936                 if (sepp == sep)
937                         continue;
938 		if (sep->se_checked == 0 ||
939                     !sepp->se_rpc ||
940                     sep->se_rpc_prog != sepp->se_rpc_prog)
941 			continue;
942                 return;
943         }
944         if (debug)
945                 print_service("UNREG", sep);
946         for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++)
947                 pmap_unset(sep->se_rpc_prog, i);
948         if (sep->se_fd != -1)
949                 (void) close(sep->se_fd);
950         sep->se_fd = -1;
951 	(void) sigsetmask(omask);
952 }
953 
954 void
955 flag_retry(signo)
956 	int signo;
957 {
958 	flag_signal('A');
959 }
960 
961 void
962 retry()
963 {
964 	struct servtab *sep;
965 
966 	timingout = 0;
967 	for (sep = servtab; sep; sep = sep->se_next)
968 		if (sep->se_fd == -1 && !ISMUX(sep))
969 			setup(sep);
970 }
971 
972 void
973 setup(sep)
974 	struct servtab *sep;
975 {
976 	int on = 1;
977 
978 	if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
979 		if (debug)
980 			warn("socket failed on %s/%s",
981 				sep->se_service, sep->se_proto);
982 		syslog(LOG_ERR, "%s/%s: socket: %m",
983 		    sep->se_service, sep->se_proto);
984 		return;
985 	}
986 #define	turnon(fd, opt) \
987 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
988 	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
989 	    turnon(sep->se_fd, SO_DEBUG) < 0)
990 		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
991 	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
992 		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
993 #ifdef SO_PRIVSTATE
994 	if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
995 		syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
996 #endif
997 #undef turnon
998 	if (sep->se_type == TTCP_TYPE)
999 		if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1000 		    (char *)&on, sizeof (on)) < 0)
1001 			syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1002 	if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1003 	    sizeof (sep->se_ctrladdr)) < 0) {
1004 		if (debug)
1005 			warn("bind failed on %s/%s",
1006 				sep->se_service, sep->se_proto);
1007 		syslog(LOG_ERR, "%s/%s: bind: %m",
1008 		    sep->se_service, sep->se_proto);
1009 		(void) close(sep->se_fd);
1010 		sep->se_fd = -1;
1011 		if (!timingout) {
1012 			timingout = 1;
1013 			alarm(RETRYTIME);
1014 		}
1015 		return;
1016 	}
1017         if (sep->se_rpc) {
1018                 int i, len = sizeof(struct sockaddr);
1019 
1020                 if (getsockname(sep->se_fd,
1021 				(struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1022                         syslog(LOG_ERR, "%s/%s: getsockname: %m",
1023                                sep->se_service, sep->se_proto);
1024                         (void) close(sep->se_fd);
1025                         sep->se_fd = -1;
1026                         return;
1027                 }
1028                 if (debug)
1029                         print_service("REG ", sep);
1030                 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1031                         pmap_unset(sep->se_rpc_prog, i);
1032                         pmap_set(sep->se_rpc_prog, i,
1033                                  (sep->se_socktype == SOCK_DGRAM)
1034                                  ? IPPROTO_UDP : IPPROTO_TCP,
1035                                  ntohs(sep->se_ctrladdr.sin_port));
1036                 }
1037 
1038         }
1039 	if (sep->se_socktype == SOCK_STREAM)
1040 		listen(sep->se_fd, 64);
1041 	enable(sep);
1042 	if (debug) {
1043 		warnx("registered %s on %d",
1044 			sep->se_server, sep->se_fd);
1045 	}
1046 }
1047 
1048 /*
1049  * Finish with a service and its socket.
1050  */
1051 void
1052 close_sep(sep)
1053 	struct servtab *sep;
1054 {
1055 	if (sep->se_fd >= 0) {
1056 		if (FD_ISSET(sep->se_fd, &allsock))
1057 			disable(sep);
1058 		(void) close(sep->se_fd);
1059 		sep->se_fd = -1;
1060 	}
1061 	sep->se_count = 0;
1062 	sep->se_numchild = 0;	/* forget about any existing children */
1063 }
1064 
1065 struct servtab *
1066 enter(cp)
1067 	struct servtab *cp;
1068 {
1069 	struct servtab *sep;
1070 	long omask;
1071 
1072 	sep = (struct servtab *)malloc(sizeof (*sep));
1073 	if (sep == (struct servtab *)0) {
1074 		syslog(LOG_ERR, "Out of memory.");
1075 		exit(EX_OSERR);
1076 	}
1077 	*sep = *cp;
1078 	sep->se_fd = -1;
1079 	omask = sigblock(SIGBLOCK);
1080 	sep->se_next = servtab;
1081 	servtab = sep;
1082 	sigsetmask(omask);
1083 	return (sep);
1084 }
1085 
1086 void
1087 enable(struct servtab *sep)
1088 {
1089 	if (debug)
1090 		warnx(
1091 		    "enabling %s, fd %d", sep->se_service, sep->se_fd);
1092 #ifdef SANITY_CHECK
1093 	if (sep->se_fd < 0) {
1094 		syslog(LOG_ERR,
1095 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1096 		exit(EX_SOFTWARE);
1097 	}
1098 	if (ISMUX(sep)) {
1099 		syslog(LOG_ERR,
1100 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1101 		exit(EX_SOFTWARE);
1102 	}
1103 	if (FD_ISSET(sep->se_fd, &allsock)) {
1104 		syslog(LOG_ERR,
1105 		    "%s: %s: not off", __FUNCTION__, sep->se_service);
1106 		exit(EX_SOFTWARE);
1107 	}
1108 #endif
1109 	FD_SET(sep->se_fd, &allsock);
1110 	nsock++;
1111 	if (sep->se_fd > maxsock)
1112 		maxsock = sep->se_fd;
1113 }
1114 
1115 void
1116 disable(struct servtab *sep)
1117 {
1118 	if (debug)
1119 		warnx(
1120 		    "disabling %s, fd %d", sep->se_service, sep->se_fd);
1121 #ifdef SANITY_CHECK
1122 	if (sep->se_fd < 0) {
1123 		syslog(LOG_ERR,
1124 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1125 		exit(EX_SOFTWARE);
1126 	}
1127 	if (ISMUX(sep)) {
1128 		syslog(LOG_ERR,
1129 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1130 		exit(EX_SOFTWARE);
1131 	}
1132 	if (!FD_ISSET(sep->se_fd, &allsock)) {
1133 		syslog(LOG_ERR,
1134 		    "%s: %s: not on", __FUNCTION__, sep->se_service);
1135 		exit(EX_SOFTWARE);
1136 	}
1137 	if (nsock == 0) {
1138 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
1139 		exit(EX_SOFTWARE);
1140 	}
1141 #endif
1142 	FD_CLR(sep->se_fd, &allsock);
1143 	nsock--;
1144 	if (sep->se_fd == maxsock)
1145 		maxsock--;
1146 }
1147 
1148 FILE	*fconfig = NULL;
1149 struct	servtab serv;
1150 char	line[LINE_MAX];
1151 
1152 int
1153 setconfig()
1154 {
1155 
1156 	if (fconfig != NULL) {
1157 		fseek(fconfig, 0L, SEEK_SET);
1158 		return (1);
1159 	}
1160 	fconfig = fopen(CONFIG, "r");
1161 	return (fconfig != NULL);
1162 }
1163 
1164 void
1165 endconfig()
1166 {
1167 	if (fconfig) {
1168 		(void) fclose(fconfig);
1169 		fconfig = NULL;
1170 	}
1171 }
1172 
1173 struct servtab *
1174 getconfigent()
1175 {
1176 	struct servtab *sep = &serv;
1177 	int argc;
1178 	char *cp, *arg, *s;
1179 	char *versp;
1180 	static char TCPMUX_TOKEN[] = "tcpmux/";
1181 #define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1182 
1183 more:
1184 	while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
1185 		;
1186 	if (cp == NULL)
1187 		return ((struct servtab *)0);
1188 	/*
1189 	 * clear the static buffer, since some fields (se_ctrladdr,
1190 	 * for example) don't get initialized here.
1191 	 */
1192 	memset((caddr_t)sep, 0, sizeof *sep);
1193 	arg = skip(&cp);
1194 	if (cp == NULL) {
1195 		/* got an empty line containing just blanks/tabs. */
1196 		goto more;
1197 	}
1198 	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1199 		char *c = arg + MUX_LEN;
1200 		if (*c == '+') {
1201 			sep->se_type = MUXPLUS_TYPE;
1202 			c++;
1203 		} else
1204 			sep->se_type = MUX_TYPE;
1205 		sep->se_service = newstr(c);
1206 	} else {
1207 		sep->se_service = newstr(arg);
1208 		sep->se_type = NORM_TYPE;
1209 	}
1210 	arg = sskip(&cp);
1211 	if (strcmp(arg, "stream") == 0)
1212 		sep->se_socktype = SOCK_STREAM;
1213 	else if (strcmp(arg, "dgram") == 0)
1214 		sep->se_socktype = SOCK_DGRAM;
1215 	else if (strcmp(arg, "rdm") == 0)
1216 		sep->se_socktype = SOCK_RDM;
1217 	else if (strcmp(arg, "seqpacket") == 0)
1218 		sep->se_socktype = SOCK_SEQPACKET;
1219 	else if (strcmp(arg, "raw") == 0)
1220 		sep->se_socktype = SOCK_RAW;
1221 	else
1222 		sep->se_socktype = -1;
1223 
1224 	arg = sskip(&cp);
1225 	if (strcmp(arg, "tcp/ttcp") == 0) {
1226 		sep->se_type = TTCP_TYPE;
1227 		sep->se_proto = newstr("tcp");
1228 	} else {
1229 		sep->se_proto = newstr(arg);
1230 	}
1231         if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1232                 memmove(sep->se_proto, sep->se_proto + 4,
1233                     strlen(sep->se_proto) + 1 - 4);
1234                 sep->se_rpc = 1;
1235                 sep->se_rpc_prog = sep->se_rpc_lowvers =
1236 			sep->se_rpc_lowvers = 0;
1237                 sep->se_ctrladdr.sin_family = AF_INET;
1238                 sep->se_ctrladdr.sin_port = 0;
1239                 sep->se_ctrladdr.sin_addr = bind_address;
1240                 if ((versp = rindex(sep->se_service, '/'))) {
1241                         *versp++ = '\0';
1242                         switch (sscanf(versp, "%d-%d",
1243                                        &sep->se_rpc_lowvers,
1244                                        &sep->se_rpc_highvers)) {
1245                         case 2:
1246                                 break;
1247                         case 1:
1248                                 sep->se_rpc_highvers =
1249                                         sep->se_rpc_lowvers;
1250                                 break;
1251                         default:
1252                                 syslog(LOG_ERR,
1253 					"bad RPC version specifier; %s\n",
1254 					sep->se_service);
1255                                 freeconfig(sep);
1256                                 goto more;
1257                         }
1258                 }
1259                 else {
1260                         sep->se_rpc_lowvers =
1261                                 sep->se_rpc_highvers = 1;
1262                 }
1263         }
1264 	arg = sskip(&cp);
1265 	if (!strncmp(arg, "wait", 4))
1266 		sep->se_accept = 0;
1267 	else if (!strncmp(arg, "nowait", 6))
1268 		sep->se_accept = 1;
1269 	else {
1270 		syslog(LOG_ERR,
1271 			"%s: bad wait/nowait for service %s",
1272 			CONFIG, sep->se_service);
1273 		goto more;
1274 	}
1275 	sep->se_maxchild = maxchild;
1276 	sep->se_maxcpm = maxcpm;
1277 	if ((s = strchr(arg, '/')) != NULL) {
1278 		char *eptr;
1279 		u_long val;
1280 
1281 		val = strtoul(s + 1, &eptr, 10);
1282 		if (eptr == s + 1 || val > MAX_MAXCHLD) {
1283 			syslog(LOG_ERR,
1284 				"%s: bad max-child for service %s",
1285 				CONFIG, sep->se_service);
1286 			goto more;
1287 		}
1288 		sep->se_maxchild = val;
1289 		if (*eptr == '/')
1290 			sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1291 		/*
1292 		 * explicitly do not check for \0 for future expansion /
1293 		 * backwards compatibility
1294 		 */
1295 	}
1296 	if (ISMUX(sep)) {
1297 		/*
1298 		 * Silently enforce "nowait" mode for TCPMUX services
1299 		 * since they don't have an assigned port to listen on.
1300 		 */
1301 		sep->se_accept = 1;
1302 		if (strcmp(sep->se_proto, "tcp")) {
1303 			syslog(LOG_ERR,
1304 				"%s: bad protocol for tcpmux service %s",
1305 				CONFIG, sep->se_service);
1306 			goto more;
1307 		}
1308 		if (sep->se_socktype != SOCK_STREAM) {
1309 			syslog(LOG_ERR,
1310 				"%s: bad socket type for tcpmux service %s",
1311 				CONFIG, sep->se_service);
1312 			goto more;
1313 		}
1314 	}
1315 	sep->se_user = newstr(sskip(&cp));
1316 #ifdef LOGIN_CAP
1317 	if ((s = strrchr(sep->se_user, '/')) != NULL) {
1318 		*s = '\0';
1319 		sep->se_class = newstr(s + 1);
1320 	} else
1321 		sep->se_class = newstr(RESOURCE_RC);
1322 #endif
1323 	if ((s = strrchr(sep->se_user, ':')) != NULL) {
1324 		*s = '\0';
1325 		sep->se_group = newstr(s + 1);
1326 	} else
1327 		sep->se_group = NULL;
1328 	sep->se_server = newstr(sskip(&cp));
1329 	if (strcmp(sep->se_server, "internal") == 0) {
1330 		struct biltin *bi;
1331 
1332 		for (bi = biltins; bi->bi_service; bi++)
1333 			if (bi->bi_socktype == sep->se_socktype &&
1334 			    strcmp(bi->bi_service, sep->se_service) == 0)
1335 				break;
1336 		if (bi->bi_service == 0) {
1337 			syslog(LOG_ERR, "internal service %s unknown",
1338 				sep->se_service);
1339 			goto more;
1340 		}
1341 		sep->se_accept = 1;	/* force accept mode for built-ins */
1342 		sep->se_bi = bi;
1343 	} else
1344 		sep->se_bi = NULL;
1345 	if (sep->se_maxchild < 0)	/* apply default max-children */
1346 		if (sep->se_bi)
1347 			sep->se_maxchild = sep->se_bi->bi_maxchild;
1348 		else
1349 			sep->se_maxchild = sep->se_accept ? 0 : 1;
1350 	if (sep->se_maxchild) {
1351 		sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1352 		if (sep->se_pids == NULL) {
1353 			syslog(LOG_ERR, "Out of memory.");
1354 			exit(EX_OSERR);
1355 		}
1356 	}
1357 	argc = 0;
1358 	for (arg = skip(&cp); cp; arg = skip(&cp))
1359 		if (argc < MAXARGV) {
1360 			sep->se_argv[argc++] = newstr(arg);
1361 		} else {
1362 			syslog(LOG_ERR,
1363 				"%s: too many arguments for service %s",
1364 				CONFIG, sep->se_service);
1365 			goto more;
1366 		}
1367 	while (argc <= MAXARGV)
1368 		sep->se_argv[argc++] = NULL;
1369 	return (sep);
1370 }
1371 
1372 void
1373 freeconfig(cp)
1374 	struct servtab *cp;
1375 {
1376 	int i;
1377 
1378 	if (cp->se_service)
1379 		free(cp->se_service);
1380 	if (cp->se_proto)
1381 		free(cp->se_proto);
1382 	if (cp->se_user)
1383 		free(cp->se_user);
1384 	if (cp->se_group)
1385 		free(cp->se_group);
1386 #ifdef LOGIN_CAP
1387 	if (cp->se_class)
1388 		free(cp->se_class);
1389 #endif
1390 	if (cp->se_server)
1391 		free(cp->se_server);
1392 	if (cp->se_pids)
1393 		free(cp->se_pids);
1394 	for (i = 0; i < MAXARGV; i++)
1395 		if (cp->se_argv[i])
1396 			free(cp->se_argv[i]);
1397 }
1398 
1399 
1400 /*
1401  * Safe skip - if skip returns null, log a syntax error in the
1402  * configuration file and exit.
1403  */
1404 char *
1405 sskip(cpp)
1406 	char **cpp;
1407 {
1408 	char *cp;
1409 
1410 	cp = skip(cpp);
1411 	if (cp == NULL) {
1412 		syslog(LOG_ERR, "%s: syntax error", CONFIG);
1413 		exit(EX_DATAERR);
1414 	}
1415 	return (cp);
1416 }
1417 
1418 char *
1419 skip(cpp)
1420 	char **cpp;
1421 {
1422 	char *cp = *cpp;
1423 	char *start;
1424 	char quote = '\0';
1425 
1426 again:
1427 	while (*cp == ' ' || *cp == '\t')
1428 		cp++;
1429 	if (*cp == '\0') {
1430 		int c;
1431 
1432 		c = getc(fconfig);
1433 		(void) ungetc(c, fconfig);
1434 		if (c == ' ' || c == '\t')
1435 			if ((cp = nextline(fconfig)))
1436 				goto again;
1437 		*cpp = (char *)0;
1438 		return ((char *)0);
1439 	}
1440 	if (*cp == '"' || *cp == '\'')
1441 		quote = *cp++;
1442 	start = cp;
1443 	if (quote)
1444 		while (*cp && *cp != quote)
1445 			cp++;
1446 	else
1447 		while (*cp && *cp != ' ' && *cp != '\t')
1448 			cp++;
1449 	if (*cp != '\0')
1450 		*cp++ = '\0';
1451 	*cpp = cp;
1452 	return (start);
1453 }
1454 
1455 char *
1456 nextline(fd)
1457 	FILE *fd;
1458 {
1459 	char *cp;
1460 
1461 	if (fgets(line, sizeof (line), fd) == NULL)
1462 		return ((char *)0);
1463 	cp = strchr(line, '\n');
1464 	if (cp)
1465 		*cp = '\0';
1466 	return (line);
1467 }
1468 
1469 char *
1470 newstr(cp)
1471 	char *cp;
1472 {
1473 	if ((cp = strdup(cp ? cp : "")))
1474 		return (cp);
1475 	syslog(LOG_ERR, "strdup: %m");
1476 	exit(EX_OSERR);
1477 }
1478 
1479 #ifdef OLD_SETPROCTITLE
1480 void
1481 inetd_setproctitle(a, s)
1482 	char *a;
1483 	int s;
1484 {
1485 	int size;
1486 	char *cp;
1487 	struct sockaddr_in sin;
1488 	char buf[80];
1489 
1490 	cp = Argv[0];
1491 	size = sizeof(sin);
1492 	if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1493 		(void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
1494 	else
1495 		(void) sprintf(buf, "-%s", a);
1496 	strncpy(cp, buf, LastArg - cp);
1497 	cp += strlen(cp);
1498 	while (cp < LastArg)
1499 		*cp++ = ' ';
1500 }
1501 #else
1502 void
1503 inetd_setproctitle(a, s)
1504 	char *a;
1505 	int s;
1506 {
1507 	int size;
1508 	struct sockaddr_in sin;
1509 	char buf[80];
1510 
1511 	size = sizeof(sin);
1512 	if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1513 		(void) sprintf(buf, "%s [%s]", a, inet_ntoa(sin.sin_addr));
1514 	else
1515 		(void) sprintf(buf, "%s", a);
1516 	setproctitle("%s", buf);
1517 }
1518 #endif
1519 
1520 
1521 /*
1522  * Internet services provided internally by inetd:
1523  */
1524 #define	BUFSIZE	8192
1525 
1526 #define IDENT_RESPONSE ":ERROR:HIDDEN-USER\r\n"
1527 
1528 /* ARGSUSED */
1529 void
1530 ident_stream(s, sep)		/* Ident service */
1531 	int s;
1532 	struct servtab *sep;
1533 {
1534 	char buffer[BUFSIZE];
1535 	int i, j;
1536 
1537 	inetd_setproctitle(sep->se_service, s);
1538 	j = 0;
1539 	while ((i = read(s, buffer + j, sizeof(buffer) - j)) > 0) {
1540 		j += i;
1541 		buffer[j] = '\0';
1542 		if (strchr(buffer, '\n'))
1543 			break;
1544 		if (strchr(buffer, '\r'))
1545 			break;
1546 	}
1547 	while (j > 0 && (buffer[j-1] == '\n' || buffer[j-1] == '\r'))
1548 		j--;
1549 	write(s, buffer, j);
1550 	write(s, IDENT_RESPONSE, strlen(IDENT_RESPONSE));
1551 	exit(0);
1552 }
1553 /* ARGSUSED */
1554 void
1555 echo_stream(s, sep)		/* Echo service -- echo data back */
1556 	int s;
1557 	struct servtab *sep;
1558 {
1559 	char buffer[BUFSIZE];
1560 	int i;
1561 
1562 	inetd_setproctitle(sep->se_service, s);
1563 	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1564 	    write(s, buffer, i) > 0)
1565 		;
1566 	exit(0);
1567 }
1568 
1569 int check_loop(sin, sep)
1570 	struct sockaddr_in *sin;
1571 	struct servtab *sep;
1572 {
1573 	struct servtab *se2;
1574 
1575 	for (se2 = servtab; se2; se2 = se2->se_next) {
1576 		if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
1577 			continue;
1578 
1579 		if (sin->sin_port == se2->se_ctrladdr.sin_port) {
1580 			syslog(LOG_WARNING,
1581 			       "%s/%s:%s/%s loop request REFUSED from %s",
1582 			       sep->se_service, sep->se_proto,
1583 			       se2->se_service, se2->se_proto,
1584 			       inet_ntoa(sin->sin_addr));
1585 			return 1;
1586 		}
1587 	}
1588 	return 0;
1589 }
1590 
1591 /* ARGSUSED */
1592 void
1593 echo_dg(s, sep)			/* Echo service -- echo data back */
1594 	int s;
1595 	struct servtab *sep;
1596 {
1597 	char buffer[BUFSIZE];
1598 	int i, size;
1599 	struct sockaddr_in sin;
1600 
1601 	size = sizeof(sin);
1602 	if ((i = recvfrom(s, buffer, sizeof(buffer), 0,
1603 			  (struct sockaddr *)&sin, &size)) < 0)
1604 		return;
1605 
1606 	if (check_loop(&sin, sep))
1607 		return;
1608 
1609 	(void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin,
1610 		      sizeof(sin));
1611 }
1612 
1613 /* ARGSUSED */
1614 void
1615 discard_stream(s, sep)		/* Discard service -- ignore data */
1616 	int s;
1617 	struct servtab *sep;
1618 {
1619 	int ret;
1620 	char buffer[BUFSIZE];
1621 
1622 	inetd_setproctitle(sep->se_service, s);
1623 	while (1) {
1624 		while ((ret = read(s, buffer, sizeof(buffer))) > 0)
1625 			;
1626 		if (ret == 0 || errno != EINTR)
1627 			break;
1628 	}
1629 	exit(0);
1630 }
1631 
1632 /* ARGSUSED */
1633 void
1634 discard_dg(s, sep)		/* Discard service -- ignore data */
1635 	int s;
1636 	struct servtab *sep;
1637 {
1638 	char buffer[BUFSIZE];
1639 
1640 	(void) read(s, buffer, sizeof(buffer));
1641 }
1642 
1643 #include <ctype.h>
1644 #define LINESIZ 72
1645 char ring[128];
1646 char *endring;
1647 
1648 void
1649 initring()
1650 {
1651 	int i;
1652 
1653 	endring = ring;
1654 
1655 	for (i = 0; i <= 128; ++i)
1656 		if (isprint(i))
1657 			*endring++ = i;
1658 }
1659 
1660 /* ARGSUSED */
1661 void
1662 chargen_stream(s, sep)		/* Character generator */
1663 	int s;
1664 	struct servtab *sep;
1665 {
1666 	int len;
1667 	char *rs, text[LINESIZ+2];
1668 
1669 	inetd_setproctitle(sep->se_service, s);
1670 
1671 	if (!endring) {
1672 		initring();
1673 		rs = ring;
1674 	}
1675 
1676 	text[LINESIZ] = '\r';
1677 	text[LINESIZ + 1] = '\n';
1678 	for (rs = ring;;) {
1679 		if ((len = endring - rs) >= LINESIZ)
1680 			memmove(text, rs, LINESIZ);
1681 		else {
1682 			memmove(text, rs, len);
1683 			memmove(text + len, ring, LINESIZ - len);
1684 		}
1685 		if (++rs == endring)
1686 			rs = ring;
1687 		if (write(s, text, sizeof(text)) != sizeof(text))
1688 			break;
1689 	}
1690 	exit(0);
1691 }
1692 
1693 /* ARGSUSED */
1694 void
1695 chargen_dg(s, sep)		/* Character generator */
1696 	int s;
1697 	struct servtab *sep;
1698 {
1699 	struct sockaddr_in sin;
1700 	static char *rs;
1701 	int len, size;
1702 	char text[LINESIZ+2];
1703 
1704 	if (endring == 0) {
1705 		initring();
1706 		rs = ring;
1707 	}
1708 
1709 	size = sizeof(sin);
1710 	if (recvfrom(s, text, sizeof(text), 0,
1711 		     (struct sockaddr *)&sin, &size) < 0)
1712 		return;
1713 
1714 	if (check_loop(&sin, sep))
1715 		return;
1716 
1717 	if ((len = endring - rs) >= LINESIZ)
1718 		memmove(text, rs, LINESIZ);
1719 	else {
1720 		memmove(text, rs, len);
1721 		memmove(text + len, ring, LINESIZ - len);
1722 	}
1723 	if (++rs == endring)
1724 		rs = ring;
1725 	text[LINESIZ] = '\r';
1726 	text[LINESIZ + 1] = '\n';
1727 	(void) sendto(s, text, sizeof(text), 0,
1728 		      (struct sockaddr *)&sin, sizeof(sin));
1729 }
1730 
1731 /*
1732  * Return a machine readable date and time, in the form of the
1733  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1734  * returns the number of seconds since midnight, Jan 1, 1970,
1735  * we must add 2208988800 seconds to this figure to make up for
1736  * some seventy years Bell Labs was asleep.
1737  */
1738 
1739 unsigned long
1740 machtime()
1741 {
1742 	struct timeval tv;
1743 
1744 	if (gettimeofday(&tv, (struct timezone *)NULL) < 0) {
1745 		if (debug)
1746 			warnx("unable to get time of day");
1747 		return (0L);
1748 	}
1749 #define	OFFSET ((u_long)25567 * 24*60*60)
1750 	return (htonl((long)(tv.tv_sec + OFFSET)));
1751 #undef OFFSET
1752 }
1753 
1754 /* ARGSUSED */
1755 void
1756 machtime_stream(s, sep)
1757 	int s;
1758 	struct servtab *sep;
1759 {
1760 	unsigned long result;
1761 
1762 	result = machtime();
1763 	(void) write(s, (char *) &result, sizeof(result));
1764 }
1765 
1766 /* ARGSUSED */
1767 void
1768 machtime_dg(s, sep)
1769 	int s;
1770 	struct servtab *sep;
1771 {
1772 	unsigned long result;
1773 	struct sockaddr_in sin;
1774 	int size;
1775 
1776 	size = sizeof(sin);
1777 	if (recvfrom(s, (char *)&result, sizeof(result), 0,
1778 		     (struct sockaddr *)&sin, &size) < 0)
1779 		return;
1780 
1781 	if (check_loop(&sin, sep))
1782 		return;
1783 
1784 	result = machtime();
1785 	(void) sendto(s, (char *) &result, sizeof(result), 0,
1786 		      (struct sockaddr *)&sin, sizeof(sin));
1787 }
1788 
1789 /* ARGSUSED */
1790 void
1791 daytime_stream(s, sep)		/* Return human-readable time of day */
1792 	int s;
1793 	struct servtab *sep;
1794 {
1795 	char buffer[256];
1796 	time_t clock;
1797 
1798 	clock = time((time_t *) 0);
1799 
1800 	(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
1801 	(void) write(s, buffer, strlen(buffer));
1802 }
1803 
1804 /* ARGSUSED */
1805 void
1806 daytime_dg(s, sep)		/* Return human-readable time of day */
1807 	int s;
1808 	struct servtab *sep;
1809 {
1810 	char buffer[256];
1811 	time_t clock;
1812 	struct sockaddr_in sin;
1813 	int size;
1814 
1815 	clock = time((time_t *) 0);
1816 
1817 	size = sizeof(sin);
1818 	if (recvfrom(s, buffer, sizeof(buffer), 0,
1819 		     (struct sockaddr *)&sin, &size) < 0)
1820 		return;
1821 
1822 	if (check_loop(&sin, sep))
1823 		return;
1824 
1825 	(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
1826 	(void) sendto(s, buffer, strlen(buffer), 0,
1827 		      (struct sockaddr *)&sin, sizeof(sin));
1828 }
1829 
1830 /*
1831  * print_service:
1832  *	Dump relevant information to stderr
1833  */
1834 void
1835 print_service(action, sep)
1836 	char *action;
1837 	struct servtab *sep;
1838 {
1839 	fprintf(stderr,
1840 #ifdef LOGIN_CAP
1841 	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s class=%s builtin=%p server=%s\n",
1842 #else
1843 	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s builtin=%p server=%s\n",
1844 #endif
1845 	    action, sep->se_service, sep->se_proto,
1846 	    sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
1847 #ifdef LOGIN_CAP
1848 	    sep->se_class,
1849 #endif
1850 	    (void *) sep->se_bi, sep->se_server);
1851 }
1852 
1853 /*
1854  *  Based on TCPMUX.C by Mark K. Lottor November 1988
1855  *  sri-nic::ps:<mkl>tcpmux.c
1856  */
1857 
1858 
1859 static int		/* # of characters upto \r,\n or \0 */
1860 getline(fd, buf, len)
1861 	int fd;
1862 	char *buf;
1863 	int len;
1864 {
1865 	int count = 0, n;
1866 	struct sigaction sa;
1867 
1868 	sa.sa_flags = 0;
1869 	sigemptyset(&sa.sa_mask);
1870 	sa.sa_handler = SIG_DFL;
1871 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
1872 	do {
1873 		alarm(10);
1874 		n = read(fd, buf, len-count);
1875 		alarm(0);
1876 		if (n == 0)
1877 			return (count);
1878 		if (n < 0)
1879 			return (-1);
1880 		while (--n >= 0) {
1881 			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
1882 				return (count);
1883 			count++;
1884 			buf++;
1885 		}
1886 	} while (count < len);
1887 	return (count);
1888 }
1889 
1890 #define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
1891 
1892 #define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
1893 
1894 struct servtab *
1895 tcpmux(s)
1896 	int s;
1897 {
1898 	struct servtab *sep;
1899 	char service[MAX_SERV_LEN+1];
1900 	int len;
1901 
1902 	/* Get requested service name */
1903 	if ((len = getline(s, service, MAX_SERV_LEN)) < 0) {
1904 		strwrite(s, "-Error reading service name\r\n");
1905 		return (NULL);
1906 	}
1907 	service[len] = '\0';
1908 
1909 	if (debug)
1910 		warnx("tcpmux: someone wants %s", service);
1911 
1912 	/*
1913 	 * Help is a required command, and lists available services,
1914 	 * one per line.
1915 	 */
1916 	if (!strcasecmp(service, "help")) {
1917 		for (sep = servtab; sep; sep = sep->se_next) {
1918 			if (!ISMUX(sep))
1919 				continue;
1920 			(void)write(s,sep->se_service,strlen(sep->se_service));
1921 			strwrite(s, "\r\n");
1922 		}
1923 		return (NULL);
1924 	}
1925 
1926 	/* Try matching a service in inetd.conf with the request */
1927 	for (sep = servtab; sep; sep = sep->se_next) {
1928 		if (!ISMUX(sep))
1929 			continue;
1930 		if (!strcasecmp(service, sep->se_service)) {
1931 			if (ISMUXPLUS(sep)) {
1932 				strwrite(s, "+Go\r\n");
1933 			}
1934 			return (sep);
1935 		}
1936 	}
1937 	strwrite(s, "-Service not available\r\n");
1938 	return (NULL);
1939 }
1940 
1941 #define CPMHSIZE	256
1942 #define CPMHMASK	(CPMHSIZE-1)
1943 #define CHTGRAN		10
1944 #define CHTSIZE		6
1945 
1946 typedef struct CTime {
1947 	unsigned long 	ct_Ticks;
1948 	int		ct_Count;
1949 } CTime;
1950 
1951 typedef struct CHash {
1952 	struct in_addr	ch_Addr;
1953 	time_t		ch_LTime;
1954 	char		*ch_Service;
1955 	CTime		ch_Times[CHTSIZE];
1956 } CHash;
1957 
1958 CHash	CHashAry[CPMHSIZE];
1959 
1960 int
1961 cpmip(sep, ctrl)
1962 	struct servtab *sep;
1963 	int ctrl;
1964 {
1965 	struct sockaddr_in rsin;
1966 	int rsinLen = sizeof(rsin);
1967 	int r = 0;
1968 
1969 	/*
1970 	 * If getpeername() fails, just let it through (if logging is
1971 	 * enabled the condition is caught elsewhere)
1972 	 */
1973 
1974 	if (sep->se_maxcpm > 0 &&
1975 	    getpeername(ctrl, (struct sockaddr *)&rsin, &rsinLen) == 0 ) {
1976 		time_t t = time(NULL);
1977 		int hv = 0xABC3D20F;
1978 		int i;
1979 		int cnt = 0;
1980 		CHash *chBest = NULL;
1981 		unsigned int ticks = t / CHTGRAN;
1982 
1983 		{
1984 			char *p;
1985 			int i;
1986 
1987 			for (i = 0, p = (char *)&rsin.sin_addr;
1988 			    i < sizeof(rsin.sin_addr);
1989 			    ++i, ++p) {
1990 				hv = (hv << 5) ^ (hv >> 23) ^ *p;
1991 			}
1992 			hv = (hv ^ (hv >> 16));
1993 		}
1994 		for (i = 0; i < 5; ++i) {
1995 			CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
1996 
1997 			if (rsin.sin_addr.s_addr == ch->ch_Addr.s_addr &&
1998 			    ch->ch_Service && strcmp(sep->se_service,
1999 			    ch->ch_Service) == 0) {
2000 				chBest = ch;
2001 				break;
2002 			}
2003 			if (chBest == NULL || ch->ch_LTime == 0 ||
2004 			    ch->ch_LTime < chBest->ch_LTime) {
2005 				chBest = ch;
2006 			}
2007 		}
2008 		if (rsin.sin_addr.s_addr != chBest->ch_Addr.s_addr ||
2009 		    chBest->ch_Service == NULL ||
2010 		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2011 			chBest->ch_Addr = rsin.sin_addr;
2012 			if (chBest->ch_Service)
2013 				free(chBest->ch_Service);
2014 			chBest->ch_Service = strdup(sep->se_service);
2015 			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2016 		}
2017 		chBest->ch_LTime = t;
2018 		{
2019 			CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2020 			if (ct->ct_Ticks != ticks) {
2021 				ct->ct_Ticks = ticks;
2022 				ct->ct_Count = 0;
2023 			}
2024 			++ct->ct_Count;
2025 		}
2026 		for (i = 0; i < CHTSIZE; ++i) {
2027 			CTime *ct = &chBest->ch_Times[i];
2028 			if (ct->ct_Ticks <= ticks &&
2029 			    ct->ct_Ticks >= ticks - CHTSIZE) {
2030 				cnt += ct->ct_Count;
2031 			}
2032 		}
2033 		if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
2034 			r = -1;
2035 			syslog(LOG_ERR,
2036 			    "%s from %s exceeded counts/min (limit %d/min)",
2037 			    sep->se_service, inet_ntoa(rsin.sin_addr),
2038 			    sep->se_maxcpm);
2039 		}
2040 	}
2041 	return(r);
2042 }
2043