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