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