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