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