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