inetd.c revision 106054
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
44#endif /* not lint */
45
46#include <sys/cdefs.h>
47__FBSDID("$FreeBSD: head/usr.sbin/inetd/inetd.c 106054 2002-10-27 17:46:53Z wollman $");
48
49/*
50 * Inetd - Internet super-server
51 *
52 * This program invokes all internet services as needed.  Connection-oriented
53 * services are invoked each time a connection is made, by creating a process.
54 * This process is passed the connection as file descriptor 0 and is expected
55 * to do a getpeername to find out the source host and port.
56 *
57 * Datagram oriented services are invoked when a datagram
58 * arrives; a process is created and passed a pending message
59 * on file descriptor 0.  Datagram servers may either connect
60 * to their peer, freeing up the original socket for inetd
61 * to receive further messages on, or ``take over the socket'',
62 * processing all arriving datagrams and, eventually, timing
63 * out.	 The first type of server is said to be ``multi-threaded'';
64 * the second type of server ``single-threaded''.
65 *
66 * Inetd uses a configuration file which is read at startup
67 * and, possibly, at some later time in response to a hangup signal.
68 * The configuration file is ``free format'' with fields given in the
69 * order shown below.  Continuation lines for an entry must begin with
70 * a space or tab.  All fields must be present in each entry.
71 *
72 *	service name			must be in /etc/services
73 *					or name a tcpmux service
74 *					or specify a unix domain socket
75 *	socket type			stream/dgram/raw/rdm/seqpacket
76 *	protocol			tcp[4][6][/faith,ttcp], udp[4][6], unix
77 *	wait/nowait			single-threaded/multi-threaded
78 *	user				user to run daemon as
79 *	server program			full path name
80 *	server program arguments	maximum of MAXARGS (20)
81 *
82 * TCP services without official port numbers are handled with the
83 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
84 * requests. When a connection is made from a foreign host, the service
85 * requested is passed to tcpmux, which looks it up in the servtab list
86 * and returns the proper entry for the service. Tcpmux returns a
87 * negative reply if the service doesn't exist, otherwise the invoked
88 * server is expected to return the positive reply if the service type in
89 * inetd.conf file has the prefix "tcpmux/". If the service type has the
90 * prefix "tcpmux/+", tcpmux will return the positive reply for the
91 * process; this is for compatibility with older server code, and also
92 * allows you to invoke programs that use stdin/stdout without putting any
93 * special server code in them. Services that use tcpmux are "nowait"
94 * because they do not have a well-known port and hence cannot listen
95 * for new requests.
96 *
97 * For RPC services
98 *	service name/version		must be in /etc/rpc
99 *	socket type			stream/dgram/raw/rdm/seqpacket
100 *	protocol			rpc/tcp[4][6], rpc/udp[4][6]
101 *	wait/nowait			single-threaded/multi-threaded
102 *	user				user to run daemon as
103 *	server program			full path name
104 *	server program arguments	maximum of MAXARGS
105 *
106 * Comment lines are indicated by a `#' in column 1.
107 *
108 * #ifdef IPSEC
109 * Comment lines that start with "#@" denote IPsec policy string, as described
110 * in ipsec_set_policy(3).  This will affect all the following items in
111 * inetd.conf(8).  To reset the policy, just use "#@" line.  By default,
112 * there's no IPsec policy.
113 * #endif
114 */
115#include <sys/param.h>
116#include <sys/ioctl.h>
117#include <sys/wait.h>
118#include <sys/time.h>
119#include <sys/resource.h>
120#include <sys/stat.h>
121#include <sys/un.h>
122
123#include <netinet/in.h>
124#include <netinet/tcp.h>
125#include <arpa/inet.h>
126#include <rpc/rpc.h>
127#include <rpc/pmap_clnt.h>
128
129#include <ctype.h>
130#include <errno.h>
131#include <err.h>
132#include <fcntl.h>
133#include <grp.h>
134#include <libutil.h>
135#include <limits.h>
136#include <netdb.h>
137#include <pwd.h>
138#include <signal.h>
139#include <stdio.h>
140#include <stdlib.h>
141#include <string.h>
142#include <sysexits.h>
143#include <syslog.h>
144#include <tcpd.h>
145#include <unistd.h>
146
147#include "inetd.h"
148#include "pathnames.h"
149
150#ifdef IPSEC
151#include <netinet6/ipsec.h>
152#ifndef IPSEC_POLICY_IPSEC	/* no ipsec support on old ipsec */
153#undef IPSEC
154#endif
155#endif
156
157/* wrapper for KAME-special getnameinfo() */
158#ifndef NI_WITHSCOPEID
159#define NI_WITHSCOPEID	0
160#endif
161
162#ifndef LIBWRAP_ALLOW_FACILITY
163# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
164#endif
165#ifndef LIBWRAP_ALLOW_SEVERITY
166# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
167#endif
168#ifndef LIBWRAP_DENY_FACILITY
169# define LIBWRAP_DENY_FACILITY LOG_AUTH
170#endif
171#ifndef LIBWRAP_DENY_SEVERITY
172# define LIBWRAP_DENY_SEVERITY LOG_WARNING
173#endif
174
175#define ISWRAP(sep)	\
176	   ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
177	&& (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
178	&& ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
179	    || (sep)->se_socktype == SOCK_DGRAM))
180
181#ifdef LOGIN_CAP
182#include <login_cap.h>
183
184/* see init.c */
185#define RESOURCE_RC "daemon"
186
187#endif
188
189#ifndef	MAXCHILD
190#define	MAXCHILD	-1		/* maximum number of this service
191					   < 0 = no limit */
192#endif
193
194#ifndef	MAXCPM
195#define	MAXCPM		-1		/* rate limit invocations from a
196					   single remote address,
197					   < 0 = no limit */
198#endif
199
200#ifndef	MAXPERIP
201#define	MAXPERIP	-1		/* maximum number of this service
202					   from a single remote address,
203					   < 0 = no limit */
204#endif
205
206#ifndef TOOMANY
207#define	TOOMANY		256		/* don't start more than TOOMANY */
208#endif
209#define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
210#define	RETRYTIME	(60*10)		/* retry after bind or server fail */
211#define MAX_MAXCHLD	32767		/* max allowable max children */
212
213#define	SIGBLOCK	(sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
214
215void		close_sep(struct servtab *);
216void		flag_signal(int);
217void		flag_config(int);
218void		config(void);
219int		cpmip(const struct servtab *, int);
220void		endconfig(void);
221struct servtab *enter(struct servtab *);
222void		freeconfig(struct servtab *);
223struct servtab *getconfigent(void);
224int		matchservent(const char *, const char *, const char *);
225char	       *nextline(FILE *);
226void		addchild(struct servtab *, int);
227void		flag_reapchild(int);
228void		reapchild(void);
229void		enable(struct servtab *);
230void		disable(struct servtab *);
231void		flag_retry(int);
232void		retry(void);
233int		setconfig(void);
234void		setup(struct servtab *);
235#ifdef IPSEC
236void		ipsecsetup(struct servtab *);
237#endif
238void		unregisterrpc(register struct servtab *sep);
239static struct conninfo *search_conn(struct servtab *sep, int ctrl);
240static int	room_conn(struct servtab *sep, struct conninfo *conn);
241static void	addchild_conn(struct conninfo *conn, pid_t pid);
242static void	reapchild_conn(pid_t pid);
243static void	free_conn(struct conninfo *conn);
244static void	resize_conn(struct servtab *sep, int maxperip);
245static void	free_connlist(struct servtab *sep);
246static void	free_proc(struct procinfo *);
247static struct procinfo *search_proc(pid_t pid, int add);
248static int	hashval(char *p, int len);
249
250int	allow_severity;
251int	deny_severity;
252int	wrap_ex = 0;
253int	wrap_bi = 0;
254int	debug = 0;
255int	log = 0;
256int	maxsock;			/* highest-numbered descriptor */
257fd_set	allsock;
258int	options;
259int	timingout;
260int	toomany = TOOMANY;
261int	maxchild = MAXCHILD;
262int	maxcpm = MAXCPM;
263int	maxperip = MAXPERIP;
264struct	servent *sp;
265struct	rpcent *rpc;
266char	*hostname = NULL;
267struct	sockaddr_in *bind_sa4;
268int	v4bind_ok = 0;
269#ifdef INET6
270struct	sockaddr_in6 *bind_sa6;
271int	v6bind_ok = 0;
272#endif
273int	signalpipe[2];
274#ifdef SANITY_CHECK
275int	nsock;
276#endif
277uid_t	euid;
278gid_t	egid;
279mode_t	mask;
280
281struct	servtab *servtab;
282
283extern struct biltin biltins[];
284
285const char	*CONFIG = _PATH_INETDCONF;
286const char	*pid_file = _PATH_INETDPID;
287
288struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf;
289
290static LIST_HEAD(, procinfo) proctable[PERIPSIZE];
291
292int
293getvalue(const char *arg, int *value, const char *whine)
294{
295	int  tmp;
296	char *p;
297
298	tmp = strtol(arg, &p, 0);
299	if (tmp < 0 || *p) {
300		syslog(LOG_ERR, whine, arg);
301		return 1;			/* failure */
302	}
303	*value = tmp;
304	return 0;				/* success */
305}
306
307int
308main(int argc, char **argv)
309{
310	struct servtab *sep;
311	struct passwd *pwd;
312	struct group *grp;
313	struct sigaction sa, saalrm, sachld, sahup, sapipe;
314	int tmpint, ch, dofork;
315	pid_t pid;
316	char buf[50];
317#ifdef LOGIN_CAP
318	login_cap_t *lc = NULL;
319#endif
320	struct request_info req;
321	int denied;
322	char *service = NULL;
323	union {
324		struct sockaddr peer_un;
325		struct sockaddr_in peer_un4;
326		struct sockaddr_in6 peer_un6;
327		struct sockaddr_storage peer_max;
328	} p_un;
329#define peer	p_un.peer_un
330#define peer4	p_un.peer_un4
331#define peer6	p_un.peer_un6
332#define peermax	p_un.peer_max
333	int i;
334	struct addrinfo hints, *res;
335	const char *servname;
336	int error;
337	struct conninfo *conn;
338
339	openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON);
340
341	while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1)
342		switch(ch) {
343		case 'd':
344			debug = 1;
345			options |= SO_DEBUG;
346			break;
347		case 'l':
348			log = 1;
349			break;
350		case 'R':
351			getvalue(optarg, &toomany,
352				"-R %s: bad value for service invocation rate");
353			break;
354		case 'c':
355			getvalue(optarg, &maxchild,
356				"-c %s: bad value for maximum children");
357			break;
358		case 'C':
359			getvalue(optarg, &maxcpm,
360				"-C %s: bad value for maximum children/minute");
361			break;
362		case 'a':
363			hostname = optarg;
364			break;
365		case 'p':
366			pid_file = optarg;
367			break;
368		case 's':
369			getvalue(optarg, &maxperip,
370				"-s %s: bad value for maximum children per source address");
371			break;
372		case 'w':
373			wrap_ex++;
374			break;
375		case 'W':
376			wrap_bi++;
377			break;
378		case '?':
379		default:
380			syslog(LOG_ERR,
381				"usage: inetd [-dlwW] [-a address] [-R rate]"
382				" [-c maximum] [-C rate]"
383				" [-p pidfile] [conf-file]");
384			exit(EX_USAGE);
385		}
386	/*
387	 * Initialize Bind Addrs.
388	 *   When hostname is NULL, wild card bind addrs are obtained from
389	 *   getaddrinfo(). But getaddrinfo() requires at least one of
390	 *   hostname or servname is non NULL.
391	 *   So when hostname is NULL, set dummy value to servname.
392	 */
393	servname = (hostname == NULL) ? "discard" /* dummy */ : NULL;
394
395	bzero(&hints, sizeof(struct addrinfo));
396	hints.ai_flags = AI_PASSIVE;
397	hints.ai_family = AF_UNSPEC;
398	error = getaddrinfo(hostname, servname, &hints, &res);
399	if (error != 0) {
400		syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
401		if (error == EAI_SYSTEM)
402			syslog(LOG_ERR, "%s", strerror(errno));
403		exit(EX_USAGE);
404	}
405	do {
406		if (res->ai_addr == NULL) {
407			syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
408			exit(EX_USAGE);
409		}
410		switch (res->ai_addr->sa_family) {
411		case AF_INET:
412			if (v4bind_ok)
413				continue;
414			bind_sa4 = (struct sockaddr_in *)res->ai_addr;
415			/* init port num in case servname is dummy */
416			bind_sa4->sin_port = 0;
417			v4bind_ok = 1;
418			continue;
419#ifdef INET6
420		case AF_INET6:
421			if (v6bind_ok)
422				continue;
423			bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
424			/* init port num in case servname is dummy */
425			bind_sa6->sin6_port = 0;
426			v6bind_ok = 1;
427			continue;
428#endif
429		}
430		if (v4bind_ok
431#ifdef INET6
432		    && v6bind_ok
433#endif
434		    )
435			break;
436	} while ((res = res->ai_next) != NULL);
437	if (!v4bind_ok
438#ifdef INET6
439	    && !v6bind_ok
440#endif
441	    ) {
442		syslog(LOG_ERR, "-a %s: unknown address family", hostname);
443		exit(EX_USAGE);
444	}
445
446	euid = geteuid();
447	egid = getegid();
448	umask(mask = umask(0777));
449
450	argc -= optind;
451	argv += optind;
452
453	if (argc > 0)
454		CONFIG = argv[0];
455	if (debug == 0) {
456		FILE *fp;
457		if (daemon(0, 0) < 0) {
458			syslog(LOG_WARNING, "daemon(0,0) failed: %m");
459		}
460		/* From now on we don't want syslog messages going to stderr. */
461		closelog();
462		openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
463		/*
464		 * In case somebody has started inetd manually, we need to
465		 * clear the logname, so that old servers run as root do not
466		 * get the user's logname..
467		 */
468		if (setlogin("") < 0) {
469			syslog(LOG_WARNING, "cannot clear logname: %m");
470			/* no big deal if it fails.. */
471		}
472		pid = getpid();
473		fp = fopen(pid_file, "w");
474		if (fp) {
475			fprintf(fp, "%ld\n", (long)pid);
476			fclose(fp);
477		} else {
478			syslog(LOG_WARNING, "%s: %m", pid_file);
479		}
480	}
481
482	for (i = 0; i < PERIPSIZE; ++i)
483		LIST_INIT(&proctable[i]);
484
485	if (v4bind_ok) {
486		udpconf = getnetconfigent("udp");
487		tcpconf = getnetconfigent("tcp");
488		if (udpconf == NULL || tcpconf == NULL) {
489			syslog(LOG_ERR, "unknown rpc/udp or rpc/tcp");
490			exit(EX_USAGE);
491		}
492	}
493#ifdef INET6
494	if (v6bind_ok) {
495		udp6conf = getnetconfigent("udp6");
496		tcp6conf = getnetconfigent("tcp6");
497		if (udp6conf == NULL || tcp6conf == NULL) {
498			syslog(LOG_ERR, "unknown rpc/udp6 or rpc/tcp6");
499			exit(EX_USAGE);
500		}
501	}
502#endif
503
504	sa.sa_flags = 0;
505	sigemptyset(&sa.sa_mask);
506	sigaddset(&sa.sa_mask, SIGALRM);
507	sigaddset(&sa.sa_mask, SIGCHLD);
508	sigaddset(&sa.sa_mask, SIGHUP);
509	sa.sa_handler = flag_retry;
510	sigaction(SIGALRM, &sa, &saalrm);
511	config();
512	sa.sa_handler = flag_config;
513	sigaction(SIGHUP, &sa, &sahup);
514	sa.sa_handler = flag_reapchild;
515	sigaction(SIGCHLD, &sa, &sachld);
516	sa.sa_handler = SIG_IGN;
517	sigaction(SIGPIPE, &sa, &sapipe);
518
519	{
520		/* space for daemons to overwrite environment for ps */
521#define	DUMMYSIZE	100
522		char dummy[DUMMYSIZE];
523
524		(void)memset(dummy, 'x', DUMMYSIZE - 1);
525		dummy[DUMMYSIZE - 1] = '\0';
526		(void)setenv("inetd_dummy", dummy, 1);
527	}
528
529	if (pipe(signalpipe) != 0) {
530		syslog(LOG_ERR, "pipe: %m");
531		exit(EX_OSERR);
532	}
533	FD_SET(signalpipe[0], &allsock);
534#ifdef SANITY_CHECK
535	nsock++;
536#endif
537	if (signalpipe[0] > maxsock)
538	    maxsock = signalpipe[0];
539	if (signalpipe[1] > maxsock)
540	    maxsock = signalpipe[1];
541
542	for (;;) {
543	    int n, ctrl;
544	    fd_set readable;
545
546#ifdef SANITY_CHECK
547	    if (nsock == 0) {
548		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
549		exit(EX_SOFTWARE);
550	    }
551#endif
552	    readable = allsock;
553	    if ((n = select(maxsock + 1, &readable, (fd_set *)0,
554		(fd_set *)0, (struct timeval *)0)) <= 0) {
555		    if (n < 0 && errno != EINTR) {
556			syslog(LOG_WARNING, "select: %m");
557			sleep(1);
558		    }
559		    continue;
560	    }
561	    /* handle any queued signal flags */
562	    if (FD_ISSET(signalpipe[0], &readable)) {
563		int nsig;
564		if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) {
565		    syslog(LOG_ERR, "ioctl: %m");
566		    exit(EX_OSERR);
567		}
568		while (--nsig >= 0) {
569		    char c;
570		    if (read(signalpipe[0], &c, 1) != 1) {
571			syslog(LOG_ERR, "read: %m");
572			exit(EX_OSERR);
573		    }
574		    if (debug)
575			warnx("handling signal flag %c", c);
576		    switch(c) {
577		    case 'A': /* sigalrm */
578			retry();
579			break;
580		    case 'C': /* sigchld */
581			reapchild();
582			break;
583		    case 'H': /* sighup */
584			config();
585			break;
586		    }
587		}
588	    }
589	    for (sep = servtab; n && sep; sep = sep->se_next)
590	        if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
591		    n--;
592		    if (debug)
593			    warnx("someone wants %s", sep->se_service);
594		    dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep);
595		    conn = NULL;
596		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
597			    i = 1;
598			    if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
599				    syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m");
600			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
601				(socklen_t *)0);
602			    if (debug)
603				    warnx("accept, ctrl %d", ctrl);
604			    if (ctrl < 0) {
605				    if (errno != EINTR)
606					    syslog(LOG_WARNING,
607						"accept (for %s): %m",
608						sep->se_service);
609                                      if (sep->se_accept &&
610                                          sep->se_socktype == SOCK_STREAM)
611                                              close(ctrl);
612				    continue;
613			    }
614			    i = 0;
615			    if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
616				    syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m");
617			    if (ioctl(ctrl, FIONBIO, &i) < 0)
618				    syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m");
619			    if (cpmip(sep, ctrl) < 0) {
620				close(ctrl);
621				continue;
622			    }
623			    if (dofork &&
624				(conn = search_conn(sep, ctrl)) != NULL &&
625				!room_conn(sep, conn)) {
626				close(ctrl);
627				continue;
628			    }
629		    } else
630			    ctrl = sep->se_fd;
631		    if (log && !ISWRAP(sep)) {
632			    char pname[INET6_ADDRSTRLEN] = "unknown";
633			    socklen_t sl;
634			    sl = sizeof peermax;
635			    if (getpeername(ctrl, (struct sockaddr *)
636					    &peermax, &sl)) {
637				    sl = sizeof peermax;
638				    if (recvfrom(ctrl, buf, sizeof(buf),
639					MSG_PEEK,
640					(struct sockaddr *)&peermax,
641					&sl) >= 0) {
642				      getnameinfo((struct sockaddr *)&peermax,
643						  peer.sa_len,
644						  pname, sizeof(pname),
645						  NULL, 0,
646						  NI_NUMERICHOST|
647						  NI_WITHSCOPEID);
648				    }
649			    } else {
650			            getnameinfo((struct sockaddr *)&peermax,
651						peer.sa_len,
652						pname, sizeof(pname),
653						NULL, 0,
654						NI_NUMERICHOST|
655						NI_WITHSCOPEID);
656			    }
657			    syslog(LOG_INFO,"%s from %s", sep->se_service, pname);
658		    }
659		    (void) sigblock(SIGBLOCK);
660		    pid = 0;
661		    /*
662		     * Fork for all external services, builtins which need to
663		     * fork and anything we're wrapping (as wrapping might
664		     * block or use hosts_options(5) twist).
665		     */
666		    if (dofork) {
667			    if (sep->se_count++ == 0)
668				(void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
669			    else if (toomany > 0 && sep->se_count >= toomany) {
670				struct timeval now;
671
672				(void)gettimeofday(&now, (struct timezone *)NULL);
673				if (now.tv_sec - sep->se_time.tv_sec >
674				    CNT_INTVL) {
675					sep->se_time = now;
676					sep->se_count = 1;
677				} else {
678					syslog(LOG_ERR,
679			"%s/%s server failing (looping), service terminated",
680					    sep->se_service, sep->se_proto);
681					if (sep->se_accept &&
682					    sep->se_socktype == SOCK_STREAM)
683						close(ctrl);
684					close_sep(sep);
685					free_conn(conn);
686					sigsetmask(0L);
687					if (!timingout) {
688						timingout = 1;
689						alarm(RETRYTIME);
690					}
691					continue;
692				}
693			    }
694			    pid = fork();
695		    }
696		    if (pid < 0) {
697			    syslog(LOG_ERR, "fork: %m");
698			    if (sep->se_accept &&
699				sep->se_socktype == SOCK_STREAM)
700				    close(ctrl);
701			    free_conn(conn);
702			    sigsetmask(0L);
703			    sleep(1);
704			    continue;
705		    }
706		    if (pid) {
707			addchild_conn(conn, pid);
708			addchild(sep, pid);
709		    }
710		    sigsetmask(0L);
711		    if (pid == 0) {
712			    if (dofork) {
713				if (debug)
714					warnx("+ closing from %d", maxsock);
715				for (tmpint = maxsock; tmpint > 2; tmpint--)
716					if (tmpint != ctrl)
717						(void) close(tmpint);
718				sigaction(SIGALRM, &saalrm, (struct sigaction *)0);
719				sigaction(SIGCHLD, &sachld, (struct sigaction *)0);
720				sigaction(SIGHUP, &sahup, (struct sigaction *)0);
721				/* SIGPIPE reset before exec */
722			    }
723			    /*
724			     * Call tcpmux to find the real service to exec.
725			     */
726			    if (sep->se_bi &&
727				sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) {
728				    sep = tcpmux(ctrl);
729				    if (sep == NULL) {
730					    close(ctrl);
731					    _exit(0);
732				    }
733			    }
734			    if (ISWRAP(sep)) {
735				inetd_setproctitle("wrapping", ctrl);
736				service = sep->se_server_name ?
737				    sep->se_server_name : sep->se_service;
738				request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, NULL);
739				fromhost(&req);
740				deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
741				allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
742				denied = !hosts_access(&req);
743				if (denied) {
744				    syslog(deny_severity,
745				        "refused connection from %.500s, service %s (%s%s)",
746				        eval_client(&req), service, sep->se_proto,
747					(((struct sockaddr *)req.client->sin)->sa_family == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)req.client->sin)->sin6_addr)) ? "6" : "");
748				    if (sep->se_socktype != SOCK_STREAM)
749					recv(ctrl, buf, sizeof (buf), 0);
750				    if (dofork) {
751					sleep(1);
752					_exit(0);
753				    }
754				}
755				if (log) {
756				    syslog(allow_severity,
757				        "connection from %.500s, service %s (%s%s)",
758					eval_client(&req), service, sep->se_proto,
759					(((struct sockaddr *)req.client->sin)->sa_family == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)req.client->sin)->sin6_addr)) ? "6" : "");
760				}
761			    }
762			    if (sep->se_bi) {
763				(*sep->se_bi->bi_fn)(ctrl, sep);
764			    } else {
765				if (debug)
766					warnx("%d execl %s",
767						getpid(), sep->se_server);
768				dup2(ctrl, 0);
769				close(ctrl);
770				dup2(0, 1);
771				dup2(0, 2);
772				if ((pwd = getpwnam(sep->se_user)) == NULL) {
773					syslog(LOG_ERR,
774					    "%s/%s: %s: no such user",
775						sep->se_service, sep->se_proto,
776						sep->se_user);
777					if (sep->se_socktype != SOCK_STREAM)
778						recv(0, buf, sizeof (buf), 0);
779					_exit(EX_NOUSER);
780				}
781				grp = NULL;
782				if (   sep->se_group != NULL
783				    && (grp = getgrnam(sep->se_group)) == NULL
784				   ) {
785					syslog(LOG_ERR,
786					    "%s/%s: %s: no such group",
787						sep->se_service, sep->se_proto,
788						sep->se_group);
789					if (sep->se_socktype != SOCK_STREAM)
790						recv(0, buf, sizeof (buf), 0);
791					_exit(EX_NOUSER);
792				}
793				if (grp != NULL)
794					pwd->pw_gid = grp->gr_gid;
795#ifdef LOGIN_CAP
796				if ((lc = login_getclass(sep->se_class)) == NULL) {
797					/* error syslogged by getclass */
798					syslog(LOG_ERR,
799					    "%s/%s: %s: login class error",
800						sep->se_service, sep->se_proto,
801						sep->se_class);
802					if (sep->se_socktype != SOCK_STREAM)
803						recv(0, buf, sizeof (buf), 0);
804					_exit(EX_NOUSER);
805				}
806#endif
807				if (setsid() < 0) {
808					syslog(LOG_ERR,
809						"%s: can't setsid(): %m",
810						 sep->se_service);
811					/* _exit(EX_OSERR); not fatal yet */
812				}
813#ifdef LOGIN_CAP
814				if (setusercontext(lc, pwd, pwd->pw_uid,
815				    LOGIN_SETALL) != 0) {
816					syslog(LOG_ERR,
817					 "%s: can't setusercontext(..%s..): %m",
818					 sep->se_service, sep->se_user);
819					_exit(EX_OSERR);
820				}
821#else
822				if (pwd->pw_uid) {
823					if (setlogin(sep->se_user) < 0) {
824						syslog(LOG_ERR,
825						 "%s: can't setlogin(%s): %m",
826						 sep->se_service, sep->se_user);
827						/* _exit(EX_OSERR); not yet */
828					}
829					if (setgid(pwd->pw_gid) < 0) {
830						syslog(LOG_ERR,
831						  "%s: can't set gid %d: %m",
832						  sep->se_service, pwd->pw_gid);
833						_exit(EX_OSERR);
834					}
835					(void) initgroups(pwd->pw_name,
836							pwd->pw_gid);
837					if (setuid(pwd->pw_uid) < 0) {
838						syslog(LOG_ERR,
839						  "%s: can't set uid %d: %m",
840						  sep->se_service, pwd->pw_uid);
841						_exit(EX_OSERR);
842					}
843				}
844#endif
845				sigaction(SIGPIPE, &sapipe,
846				    (struct sigaction *)0);
847				execv(sep->se_server, sep->se_argv);
848				syslog(LOG_ERR,
849				    "cannot execute %s: %m", sep->se_server);
850				if (sep->se_socktype != SOCK_STREAM)
851					recv(0, buf, sizeof (buf), 0);
852			    }
853			    if (dofork)
854				_exit(0);
855		    }
856		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
857			    close(ctrl);
858		}
859	}
860}
861
862/*
863 * Add a signal flag to the signal flag queue for later handling
864 */
865
866void
867flag_signal(int c)
868{
869	char ch = c;
870
871	if (write(signalpipe[1], &ch, 1) != 1) {
872		syslog(LOG_ERR, "write: %m");
873		_exit(EX_OSERR);
874	}
875}
876
877/*
878 * Record a new child pid for this service. If we've reached the
879 * limit on children, then stop accepting incoming requests.
880 */
881
882void
883addchild(struct servtab *sep, pid_t pid)
884{
885	if (sep->se_maxchild <= 0)
886		return;
887#ifdef SANITY_CHECK
888	if (sep->se_numchild >= sep->se_maxchild) {
889		syslog(LOG_ERR, "%s: %d >= %d",
890		    __FUNCTION__, sep->se_numchild, sep->se_maxchild);
891		exit(EX_SOFTWARE);
892	}
893#endif
894	sep->se_pids[sep->se_numchild++] = pid;
895	if (sep->se_numchild == sep->se_maxchild)
896		disable(sep);
897}
898
899/*
900 * Some child process has exited. See if it's on somebody's list.
901 */
902
903void
904flag_reapchild(int signo __unused)
905{
906	flag_signal('C');
907}
908
909void
910reapchild(void)
911{
912	int k, status;
913	pid_t pid;
914	struct servtab *sep;
915
916	for (;;) {
917		pid = wait3(&status, WNOHANG, (struct rusage *)0);
918		if (pid <= 0)
919			break;
920		if (debug)
921			warnx("%d reaped, %s %u", pid,
922			    WIFEXITED(status) ? "status" : "signal",
923			    WIFEXITED(status) ? WEXITSTATUS(status)
924				: WTERMSIG(status));
925		for (sep = servtab; sep; sep = sep->se_next) {
926			for (k = 0; k < sep->se_numchild; k++)
927				if (sep->se_pids[k] == pid)
928					break;
929			if (k == sep->se_numchild)
930				continue;
931			if (sep->se_numchild == sep->se_maxchild)
932				enable(sep);
933			sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
934			if (WIFSIGNALED(status) || WEXITSTATUS(status))
935				syslog(LOG_WARNING,
936				    "%s[%d]: exited, %s %u",
937				    sep->se_server, pid,
938				    WIFEXITED(status) ? "status" : "signal",
939				    WIFEXITED(status) ? WEXITSTATUS(status)
940					: WTERMSIG(status));
941			break;
942		}
943		reapchild_conn(pid);
944	}
945}
946
947void
948flag_config(int signo __unused)
949{
950	flag_signal('H');
951}
952
953void
954config(void)
955{
956	struct servtab *sep, *new, **sepp;
957	long omask;
958	int new_nomapped;
959
960	if (!setconfig()) {
961		syslog(LOG_ERR, "%s: %m", CONFIG);
962		return;
963	}
964	for (sep = servtab; sep; sep = sep->se_next)
965		sep->se_checked = 0;
966	while ((new = getconfigent())) {
967		if (getpwnam(new->se_user) == NULL) {
968			syslog(LOG_ERR,
969				"%s/%s: no such user '%s', service ignored",
970				new->se_service, new->se_proto, new->se_user);
971			continue;
972		}
973		if (new->se_group && getgrnam(new->se_group) == NULL) {
974			syslog(LOG_ERR,
975				"%s/%s: no such group '%s', service ignored",
976				new->se_service, new->se_proto, new->se_group);
977			continue;
978		}
979#ifdef LOGIN_CAP
980		if (login_getclass(new->se_class) == NULL) {
981			/* error syslogged by getclass */
982			syslog(LOG_ERR,
983				"%s/%s: %s: login class error, service ignored",
984				new->se_service, new->se_proto, new->se_class);
985			continue;
986		}
987#endif
988		new_nomapped = new->se_nomapped;
989		for (sep = servtab; sep; sep = sep->se_next)
990			if (strcmp(sep->se_service, new->se_service) == 0 &&
991			    strcmp(sep->se_proto, new->se_proto) == 0 &&
992			    sep->se_rpc == new->se_rpc &&
993			    sep->se_socktype == new->se_socktype &&
994			    sep->se_family == new->se_family)
995				break;
996		if (sep != 0) {
997			int i;
998
999#define SWAP(t,a, b) { t c = a; a = b; b = c; }
1000			omask = sigblock(SIGBLOCK);
1001			if (sep->se_nomapped != new->se_nomapped) {
1002				/* for rpc keep old nommaped till unregister */
1003				if (!sep->se_rpc)
1004					sep->se_nomapped = new->se_nomapped;
1005				sep->se_reset = 1;
1006			}
1007			/* copy over outstanding child pids */
1008			if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
1009				new->se_numchild = sep->se_numchild;
1010				if (new->se_numchild > new->se_maxchild)
1011					new->se_numchild = new->se_maxchild;
1012				memcpy(new->se_pids, sep->se_pids,
1013				    new->se_numchild * sizeof(*new->se_pids));
1014			}
1015			SWAP(pid_t *, sep->se_pids, new->se_pids);
1016			sep->se_maxchild = new->se_maxchild;
1017			sep->se_numchild = new->se_numchild;
1018			sep->se_maxcpm = new->se_maxcpm;
1019			resize_conn(sep, new->se_maxperip);
1020			sep->se_maxperip = new->se_maxperip;
1021			sep->se_bi = new->se_bi;
1022			/* might need to turn on or off service now */
1023			if (sep->se_fd >= 0) {
1024			      if (sep->se_maxchild > 0
1025				  && sep->se_numchild == sep->se_maxchild) {
1026				      if (FD_ISSET(sep->se_fd, &allsock))
1027					  disable(sep);
1028			      } else {
1029				      if (!FD_ISSET(sep->se_fd, &allsock))
1030					  enable(sep);
1031			      }
1032			}
1033			sep->se_accept = new->se_accept;
1034			SWAP(char *, sep->se_user, new->se_user);
1035			SWAP(char *, sep->se_group, new->se_group);
1036#ifdef LOGIN_CAP
1037			SWAP(char *, sep->se_class, new->se_class);
1038#endif
1039			SWAP(char *, sep->se_server, new->se_server);
1040			SWAP(char *, sep->se_server_name, new->se_server_name);
1041			for (i = 0; i < MAXARGV; i++)
1042				SWAP(char *, sep->se_argv[i], new->se_argv[i]);
1043#ifdef IPSEC
1044			SWAP(char *, sep->se_policy, new->se_policy);
1045			ipsecsetup(sep);
1046#endif
1047			sigsetmask(omask);
1048			freeconfig(new);
1049			if (debug)
1050				print_service("REDO", sep);
1051		} else {
1052			sep = enter(new);
1053			if (debug)
1054				print_service("ADD ", sep);
1055		}
1056		sep->se_checked = 1;
1057		if (ISMUX(sep)) {
1058			sep->se_fd = -1;
1059			continue;
1060		}
1061		switch (sep->se_family) {
1062		case AF_INET:
1063			if (!v4bind_ok) {
1064				sep->se_fd = -1;
1065				continue;
1066			}
1067			break;
1068#ifdef INET6
1069		case AF_INET6:
1070			if (!v6bind_ok) {
1071				sep->se_fd = -1;
1072				continue;
1073			}
1074			break;
1075#endif
1076		}
1077		if (!sep->se_rpc) {
1078			if (sep->se_family != AF_UNIX) {
1079				sp = getservbyname(sep->se_service, sep->se_proto);
1080				if (sp == 0) {
1081					syslog(LOG_ERR, "%s/%s: unknown service",
1082					sep->se_service, sep->se_proto);
1083					sep->se_checked = 0;
1084					continue;
1085				}
1086			}
1087			switch (sep->se_family) {
1088			case AF_INET:
1089				if (sp->s_port != sep->se_ctrladdr4.sin_port) {
1090					sep->se_ctrladdr4.sin_port =
1091						sp->s_port;
1092					sep->se_reset = 1;
1093				}
1094				break;
1095#ifdef INET6
1096			case AF_INET6:
1097				if (sp->s_port !=
1098				    sep->se_ctrladdr6.sin6_port) {
1099					sep->se_ctrladdr6.sin6_port =
1100						sp->s_port;
1101					sep->se_reset = 1;
1102				}
1103				break;
1104#endif
1105			}
1106			if (sep->se_reset != 0 && sep->se_fd >= 0)
1107				close_sep(sep);
1108		} else {
1109			rpc = getrpcbyname(sep->se_service);
1110			if (rpc == 0) {
1111				syslog(LOG_ERR, "%s/%s unknown RPC service",
1112					sep->se_service, sep->se_proto);
1113				if (sep->se_fd != -1)
1114					(void) close(sep->se_fd);
1115				sep->se_fd = -1;
1116					continue;
1117			}
1118			if (sep->se_reset != 0 ||
1119			    rpc->r_number != sep->se_rpc_prog) {
1120				if (sep->se_rpc_prog)
1121					unregisterrpc(sep);
1122				sep->se_rpc_prog = rpc->r_number;
1123				if (sep->se_fd != -1)
1124					(void) close(sep->se_fd);
1125				sep->se_fd = -1;
1126			}
1127			sep->se_nomapped = new_nomapped;
1128		}
1129		sep->se_reset = 0;
1130		if (sep->se_fd == -1)
1131			setup(sep);
1132	}
1133	endconfig();
1134	/*
1135	 * Purge anything not looked at above.
1136	 */
1137	omask = sigblock(SIGBLOCK);
1138	sepp = &servtab;
1139	while ((sep = *sepp)) {
1140		if (sep->se_checked) {
1141			sepp = &sep->se_next;
1142			continue;
1143		}
1144		*sepp = sep->se_next;
1145		if (sep->se_fd >= 0)
1146			close_sep(sep);
1147		if (debug)
1148			print_service("FREE", sep);
1149		if (sep->se_rpc && sep->se_rpc_prog > 0)
1150			unregisterrpc(sep);
1151		freeconfig(sep);
1152		free(sep);
1153	}
1154	(void) sigsetmask(omask);
1155}
1156
1157void
1158unregisterrpc(struct servtab *sep)
1159{
1160        u_int i;
1161        struct servtab *sepp;
1162	long omask;
1163	struct netconfig *netid4, *netid6;
1164
1165	omask = sigblock(SIGBLOCK);
1166	netid4 = sep->se_socktype == SOCK_DGRAM ? udpconf : tcpconf;
1167	netid6 = sep->se_socktype == SOCK_DGRAM ? udp6conf : tcp6conf;
1168	if (sep->se_family == AF_INET)
1169		netid6 = NULL;
1170	else if (sep->se_nomapped)
1171		netid4 = NULL;
1172	/*
1173	 * Conflict if same prog and protocol - In that case one should look
1174	 * to versions, but it is not interesting: having separate servers for
1175	 * different versions does not work well.
1176	 * Therefore one do not unregister if there is a conflict.
1177	 * There is also transport conflict if destroying INET when INET46
1178	 * exists, or destroying INET46 when INET exists
1179	 */
1180        for (sepp = servtab; sepp; sepp = sepp->se_next) {
1181                if (sepp == sep)
1182                        continue;
1183		if (sepp->se_checked == 0 ||
1184                    !sepp->se_rpc ||
1185		    strcmp(sep->se_proto, sepp->se_proto) != 0 ||
1186                    sep->se_rpc_prog != sepp->se_rpc_prog)
1187			continue;
1188		if (sepp->se_family == AF_INET)
1189			netid4 = NULL;
1190		if (sepp->se_family == AF_INET6) {
1191			netid6 = NULL;
1192			if (!sep->se_nomapped)
1193				netid4 = NULL;
1194		}
1195		if (netid4 == NULL && netid6 == NULL)
1196			return;
1197        }
1198        if (debug)
1199                print_service("UNREG", sep);
1200        for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1201		if (netid4)
1202			rpcb_unset(sep->se_rpc_prog, i, netid4);
1203		if (netid6)
1204			rpcb_unset(sep->se_rpc_prog, i, netid6);
1205	}
1206        if (sep->se_fd != -1)
1207                (void) close(sep->se_fd);
1208        sep->se_fd = -1;
1209	(void) sigsetmask(omask);
1210}
1211
1212void
1213flag_retry(int signo __unused)
1214{
1215	flag_signal('A');
1216}
1217
1218void
1219retry(void)
1220{
1221	struct servtab *sep;
1222
1223	timingout = 0;
1224	for (sep = servtab; sep; sep = sep->se_next)
1225		if (sep->se_fd == -1 && !ISMUX(sep))
1226			setup(sep);
1227}
1228
1229void
1230setup(struct servtab *sep)
1231{
1232	int on = 1;
1233
1234	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1235		if (debug)
1236			warn("socket failed on %s/%s",
1237				sep->se_service, sep->se_proto);
1238		syslog(LOG_ERR, "%s/%s: socket: %m",
1239		    sep->se_service, sep->se_proto);
1240		return;
1241	}
1242#define	turnon(fd, opt) \
1243setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1244	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1245	    turnon(sep->se_fd, SO_DEBUG) < 0)
1246		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1247	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1248		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1249#ifdef SO_PRIVSTATE
1250	if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1251		syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1252#endif
1253	/* tftpd opens a new connection then needs more infos */
1254	if ((sep->se_family == AF_INET6) &&
1255	    (strcmp(sep->se_proto, "udp") == 0) &&
1256	    (sep->se_accept == 0) &&
1257	    (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO,
1258			(char *)&on, sizeof (on)) < 0))
1259		syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
1260	if (sep->se_family == AF_INET6) {
1261		int flag = sep->se_nomapped ? 1 : 0;
1262		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY,
1263			       (char *)&flag, sizeof (flag)) < 0)
1264			syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m");
1265	}
1266#undef turnon
1267	if (sep->se_type == TTCP_TYPE)
1268		if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1269		    (char *)&on, sizeof (on)) < 0)
1270			syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1271#ifdef IPV6_FAITH
1272	if (sep->se_type == FAITH_TYPE) {
1273		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
1274				sizeof(on)) < 0) {
1275			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1276		}
1277	}
1278#endif
1279#ifdef IPSEC
1280	ipsecsetup(sep);
1281#endif
1282	if (sep->se_family == AF_UNIX) {
1283		(void) unlink(sep->se_ctrladdr_un.sun_path);
1284		umask(0777); /* Make socket with conservative permissions */
1285	}
1286	if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1287	    sep->se_ctrladdr_size) < 0) {
1288		if (debug)
1289			warn("bind failed on %s/%s",
1290				sep->se_service, sep->se_proto);
1291		syslog(LOG_ERR, "%s/%s: bind: %m",
1292		    sep->se_service, sep->se_proto);
1293		(void) close(sep->se_fd);
1294		sep->se_fd = -1;
1295		if (!timingout) {
1296			timingout = 1;
1297			alarm(RETRYTIME);
1298		}
1299		if (sep->se_family == AF_UNIX)
1300			umask(mask);
1301		return;
1302	}
1303	if (sep->se_family == AF_UNIX) {
1304		/* Ick - fch{own,mod} don't work on Unix domain sockets */
1305		if (chown(sep->se_service, sep->se_sockuid, sep->se_sockgid) < 0)
1306			syslog(LOG_ERR, "chown socket: %m");
1307		if (chmod(sep->se_service, sep->se_sockmode) < 0)
1308			syslog(LOG_ERR, "chmod socket: %m");
1309		umask(mask);
1310	}
1311        if (sep->se_rpc) {
1312		u_int i;
1313		socklen_t len = sep->se_ctrladdr_size;
1314		struct netconfig *netid, *netid2 = NULL;
1315		struct sockaddr_in sock;
1316		struct netbuf nbuf, nbuf2;
1317
1318                if (getsockname(sep->se_fd,
1319				(struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1320                        syslog(LOG_ERR, "%s/%s: getsockname: %m",
1321                               sep->se_service, sep->se_proto);
1322                        (void) close(sep->se_fd);
1323                        sep->se_fd = -1;
1324                        return;
1325                }
1326		nbuf.buf = &sep->se_ctrladdr;
1327		nbuf.len = sep->se_ctrladdr.sa_len;
1328		if (sep->se_family == AF_INET)
1329			netid = sep->se_socktype==SOCK_DGRAM? udpconf:tcpconf;
1330		else  {
1331			netid = sep->se_socktype==SOCK_DGRAM? udp6conf:tcp6conf;
1332			if (!sep->se_nomapped) { /* INET and INET6 */
1333				netid2 = netid==udp6conf? udpconf:tcpconf;
1334				memset(&sock, 0, sizeof sock);	/* ADDR_ANY */
1335				nbuf2.buf = &sock;
1336				nbuf2.len = sock.sin_len = sizeof sock;
1337				sock.sin_family = AF_INET;
1338				sock.sin_port = sep->se_ctrladdr6.sin6_port;
1339			}
1340		}
1341                if (debug)
1342                        print_service("REG ", sep);
1343                for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1344			rpcb_unset(sep->se_rpc_prog, i, netid);
1345			rpcb_set(sep->se_rpc_prog, i, netid, &nbuf);
1346			if (netid2) {
1347				rpcb_unset(sep->se_rpc_prog, i, netid2);
1348				rpcb_set(sep->se_rpc_prog, i, netid2, &nbuf2);
1349			}
1350                }
1351        }
1352	if (sep->se_socktype == SOCK_STREAM)
1353		listen(sep->se_fd, 64);
1354	enable(sep);
1355	if (debug) {
1356		warnx("registered %s on %d",
1357			sep->se_server, sep->se_fd);
1358	}
1359}
1360
1361#ifdef IPSEC
1362void
1363ipsecsetup(sep)
1364	struct servtab *sep;
1365{
1366	char *buf;
1367	char *policy_in = NULL;
1368	char *policy_out = NULL;
1369	int level;
1370	int opt;
1371
1372	switch (sep->se_family) {
1373	case AF_INET:
1374		level = IPPROTO_IP;
1375		opt = IP_IPSEC_POLICY;
1376		break;
1377#ifdef INET6
1378	case AF_INET6:
1379		level = IPPROTO_IPV6;
1380		opt = IPV6_IPSEC_POLICY;
1381		break;
1382#endif
1383	default:
1384		return;
1385	}
1386
1387	if (!sep->se_policy || sep->se_policy[0] == '\0') {
1388		static char def_in[] = "in entrust", def_out[] = "out entrust";
1389		policy_in = def_in;
1390		policy_out = def_out;
1391	} else {
1392		if (!strncmp("in", sep->se_policy, 2))
1393			policy_in = sep->se_policy;
1394		else if (!strncmp("out", sep->se_policy, 3))
1395			policy_out = sep->se_policy;
1396		else {
1397			syslog(LOG_ERR, "invalid security policy \"%s\"",
1398				sep->se_policy);
1399			return;
1400		}
1401	}
1402
1403	if (policy_in != NULL) {
1404		buf = ipsec_set_policy(policy_in, strlen(policy_in));
1405		if (buf != NULL) {
1406			if (setsockopt(sep->se_fd, level, opt,
1407					buf, ipsec_get_policylen(buf)) < 0 &&
1408			    debug != 0)
1409				warnx("%s/%s: ipsec initialization failed; %s",
1410				      sep->se_service, sep->se_proto,
1411				      policy_in);
1412			free(buf);
1413		} else
1414			syslog(LOG_ERR, "invalid security policy \"%s\"",
1415				policy_in);
1416	}
1417	if (policy_out != NULL) {
1418		buf = ipsec_set_policy(policy_out, strlen(policy_out));
1419		if (buf != NULL) {
1420			if (setsockopt(sep->se_fd, level, opt,
1421					buf, ipsec_get_policylen(buf)) < 0 &&
1422			    debug != 0)
1423				warnx("%s/%s: ipsec initialization failed; %s",
1424				      sep->se_service, sep->se_proto,
1425				      policy_out);
1426			free(buf);
1427		} else
1428			syslog(LOG_ERR, "invalid security policy \"%s\"",
1429				policy_out);
1430	}
1431}
1432#endif
1433
1434/*
1435 * Finish with a service and its socket.
1436 */
1437void
1438close_sep(struct servtab *sep)
1439{
1440	if (sep->se_fd >= 0) {
1441		if (FD_ISSET(sep->se_fd, &allsock))
1442			disable(sep);
1443		(void) close(sep->se_fd);
1444		sep->se_fd = -1;
1445	}
1446	sep->se_count = 0;
1447	sep->se_numchild = 0;	/* forget about any existing children */
1448}
1449
1450int
1451matchservent(const char *name1, const char *name2, const char *proto)
1452{
1453	char **alias, *p;
1454	struct servent *se;
1455
1456	if (strcmp(proto, "unix") == 0) {
1457		if ((p = strrchr(name1, '/')) != NULL)
1458			name1 = p + 1;
1459		if ((p = strrchr(name2, '/')) != NULL)
1460			name2 = p + 1;
1461	}
1462	if (strcmp(name1, name2) == 0)
1463		return(1);
1464	if ((se = getservbyname(name1, proto)) != NULL) {
1465		if (strcmp(name2, se->s_name) == 0)
1466			return(1);
1467		for (alias = se->s_aliases; *alias; alias++)
1468			if (strcmp(name2, *alias) == 0)
1469				return(1);
1470	}
1471	return(0);
1472}
1473
1474struct servtab *
1475enter(struct servtab *cp)
1476{
1477	struct servtab *sep;
1478	long omask;
1479
1480	sep = (struct servtab *)malloc(sizeof (*sep));
1481	if (sep == (struct servtab *)0) {
1482		syslog(LOG_ERR, "malloc: %m");
1483		exit(EX_OSERR);
1484	}
1485	*sep = *cp;
1486	sep->se_fd = -1;
1487	omask = sigblock(SIGBLOCK);
1488	sep->se_next = servtab;
1489	servtab = sep;
1490	sigsetmask(omask);
1491	return (sep);
1492}
1493
1494void
1495enable(struct servtab *sep)
1496{
1497	if (debug)
1498		warnx(
1499		    "enabling %s, fd %d", sep->se_service, sep->se_fd);
1500#ifdef SANITY_CHECK
1501	if (sep->se_fd < 0) {
1502		syslog(LOG_ERR,
1503		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1504		exit(EX_SOFTWARE);
1505	}
1506	if (ISMUX(sep)) {
1507		syslog(LOG_ERR,
1508		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1509		exit(EX_SOFTWARE);
1510	}
1511	if (FD_ISSET(sep->se_fd, &allsock)) {
1512		syslog(LOG_ERR,
1513		    "%s: %s: not off", __FUNCTION__, sep->se_service);
1514		exit(EX_SOFTWARE);
1515	}
1516	nsock++;
1517#endif
1518	FD_SET(sep->se_fd, &allsock);
1519	if (sep->se_fd > maxsock)
1520		maxsock = sep->se_fd;
1521}
1522
1523void
1524disable(struct servtab *sep)
1525{
1526	if (debug)
1527		warnx(
1528		    "disabling %s, fd %d", sep->se_service, sep->se_fd);
1529#ifdef SANITY_CHECK
1530	if (sep->se_fd < 0) {
1531		syslog(LOG_ERR,
1532		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1533		exit(EX_SOFTWARE);
1534	}
1535	if (ISMUX(sep)) {
1536		syslog(LOG_ERR,
1537		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1538		exit(EX_SOFTWARE);
1539	}
1540	if (!FD_ISSET(sep->se_fd, &allsock)) {
1541		syslog(LOG_ERR,
1542		    "%s: %s: not on", __FUNCTION__, sep->se_service);
1543		exit(EX_SOFTWARE);
1544	}
1545	if (nsock == 0) {
1546		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
1547		exit(EX_SOFTWARE);
1548	}
1549	nsock--;
1550#endif
1551	FD_CLR(sep->se_fd, &allsock);
1552	if (sep->se_fd == maxsock)
1553		maxsock--;
1554}
1555
1556FILE	*fconfig = NULL;
1557struct	servtab serv;
1558char	line[LINE_MAX];
1559
1560int
1561setconfig(void)
1562{
1563
1564	if (fconfig != NULL) {
1565		fseek(fconfig, 0L, SEEK_SET);
1566		return (1);
1567	}
1568	fconfig = fopen(CONFIG, "r");
1569	return (fconfig != NULL);
1570}
1571
1572void
1573endconfig(void)
1574{
1575	if (fconfig) {
1576		(void) fclose(fconfig);
1577		fconfig = NULL;
1578	}
1579}
1580
1581struct servtab *
1582getconfigent(void)
1583{
1584	struct servtab *sep = &serv;
1585	int argc;
1586	char *cp, *arg, *s;
1587	char *versp;
1588	static char TCPMUX_TOKEN[] = "tcpmux/";
1589#define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1590#ifdef IPSEC
1591	char *policy;
1592#endif
1593	int v4bind;
1594#ifdef INET6
1595	int v6bind;
1596#endif
1597	int i;
1598
1599#ifdef IPSEC
1600	policy = NULL;
1601#endif
1602more:
1603	v4bind = 0;
1604#ifdef INET6
1605	v6bind = 0;
1606#endif
1607	while ((cp = nextline(fconfig)) != NULL) {
1608#ifdef IPSEC
1609		/* lines starting with #@ is not a comment, but the policy */
1610		if (cp[0] == '#' && cp[1] == '@') {
1611			char *p;
1612			for (p = cp + 2; p && *p && isspace(*p); p++)
1613				;
1614			if (*p == '\0') {
1615				if (policy)
1616					free(policy);
1617				policy = NULL;
1618			} else if (ipsec_get_policylen(p) >= 0) {
1619				if (policy)
1620					free(policy);
1621				policy = newstr(p);
1622			} else {
1623				syslog(LOG_ERR,
1624					"%s: invalid ipsec policy \"%s\"",
1625					CONFIG, p);
1626				exit(EX_CONFIG);
1627			}
1628		}
1629#endif
1630		if (*cp == '#' || *cp == '\0')
1631			continue;
1632		break;
1633	}
1634	if (cp == NULL)
1635		return ((struct servtab *)0);
1636	/*
1637	 * clear the static buffer, since some fields (se_ctrladdr,
1638	 * for example) don't get initialized here.
1639	 */
1640	memset(sep, 0, sizeof *sep);
1641	arg = skip(&cp);
1642	if (cp == NULL) {
1643		/* got an empty line containing just blanks/tabs. */
1644		goto more;
1645	}
1646	if (arg[0] == ':') { /* :user:group:perm: */
1647		char *user, *group, *perm;
1648		struct passwd *pw;
1649		struct group *gr;
1650		user = arg+1;
1651		if ((group = strchr(user, ':')) == NULL) {
1652			syslog(LOG_ERR, "no group after user '%s'", user);
1653			goto more;
1654		}
1655		*group++ = '\0';
1656		if ((perm = strchr(group, ':')) == NULL) {
1657			syslog(LOG_ERR, "no mode after group '%s'", group);
1658			goto more;
1659		}
1660		*perm++ = '\0';
1661		if ((pw = getpwnam(user)) == NULL) {
1662			syslog(LOG_ERR, "no such user '%s'", user);
1663			goto more;
1664		}
1665		sep->se_sockuid = pw->pw_uid;
1666		if ((gr = getgrnam(group)) == NULL) {
1667			syslog(LOG_ERR, "no such user '%s'", group);
1668			goto more;
1669		}
1670		sep->se_sockgid = gr->gr_gid;
1671		sep->se_sockmode = strtol(perm, &arg, 8);
1672		if (*arg != ':') {
1673			syslog(LOG_ERR, "bad mode '%s'", perm);
1674			goto more;
1675		}
1676		*arg++ = '\0';
1677	} else {
1678		sep->se_sockuid = euid;
1679		sep->se_sockgid = egid;
1680		sep->se_sockmode = 0200;
1681	}
1682	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1683		char *c = arg + MUX_LEN;
1684		if (*c == '+') {
1685			sep->se_type = MUXPLUS_TYPE;
1686			c++;
1687		} else
1688			sep->se_type = MUX_TYPE;
1689		sep->se_service = newstr(c);
1690	} else {
1691		sep->se_service = newstr(arg);
1692		sep->se_type = NORM_TYPE;
1693	}
1694	arg = sskip(&cp);
1695	if (strcmp(arg, "stream") == 0)
1696		sep->se_socktype = SOCK_STREAM;
1697	else if (strcmp(arg, "dgram") == 0)
1698		sep->se_socktype = SOCK_DGRAM;
1699	else if (strcmp(arg, "rdm") == 0)
1700		sep->se_socktype = SOCK_RDM;
1701	else if (strcmp(arg, "seqpacket") == 0)
1702		sep->se_socktype = SOCK_SEQPACKET;
1703	else if (strcmp(arg, "raw") == 0)
1704		sep->se_socktype = SOCK_RAW;
1705	else
1706		sep->se_socktype = -1;
1707
1708	arg = sskip(&cp);
1709	if (strncmp(arg, "tcp", 3) == 0) {
1710		sep->se_proto = newstr(strsep(&arg, "/"));
1711		if (arg != NULL) {
1712			if (strcmp(arg, "ttcp") == 0)
1713				sep->se_type = TTCP_TYPE;
1714			else if (strcmp(arg, "faith") == 0)
1715				sep->se_type = FAITH_TYPE;
1716		}
1717	} else {
1718		if (sep->se_type == NORM_TYPE &&
1719		    strncmp(arg, "faith/", 6) == 0) {
1720			arg += 6;
1721			sep->se_type = FAITH_TYPE;
1722		}
1723		sep->se_proto = newstr(arg);
1724	}
1725        if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1726                memmove(sep->se_proto, sep->se_proto + 4,
1727                    strlen(sep->se_proto) + 1 - 4);
1728                sep->se_rpc = 1;
1729                sep->se_rpc_prog = sep->se_rpc_lowvers =
1730			sep->se_rpc_lowvers = 0;
1731		memcpy(&sep->se_ctrladdr4, bind_sa4,
1732		       sizeof(sep->se_ctrladdr4));
1733                if ((versp = rindex(sep->se_service, '/'))) {
1734                        *versp++ = '\0';
1735                        switch (sscanf(versp, "%u-%u",
1736                                       &sep->se_rpc_lowvers,
1737                                       &sep->se_rpc_highvers)) {
1738                        case 2:
1739                                break;
1740                        case 1:
1741                                sep->se_rpc_highvers =
1742                                        sep->se_rpc_lowvers;
1743                                break;
1744                        default:
1745                                syslog(LOG_ERR,
1746					"bad RPC version specifier; %s",
1747					sep->se_service);
1748                                freeconfig(sep);
1749                                goto more;
1750                        }
1751                }
1752                else {
1753                        sep->se_rpc_lowvers =
1754                                sep->se_rpc_highvers = 1;
1755                }
1756        }
1757	sep->se_nomapped = 0;
1758	if (strcmp(sep->se_proto, "unix") == 0) {
1759	        sep->se_family = AF_UNIX;
1760	} else {
1761		while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
1762#ifdef INET6
1763			if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
1764				sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1765				v6bind = 1;
1766				continue;
1767			}
1768#endif
1769			if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
1770				sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1771				v4bind = 1;
1772				continue;
1773			}
1774			/* illegal version num */
1775			syslog(LOG_ERR,	"bad IP version for %s", sep->se_proto);
1776			freeconfig(sep);
1777			goto more;
1778		}
1779#ifdef INET6
1780		if (v6bind && !v6bind_ok) {
1781			syslog(LOG_INFO, "IPv6 bind is ignored for %s",
1782			       sep->se_service);
1783			if (v4bind && v4bind_ok)
1784				v6bind = 0;
1785			else {
1786				freeconfig(sep);
1787				goto more;
1788			}
1789		}
1790		if (v6bind) {
1791			sep->se_family = AF_INET6;
1792			if (!v4bind || !v4bind_ok)
1793				sep->se_nomapped = 1;
1794		} else
1795#endif
1796		{ /* default to v4 bind if not v6 bind */
1797			if (!v4bind_ok) {
1798				syslog(LOG_NOTICE, "IPv4 bind is ignored for %s",
1799				       sep->se_service);
1800				freeconfig(sep);
1801				goto more;
1802			}
1803			sep->se_family = AF_INET;
1804		}
1805	}
1806	/* init ctladdr */
1807	switch(sep->se_family) {
1808	case AF_INET:
1809		memcpy(&sep->se_ctrladdr4, bind_sa4,
1810		       sizeof(sep->se_ctrladdr4));
1811		sep->se_ctrladdr_size =	sizeof(sep->se_ctrladdr4);
1812		break;
1813#ifdef INET6
1814	case AF_INET6:
1815		memcpy(&sep->se_ctrladdr6, bind_sa6,
1816		       sizeof(sep->se_ctrladdr6));
1817		sep->se_ctrladdr_size =	sizeof(sep->se_ctrladdr6);
1818		break;
1819#endif
1820	case AF_UNIX:
1821		if (strlen(sep->se_service) >= sizeof(sep->se_ctrladdr_un.sun_path)) {
1822			syslog(LOG_ERR,
1823			    "domain socket pathname too long for service %s",
1824			    sep->se_service);
1825			goto more;
1826		}
1827		memset(&sep->se_ctrladdr, 0, sizeof(sep->se_ctrladdr));
1828		sep->se_ctrladdr_un.sun_family = sep->se_family;
1829		sep->se_ctrladdr_un.sun_len = strlen(sep->se_service);
1830		strcpy(sep->se_ctrladdr_un.sun_path, sep->se_service);
1831		sep->se_ctrladdr_size = SUN_LEN(&sep->se_ctrladdr_un);
1832	}
1833	arg = sskip(&cp);
1834	if (!strncmp(arg, "wait", 4))
1835		sep->se_accept = 0;
1836	else if (!strncmp(arg, "nowait", 6))
1837		sep->se_accept = 1;
1838	else {
1839		syslog(LOG_ERR,
1840			"%s: bad wait/nowait for service %s",
1841			CONFIG, sep->se_service);
1842		goto more;
1843	}
1844	sep->se_maxchild = -1;
1845	sep->se_maxcpm = -1;
1846	sep->se_maxperip = -1;
1847	if ((s = strchr(arg, '/')) != NULL) {
1848		char *eptr;
1849		u_long val;
1850
1851		val = strtoul(s + 1, &eptr, 10);
1852		if (eptr == s + 1 || val > MAX_MAXCHLD) {
1853			syslog(LOG_ERR,
1854				"%s: bad max-child for service %s",
1855				CONFIG, sep->se_service);
1856			goto more;
1857		}
1858		if (debug)
1859			if (!sep->se_accept && val != 1)
1860				warnx("maxchild=%lu for wait service %s"
1861				    " not recommended", val, sep->se_service);
1862		sep->se_maxchild = val;
1863		if (*eptr == '/')
1864			sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1865		if (*eptr == '/')
1866			sep->se_maxperip = strtol(eptr + 1, &eptr, 10);
1867		/*
1868		 * explicitly do not check for \0 for future expansion /
1869		 * backwards compatibility
1870		 */
1871	}
1872	if (ISMUX(sep)) {
1873		/*
1874		 * Silently enforce "nowait" mode for TCPMUX services
1875		 * since they don't have an assigned port to listen on.
1876		 */
1877		sep->se_accept = 1;
1878		if (strcmp(sep->se_proto, "tcp")) {
1879			syslog(LOG_ERR,
1880				"%s: bad protocol for tcpmux service %s",
1881				CONFIG, sep->se_service);
1882			goto more;
1883		}
1884		if (sep->se_socktype != SOCK_STREAM) {
1885			syslog(LOG_ERR,
1886				"%s: bad socket type for tcpmux service %s",
1887				CONFIG, sep->se_service);
1888			goto more;
1889		}
1890	}
1891	sep->se_user = newstr(sskip(&cp));
1892#ifdef LOGIN_CAP
1893	if ((s = strrchr(sep->se_user, '/')) != NULL) {
1894		*s = '\0';
1895		sep->se_class = newstr(s + 1);
1896	} else
1897		sep->se_class = newstr(RESOURCE_RC);
1898#endif
1899	if ((s = strrchr(sep->se_user, ':')) != NULL) {
1900		*s = '\0';
1901		sep->se_group = newstr(s + 1);
1902	} else
1903		sep->se_group = NULL;
1904	sep->se_server = newstr(sskip(&cp));
1905	if ((sep->se_server_name = rindex(sep->se_server, '/')))
1906		sep->se_server_name++;
1907	if (strcmp(sep->se_server, "internal") == 0) {
1908		struct biltin *bi;
1909
1910		for (bi = biltins; bi->bi_service; bi++)
1911			if (bi->bi_socktype == sep->se_socktype &&
1912			    matchservent(bi->bi_service, sep->se_service,
1913			    sep->se_proto))
1914				break;
1915		if (bi->bi_service == 0) {
1916			syslog(LOG_ERR, "internal service %s unknown",
1917				sep->se_service);
1918			goto more;
1919		}
1920		sep->se_accept = 1;	/* force accept mode for built-ins */
1921		sep->se_bi = bi;
1922	} else
1923		sep->se_bi = NULL;
1924	if (sep->se_maxperip < 0)
1925		sep->se_maxperip = maxperip;
1926	if (sep->se_maxcpm < 0)
1927		sep->se_maxcpm = maxcpm;
1928	if (sep->se_maxchild < 0) {	/* apply default max-children */
1929		if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1930			sep->se_maxchild = sep->se_bi->bi_maxchild;
1931		else if (sep->se_accept)
1932			sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1933		else
1934			sep->se_maxchild = 1;
1935	}
1936	if (sep->se_maxchild > 0) {
1937		sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1938		if (sep->se_pids == NULL) {
1939			syslog(LOG_ERR, "malloc: %m");
1940			exit(EX_OSERR);
1941		}
1942	}
1943	argc = 0;
1944	for (arg = skip(&cp); cp; arg = skip(&cp))
1945		if (argc < MAXARGV) {
1946			sep->se_argv[argc++] = newstr(arg);
1947		} else {
1948			syslog(LOG_ERR,
1949				"%s: too many arguments for service %s",
1950				CONFIG, sep->se_service);
1951			goto more;
1952		}
1953	while (argc <= MAXARGV)
1954		sep->se_argv[argc++] = NULL;
1955	for (i = 0; i < PERIPSIZE; ++i)
1956		LIST_INIT(&sep->se_conn[i]);
1957#ifdef IPSEC
1958	sep->se_policy = policy ? newstr(policy) : NULL;
1959#endif
1960	return (sep);
1961}
1962
1963void
1964freeconfig(struct servtab *cp)
1965{
1966	int i;
1967
1968	if (cp->se_service)
1969		free(cp->se_service);
1970	if (cp->se_proto)
1971		free(cp->se_proto);
1972	if (cp->se_user)
1973		free(cp->se_user);
1974	if (cp->se_group)
1975		free(cp->se_group);
1976#ifdef LOGIN_CAP
1977	if (cp->se_class)
1978		free(cp->se_class);
1979#endif
1980	if (cp->se_server)
1981		free(cp->se_server);
1982	if (cp->se_pids)
1983		free(cp->se_pids);
1984	for (i = 0; i < MAXARGV; i++)
1985		if (cp->se_argv[i])
1986			free(cp->se_argv[i]);
1987	free_connlist(cp);
1988#ifdef IPSEC
1989	if (cp->se_policy)
1990		free(cp->se_policy);
1991#endif
1992}
1993
1994
1995/*
1996 * Safe skip - if skip returns null, log a syntax error in the
1997 * configuration file and exit.
1998 */
1999char *
2000sskip(char **cpp)
2001{
2002	char *cp;
2003
2004	cp = skip(cpp);
2005	if (cp == NULL) {
2006		syslog(LOG_ERR, "%s: syntax error", CONFIG);
2007		exit(EX_DATAERR);
2008	}
2009	return (cp);
2010}
2011
2012char *
2013skip(char **cpp)
2014{
2015	char *cp = *cpp;
2016	char *start;
2017	char quote = '\0';
2018
2019again:
2020	while (*cp == ' ' || *cp == '\t')
2021		cp++;
2022	if (*cp == '\0') {
2023		int c;
2024
2025		c = getc(fconfig);
2026		(void) ungetc(c, fconfig);
2027		if (c == ' ' || c == '\t')
2028			if ((cp = nextline(fconfig)))
2029				goto again;
2030		*cpp = (char *)0;
2031		return ((char *)0);
2032	}
2033	if (*cp == '"' || *cp == '\'')
2034		quote = *cp++;
2035	start = cp;
2036	if (quote)
2037		while (*cp && *cp != quote)
2038			cp++;
2039	else
2040		while (*cp && *cp != ' ' && *cp != '\t')
2041			cp++;
2042	if (*cp != '\0')
2043		*cp++ = '\0';
2044	*cpp = cp;
2045	return (start);
2046}
2047
2048char *
2049nextline(FILE *fd)
2050{
2051	char *cp;
2052
2053	if (fgets(line, sizeof (line), fd) == NULL)
2054		return ((char *)0);
2055	cp = strchr(line, '\n');
2056	if (cp)
2057		*cp = '\0';
2058	return (line);
2059}
2060
2061char *
2062newstr(const char *cp)
2063{
2064	char *cr;
2065
2066	if ((cr = strdup(cp != NULL ? cp : "")))
2067		return (cr);
2068	syslog(LOG_ERR, "strdup: %m");
2069	exit(EX_OSERR);
2070}
2071
2072void
2073inetd_setproctitle(const char *a, int s)
2074{
2075	socklen_t size;
2076	struct sockaddr_storage ss;
2077	char buf[80], pbuf[INET6_ADDRSTRLEN];
2078
2079	size = sizeof(ss);
2080	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
2081		getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
2082			    NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
2083		(void) sprintf(buf, "%s [%s]", a, pbuf);
2084	} else
2085		(void) sprintf(buf, "%s", a);
2086	setproctitle("%s", buf);
2087}
2088
2089int
2090check_loop(const struct sockaddr *sa, const struct servtab *sep)
2091{
2092	struct servtab *se2;
2093	char pname[INET6_ADDRSTRLEN];
2094
2095	for (se2 = servtab; se2; se2 = se2->se_next) {
2096		if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
2097			continue;
2098
2099		switch (se2->se_family) {
2100		case AF_INET:
2101			if (((const struct sockaddr_in *)sa)->sin_port ==
2102			    se2->se_ctrladdr4.sin_port)
2103				goto isloop;
2104			continue;
2105#ifdef INET6
2106		case AF_INET6:
2107			if (((const struct sockaddr_in *)sa)->sin_port ==
2108			    se2->se_ctrladdr4.sin_port)
2109				goto isloop;
2110			continue;
2111#endif
2112		default:
2113			continue;
2114		}
2115	isloop:
2116		getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
2117			    NI_NUMERICHOST|NI_WITHSCOPEID);
2118		syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
2119		       sep->se_service, sep->se_proto,
2120		       se2->se_service, se2->se_proto,
2121		       pname);
2122		return 1;
2123	}
2124	return 0;
2125}
2126
2127/*
2128 * print_service:
2129 *	Dump relevant information to stderr
2130 */
2131void
2132print_service(const char *action, const struct servtab *sep)
2133{
2134	fprintf(stderr,
2135	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2136#ifdef LOGIN_CAP
2137	    "class=%s"
2138#endif
2139	    " builtin=%p server=%s"
2140#ifdef IPSEC
2141	    " policy=\"%s\""
2142#endif
2143	    "\n",
2144	    action, sep->se_service, sep->se_proto,
2145	    sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
2146#ifdef LOGIN_CAP
2147	    sep->se_class,
2148#endif
2149	    (void *) sep->se_bi, sep->se_server
2150#ifdef IPSEC
2151	    , (sep->se_policy ? sep->se_policy : "")
2152#endif
2153	    );
2154}
2155
2156#define CPMHSIZE	256
2157#define CPMHMASK	(CPMHSIZE-1)
2158#define CHTGRAN		10
2159#define CHTSIZE		6
2160
2161typedef struct CTime {
2162	unsigned long 	ct_Ticks;
2163	int		ct_Count;
2164} CTime;
2165
2166typedef struct CHash {
2167	union {
2168		struct in_addr	c4_Addr;
2169		struct in6_addr	c6_Addr;
2170	} cu_Addr;
2171#define	ch_Addr4	cu_Addr.c4_Addr
2172#define	ch_Addr6	cu_Addr.c6_Addr
2173	int		ch_Family;
2174	time_t		ch_LTime;
2175	char		*ch_Service;
2176	CTime		ch_Times[CHTSIZE];
2177} CHash;
2178
2179CHash	CHashAry[CPMHSIZE];
2180
2181int
2182cpmip(const struct servtab *sep, int ctrl)
2183{
2184	struct sockaddr_storage rss;
2185	socklen_t rssLen = sizeof(rss);
2186	int r = 0;
2187
2188	/*
2189	 * If getpeername() fails, just let it through (if logging is
2190	 * enabled the condition is caught elsewhere)
2191	 */
2192
2193	if (sep->se_maxcpm > 0 &&
2194	    getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
2195		time_t t = time(NULL);
2196		int hv = 0xABC3D20F;
2197		int i;
2198		int cnt = 0;
2199		CHash *chBest = NULL;
2200		unsigned int ticks = t / CHTGRAN;
2201		struct sockaddr_in *sin4;
2202#ifdef INET6
2203		struct sockaddr_in6 *sin6;
2204#endif
2205
2206		sin4 = (struct sockaddr_in *)&rss;
2207#ifdef INET6
2208		sin6 = (struct sockaddr_in6 *)&rss;
2209#endif
2210		{
2211			char *p;
2212			int addrlen;
2213
2214			switch (rss.ss_family) {
2215			case AF_INET:
2216				p = (char *)&sin4->sin_addr;
2217				addrlen = sizeof(struct in_addr);
2218				break;
2219#ifdef INET6
2220			case AF_INET6:
2221				p = (char *)&sin6->sin6_addr;
2222				addrlen = sizeof(struct in6_addr);
2223				break;
2224#endif
2225			default:
2226				/* should not happen */
2227				return -1;
2228			}
2229
2230			for (i = 0; i < addrlen; ++i, ++p) {
2231				hv = (hv << 5) ^ (hv >> 23) ^ *p;
2232			}
2233			hv = (hv ^ (hv >> 16));
2234		}
2235		for (i = 0; i < 5; ++i) {
2236			CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2237
2238			if (rss.ss_family == AF_INET &&
2239			    ch->ch_Family == AF_INET &&
2240			    sin4->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
2241			    ch->ch_Service && strcmp(sep->se_service,
2242			    ch->ch_Service) == 0) {
2243				chBest = ch;
2244				break;
2245			}
2246#ifdef INET6
2247			if (rss.ss_family == AF_INET6 &&
2248			    ch->ch_Family == AF_INET6 &&
2249			    IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2250					       &ch->ch_Addr6) != 0 &&
2251			    ch->ch_Service && strcmp(sep->se_service,
2252			    ch->ch_Service) == 0) {
2253				chBest = ch;
2254				break;
2255			}
2256#endif
2257			if (chBest == NULL || ch->ch_LTime == 0 ||
2258			    ch->ch_LTime < chBest->ch_LTime) {
2259				chBest = ch;
2260			}
2261		}
2262		if ((rss.ss_family == AF_INET &&
2263		     (chBest->ch_Family != AF_INET ||
2264		      sin4->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
2265		    chBest->ch_Service == NULL ||
2266		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2267			chBest->ch_Family = sin4->sin_family;
2268			chBest->ch_Addr4 = sin4->sin_addr;
2269			if (chBest->ch_Service)
2270				free(chBest->ch_Service);
2271			chBest->ch_Service = strdup(sep->se_service);
2272			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2273		}
2274#ifdef INET6
2275		if ((rss.ss_family == AF_INET6 &&
2276		     (chBest->ch_Family != AF_INET6 ||
2277		      IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2278					 &chBest->ch_Addr6) == 0)) ||
2279		    chBest->ch_Service == NULL ||
2280		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2281			chBest->ch_Family = sin6->sin6_family;
2282			chBest->ch_Addr6 = sin6->sin6_addr;
2283			if (chBest->ch_Service)
2284				free(chBest->ch_Service);
2285			chBest->ch_Service = strdup(sep->se_service);
2286			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2287		}
2288#endif
2289		chBest->ch_LTime = t;
2290		{
2291			CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2292			if (ct->ct_Ticks != ticks) {
2293				ct->ct_Ticks = ticks;
2294				ct->ct_Count = 0;
2295			}
2296			++ct->ct_Count;
2297		}
2298		for (i = 0; i < CHTSIZE; ++i) {
2299			CTime *ct = &chBest->ch_Times[i];
2300			if (ct->ct_Ticks <= ticks &&
2301			    ct->ct_Ticks >= ticks - CHTSIZE) {
2302				cnt += ct->ct_Count;
2303			}
2304		}
2305		if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
2306			char pname[INET6_ADDRSTRLEN];
2307
2308			getnameinfo((struct sockaddr *)&rss,
2309				    ((struct sockaddr *)&rss)->sa_len,
2310				    pname, sizeof(pname), NULL, 0,
2311				    NI_NUMERICHOST|NI_WITHSCOPEID);
2312			r = -1;
2313			syslog(LOG_ERR,
2314			    "%s from %s exceeded counts/min (limit %d/min)",
2315			    sep->se_service, pname,
2316			    sep->se_maxcpm);
2317		}
2318	}
2319	return(r);
2320}
2321
2322static struct conninfo *
2323search_conn(struct servtab *sep, int ctrl)
2324{
2325	struct sockaddr_storage ss;
2326	socklen_t sslen = sizeof(ss);
2327	struct conninfo *conn;
2328	int hv;
2329	char pname[NI_MAXHOST],  pname2[NI_MAXHOST];
2330
2331	if (sep->se_maxperip <= 0)
2332		return NULL;
2333
2334	/*
2335	 * If getpeername() fails, just let it through (if logging is
2336	 * enabled the condition is caught elsewhere)
2337	 */
2338	if (getpeername(ctrl, (struct sockaddr *)&ss, &sslen) != 0)
2339		return NULL;
2340
2341	switch (ss.ss_family) {
2342	case AF_INET:
2343		hv = hashval((char *)&((struct sockaddr_in *)&ss)->sin_addr,
2344		    sizeof(struct in_addr));
2345		break;
2346#ifdef INET6
2347	case AF_INET6:
2348		hv = hashval((char *)&((struct sockaddr_in6 *)&ss)->sin6_addr,
2349		    sizeof(struct in6_addr));
2350		break;
2351#endif
2352	default:
2353		/*
2354		 * Since we only support AF_INET and AF_INET6, just
2355		 * let other than AF_INET and AF_INET6 through.
2356		 */
2357		return NULL;
2358	}
2359
2360	if (getnameinfo((struct sockaddr *)&ss, sslen, pname, sizeof(pname),
2361	    NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
2362		return NULL;
2363
2364	LIST_FOREACH(conn, &sep->se_conn[hv], co_link) {
2365		if (getnameinfo((struct sockaddr *)&conn->co_addr,
2366		    conn->co_addr.ss_len, pname2, sizeof(pname2), NULL, 0,
2367		    NI_NUMERICHOST | NI_WITHSCOPEID) == 0 &&
2368		    strcmp(pname, pname2) == 0)
2369			break;
2370	}
2371
2372	if (conn == NULL) {
2373		if ((conn = malloc(sizeof(struct conninfo))) == NULL) {
2374			syslog(LOG_ERR, "malloc: %m");
2375			exit(EX_OSERR);
2376		}
2377		conn->co_proc = malloc(sep->se_maxperip * sizeof(*conn->co_proc));
2378		if (conn->co_proc == NULL) {
2379			syslog(LOG_ERR, "malloc: %m");
2380			exit(EX_OSERR);
2381		}
2382		memcpy(&conn->co_addr, (struct sockaddr *)&ss, sslen);
2383		conn->co_numchild = 0;
2384		LIST_INSERT_HEAD(&sep->se_conn[hv], conn, co_link);
2385	}
2386
2387	/*
2388	 * Since a child process is not invoked yet, we cannot
2389	 * determine a pid of a child.  So, co_proc and co_numchild
2390	 * should be filled leter.
2391	 */
2392
2393	return conn;
2394}
2395
2396static int
2397room_conn(struct servtab *sep, struct conninfo *conn)
2398{
2399	char pname[NI_MAXHOST];
2400
2401	if (conn->co_numchild >= sep->se_maxperip) {
2402		getnameinfo((struct sockaddr *)&conn->co_addr,
2403		    conn->co_addr.ss_len, pname, sizeof(pname), NULL, 0,
2404		    NI_NUMERICHOST | NI_WITHSCOPEID);
2405		syslog(LOG_ERR, "%s from %s exceeded counts (limit %d)",
2406		    sep->se_service, pname, sep->se_maxperip);
2407		return 0;
2408	}
2409	return 1;
2410}
2411
2412static void
2413addchild_conn(struct conninfo *conn, pid_t pid)
2414{
2415	struct procinfo *proc;
2416
2417	if (conn == NULL)
2418		return;
2419
2420	if ((proc = search_proc(pid, 1)) != NULL) {
2421		if (proc->pr_conn != NULL) {
2422			syslog(LOG_ERR,
2423			    "addchild_conn: child already on process list");
2424			exit(EX_OSERR);
2425		}
2426		proc->pr_conn = conn;
2427	}
2428
2429	conn->co_proc[conn->co_numchild++] = proc;
2430}
2431
2432static void
2433reapchild_conn(pid_t pid)
2434{
2435	struct procinfo *proc;
2436	struct conninfo *conn;
2437	int i;
2438
2439	if ((proc = search_proc(pid, 0)) == NULL)
2440		return;
2441	if ((conn = proc->pr_conn) == NULL)
2442		return;
2443	for (i = 0; i < conn->co_numchild; ++i)
2444		if (conn->co_proc[i] == proc) {
2445			conn->co_proc[i] = conn->co_proc[--conn->co_numchild];
2446			break;
2447		}
2448	free_proc(proc);
2449	free_conn(conn);
2450}
2451
2452static void
2453resize_conn(struct servtab *sep, int maxpip)
2454{
2455	struct conninfo *conn;
2456	int i, j;
2457
2458	if (sep->se_maxperip <= 0)
2459		return;
2460	if (maxpip <= 0) {
2461		free_connlist(sep);
2462		return;
2463	}
2464	for (i = 0; i < PERIPSIZE; ++i) {
2465		LIST_FOREACH(conn, &sep->se_conn[i], co_link) {
2466			for (j = maxpip; j < conn->co_numchild; ++j)
2467				free_proc(conn->co_proc[j]);
2468			conn->co_proc = realloc(conn->co_proc,
2469			    maxpip * sizeof(*conn->co_proc));
2470			if (conn->co_proc == NULL) {
2471				syslog(LOG_ERR, "realloc: %m");
2472				exit(EX_OSERR);
2473			}
2474			if (conn->co_numchild > maxpip)
2475				conn->co_numchild = maxpip;
2476		}
2477	}
2478}
2479
2480static void
2481free_connlist(struct servtab *sep)
2482{
2483	struct conninfo *conn;
2484	int i, j;
2485
2486	for (i = 0; i < PERIPSIZE; ++i) {
2487		while ((conn = LIST_FIRST(&sep->se_conn[i])) != NULL) {
2488			for (j = 0; j < conn->co_numchild; ++j)
2489				free_proc(conn->co_proc[j]);
2490			conn->co_numchild = 0;
2491			free_conn(conn);
2492		}
2493	}
2494}
2495
2496static void
2497free_conn(struct conninfo *conn)
2498{
2499	if (conn == NULL)
2500		return;
2501	if (conn->co_numchild <= 0) {
2502		LIST_REMOVE(conn, co_link);
2503		free(conn->co_proc);
2504		free(conn);
2505	}
2506}
2507
2508static struct procinfo *
2509search_proc(pid_t pid, int add)
2510{
2511	struct procinfo *proc;
2512	int hv;
2513
2514	hv = hashval((char *)&pid, sizeof(pid));
2515	LIST_FOREACH(proc, &proctable[hv], pr_link) {
2516		if (proc->pr_pid == pid)
2517			break;
2518	}
2519	if (proc == NULL && add) {
2520		if ((proc = malloc(sizeof(struct procinfo))) == NULL) {
2521			syslog(LOG_ERR, "malloc: %m");
2522			exit(EX_OSERR);
2523		}
2524		proc->pr_pid = pid;
2525		proc->pr_conn = NULL;
2526		LIST_INSERT_HEAD(&proctable[hv], proc, pr_link);
2527	}
2528	return proc;
2529}
2530
2531static void
2532free_proc(struct procinfo *proc)
2533{
2534	if (proc == NULL)
2535		return;
2536	LIST_REMOVE(proc, pr_link);
2537	free(proc);
2538}
2539
2540static int
2541hashval(char *p, int len)
2542{
2543	int i, hv = 0xABC3D20F;
2544
2545	for (i = 0; i < len; ++i, ++p)
2546		hv = (hv << 5) ^ (hv >> 23) ^ *p;
2547	hv = (hv ^ (hv >> 16)) & (PERIPSIZE - 1);
2548	return hv;
2549}
2550