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