xref: /freebsd/usr.sbin/inetd/inetd.c (revision 04c9749ff0148ec8f73b150cec8bc2c094a5d31a)
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 #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 					close_sep(sep);
608 					sigsetmask(0L);
609 					if (!timingout) {
610 						timingout = 1;
611 						alarm(RETRYTIME);
612 					}
613 					continue;
614 				}
615 			    }
616 			    pid = fork();
617 		    }
618 		    if (pid < 0) {
619 			    syslog(LOG_ERR, "fork: %m");
620 			    if (sep->se_accept &&
621 				sep->se_socktype == SOCK_STREAM)
622 				    close(ctrl);
623 			    sigsetmask(0L);
624 			    sleep(1);
625 			    continue;
626 		    }
627 		    if (pid)
628 			addchild(sep, pid);
629 		    sigsetmask(0L);
630 		    if (pid == 0) {
631 			    if (dofork) {
632 				if (debug)
633 					warnx("+ closing from %d", maxsock);
634 				for (tmpint = maxsock; tmpint > 2; tmpint--)
635 					if (tmpint != ctrl)
636 						(void) close(tmpint);
637 				sigaction(SIGALRM, &saalrm, (struct sigaction *)0);
638 				sigaction(SIGCHLD, &sachld, (struct sigaction *)0);
639 				sigaction(SIGHUP, &sahup, (struct sigaction *)0);
640 				/* SIGPIPE reset before exec */
641 			    }
642 			    /*
643 			     * Call tcpmux to find the real service to exec.
644 			     */
645 			    if (sep->se_bi &&
646 				sep->se_bi->bi_fn == (void (*)()) tcpmux) {
647 				    sep = tcpmux(ctrl);
648 				    if (sep == NULL) {
649 					    close(ctrl);
650 					    _exit(0);
651 				    }
652 			    }
653 			    if (ISWRAP(sep)) {
654 				inetd_setproctitle("wrapping", ctrl);
655 				service = sep->se_server_name ?
656 				    sep->se_server_name : sep->se_service;
657 				request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, NULL);
658 				fromhost(&req);
659 				deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
660 				allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
661 				denied = !hosts_access(&req);
662 				if (denied) {
663 				    syslog(deny_severity,
664 				        "refused connection from %.500s, service %s (%s)",
665 				        eval_client(&req), service, sep->se_proto);
666 				    if (sep->se_socktype != SOCK_STREAM)
667 					recv(ctrl, buf, sizeof (buf), 0);
668 				    if (dofork) {
669 					sleep(1);
670 					_exit(0);
671 				    }
672 				}
673 				if (log) {
674 				    syslog(allow_severity,
675 				        "connection from %.500s, service %s (%s)",
676 					eval_client(&req), service, sep->se_proto);
677 				}
678 			    }
679 			    if (sep->se_bi) {
680 				(*sep->se_bi->bi_fn)(ctrl, sep);
681 			    } else {
682 				if (debug)
683 					warnx("%d execl %s",
684 						getpid(), sep->se_server);
685 				dup2(ctrl, 0);
686 				close(ctrl);
687 				dup2(0, 1);
688 				dup2(0, 2);
689 				if ((pwd = getpwnam(sep->se_user)) == NULL) {
690 					syslog(LOG_ERR,
691 					    "%s/%s: %s: no such user",
692 						sep->se_service, sep->se_proto,
693 						sep->se_user);
694 					if (sep->se_socktype != SOCK_STREAM)
695 						recv(0, buf, sizeof (buf), 0);
696 					_exit(EX_NOUSER);
697 				}
698 				grp = NULL;
699 				if (   sep->se_group != NULL
700 				    && (grp = getgrnam(sep->se_group)) == NULL
701 				   ) {
702 					syslog(LOG_ERR,
703 					    "%s/%s: %s: no such group",
704 						sep->se_service, sep->se_proto,
705 						sep->se_group);
706 					if (sep->se_socktype != SOCK_STREAM)
707 						recv(0, buf, sizeof (buf), 0);
708 					_exit(EX_NOUSER);
709 				}
710 				if (grp != NULL)
711 					pwd->pw_gid = grp->gr_gid;
712 #ifdef LOGIN_CAP
713 				if ((lc = login_getclass(sep->se_class)) == NULL) {
714 					/* error syslogged by getclass */
715 					syslog(LOG_ERR,
716 					    "%s/%s: %s: login class error",
717 						sep->se_service, sep->se_proto,
718 						sep->se_class);
719 					if (sep->se_socktype != SOCK_STREAM)
720 						recv(0, buf, sizeof (buf), 0);
721 					_exit(EX_NOUSER);
722 				}
723 #endif
724 				if (setsid() < 0) {
725 					syslog(LOG_ERR,
726 						"%s: can't setsid(): %m",
727 						 sep->se_service);
728 					/* _exit(EX_OSERR); not fatal yet */
729 				}
730 #ifdef LOGIN_CAP
731 				if (setusercontext(lc, pwd, pwd->pw_uid,
732 				    LOGIN_SETALL) != 0) {
733 					syslog(LOG_ERR,
734 					 "%s: can't setusercontext(..%s..): %m",
735 					 sep->se_service, sep->se_user);
736 					_exit(EX_OSERR);
737 				}
738 #else
739 				if (pwd->pw_uid) {
740 					if (setlogin(sep->se_user) < 0) {
741 						syslog(LOG_ERR,
742 						 "%s: can't setlogin(%s): %m",
743 						 sep->se_service, sep->se_user);
744 						/* _exit(EX_OSERR); not yet */
745 					}
746 					if (setgid(pwd->pw_gid) < 0) {
747 						syslog(LOG_ERR,
748 						  "%s: can't set gid %d: %m",
749 						  sep->se_service, pwd->pw_gid);
750 						_exit(EX_OSERR);
751 					}
752 					(void) initgroups(pwd->pw_name,
753 							pwd->pw_gid);
754 					if (setuid(pwd->pw_uid) < 0) {
755 						syslog(LOG_ERR,
756 						  "%s: can't set uid %d: %m",
757 						  sep->se_service, pwd->pw_uid);
758 						_exit(EX_OSERR);
759 					}
760 				}
761 #endif
762 				sigaction(SIGPIPE, &sapipe,
763 				    (struct sigaction *)0);
764 				execv(sep->se_server, sep->se_argv);
765 				syslog(LOG_ERR,
766 				    "cannot execute %s: %m", sep->se_server);
767 				if (sep->se_socktype != SOCK_STREAM)
768 					recv(0, buf, sizeof (buf), 0);
769 			    }
770 			    if (dofork)
771 				_exit(0);
772 		    }
773 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
774 			    close(ctrl);
775 		}
776 	}
777 }
778 
779 /*
780  * Add a signal flag to the signal flag queue for later handling
781  */
782 
783 void flag_signal(c)
784     char c;
785 {
786 	if (write(signalpipe[1], &c, 1) != 1) {
787 		syslog(LOG_ERR, "write: %m");
788 		_exit(EX_OSERR);
789 	}
790 }
791 
792 /*
793  * Record a new child pid for this service. If we've reached the
794  * limit on children, then stop accepting incoming requests.
795  */
796 
797 void
798 addchild(struct servtab *sep, pid_t pid)
799 {
800 	if (sep->se_maxchild <= 0)
801 		return;
802 #ifdef SANITY_CHECK
803 	if (sep->se_numchild >= sep->se_maxchild) {
804 		syslog(LOG_ERR, "%s: %d >= %d",
805 		    __FUNCTION__, sep->se_numchild, sep->se_maxchild);
806 		exit(EX_SOFTWARE);
807 	}
808 #endif
809 	sep->se_pids[sep->se_numchild++] = pid;
810 	if (sep->se_numchild == sep->se_maxchild)
811 		disable(sep);
812 }
813 
814 /*
815  * Some child process has exited. See if it's on somebody's list.
816  */
817 
818 void
819 flag_reapchild(signo)
820 	int signo;
821 {
822 	flag_signal('C');
823 }
824 
825 void
826 reapchild()
827 {
828 	int k, status;
829 	pid_t pid;
830 	struct servtab *sep;
831 
832 	for (;;) {
833 		pid = wait3(&status, WNOHANG, (struct rusage *)0);
834 		if (pid <= 0)
835 			break;
836 		if (debug)
837 			warnx("%d reaped, status %#x", pid, status);
838 		for (sep = servtab; sep; sep = sep->se_next) {
839 			for (k = 0; k < sep->se_numchild; k++)
840 				if (sep->se_pids[k] == pid)
841 					break;
842 			if (k == sep->se_numchild)
843 				continue;
844 			if (sep->se_numchild == sep->se_maxchild)
845 				enable(sep);
846 			sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
847 			if (status)
848 				syslog(LOG_WARNING,
849 				    "%s[%d]: exit status 0x%x",
850 				    sep->se_server, pid, status);
851 			break;
852 		}
853 	}
854 }
855 
856 void
857 flag_config(signo)
858 	int signo;
859 {
860 	flag_signal('H');
861 }
862 
863 void config()
864 {
865 	struct servtab *sep, *new, **sepp;
866 	long omask;
867 
868 	if (!setconfig()) {
869 		syslog(LOG_ERR, "%s: %m", CONFIG);
870 		return;
871 	}
872 	for (sep = servtab; sep; sep = sep->se_next)
873 		sep->se_checked = 0;
874 	while ((new = getconfigent())) {
875 		if (getpwnam(new->se_user) == NULL) {
876 			syslog(LOG_ERR,
877 				"%s/%s: no such user '%s', service ignored",
878 				new->se_service, new->se_proto, new->se_user);
879 			continue;
880 		}
881 		if (new->se_group && getgrnam(new->se_group) == NULL) {
882 			syslog(LOG_ERR,
883 				"%s/%s: no such group '%s', service ignored",
884 				new->se_service, new->se_proto, new->se_group);
885 			continue;
886 		}
887 #ifdef LOGIN_CAP
888 		if (login_getclass(new->se_class) == NULL) {
889 			/* error syslogged by getclass */
890 			syslog(LOG_ERR,
891 				"%s/%s: %s: login class error, service ignored",
892 				new->se_service, new->se_proto, new->se_class);
893 			continue;
894 		}
895 #endif
896 		for (sep = servtab; sep; sep = sep->se_next)
897 			if (strcmp(sep->se_service, new->se_service) == 0 &&
898 			    strcmp(sep->se_proto, new->se_proto) == 0 &&
899 			    sep->se_family == new->se_family)
900 				break;
901 		if (sep != 0) {
902 			int i;
903 
904 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
905 			omask = sigblock(SIGBLOCK);
906 			if (sep->se_nomapped != new->se_nomapped) {
907 				sep->se_nomapped = new->se_nomapped;
908 				sep->se_reset = 1;
909 			}
910 			/* copy over outstanding child pids */
911 			if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
912 				new->se_numchild = sep->se_numchild;
913 				if (new->se_numchild > new->se_maxchild)
914 					new->se_numchild = new->se_maxchild;
915 				memcpy(new->se_pids, sep->se_pids,
916 				    new->se_numchild * sizeof(*new->se_pids));
917 			}
918 			SWAP(sep->se_pids, new->se_pids);
919 			sep->se_maxchild = new->se_maxchild;
920 			sep->se_numchild = new->se_numchild;
921 			sep->se_maxcpm = new->se_maxcpm;
922 			/* might need to turn on or off service now */
923 			if (sep->se_fd >= 0) {
924 			      if (sep->se_maxchild > 0
925 				  && sep->se_numchild == sep->se_maxchild) {
926 				      if (FD_ISSET(sep->se_fd, &allsock))
927 					  disable(sep);
928 			      } else {
929 				      if (!FD_ISSET(sep->se_fd, &allsock))
930 					  enable(sep);
931 			      }
932 			}
933 			sep->se_accept = new->se_accept;
934 			SWAP(sep->se_user, new->se_user);
935 			SWAP(sep->se_group, new->se_group);
936 #ifdef LOGIN_CAP
937 			SWAP(sep->se_class, new->se_class);
938 #endif
939 			SWAP(sep->se_server, new->se_server);
940 			SWAP(sep->se_server_name, new->se_server_name);
941 			for (i = 0; i < MAXARGV; i++)
942 				SWAP(sep->se_argv[i], new->se_argv[i]);
943 #ifdef IPSEC
944 			SWAP(sep->se_policy, new->se_policy);
945 			ipsecsetup(sep);
946 #endif
947 			sigsetmask(omask);
948 			freeconfig(new);
949 			if (debug)
950 				print_service("REDO", sep);
951 		} else {
952 			sep = enter(new);
953 			if (debug)
954 				print_service("ADD ", sep);
955 		}
956 		sep->se_checked = 1;
957 		if (ISMUX(sep)) {
958 			sep->se_fd = -1;
959 			continue;
960 		}
961 		switch (sep->se_family) {
962 		case AF_INET:
963 			if (no_v4bind != 0) {
964 				sep->se_fd = -1;
965 				continue;
966 			}
967 			break;
968 #ifdef INET6
969 		case AF_INET6:
970 			if (no_v6bind != 0) {
971 				sep->se_fd = -1;
972 				continue;
973 			}
974 			break;
975 #endif
976 		}
977 		if (!sep->se_rpc) {
978 			sp = getservbyname(sep->se_service, sep->se_proto);
979 			if (sp == 0) {
980 				syslog(LOG_ERR, "%s/%s: unknown service",
981 				sep->se_service, sep->se_proto);
982 				sep->se_checked = 0;
983 				continue;
984 			}
985 			switch (sep->se_family) {
986 			case AF_INET:
987 				if (sep->se_ctladdrinitok == 0) {
988 					memcpy(&sep->se_ctrladdr4, bind_sa4,
989 					       sizeof(sep->se_ctrladdr4));
990 					sep->se_ctrladdr_size =
991 						sizeof(sep->se_ctrladdr4);
992 				}
993 				if (sp->s_port != sep->se_ctrladdr4.sin_port) {
994 					sep->se_ctrladdr4.sin_port =
995 						sp->s_port;
996 					sep->se_reset = 1;
997 				}
998 				break;
999 #ifdef INET6
1000 			case AF_INET6:
1001 				if (sep->se_ctladdrinitok == 0) {
1002 					memcpy(&sep->se_ctrladdr6, bind_sa6,
1003 					       sizeof(sep->se_ctrladdr6));
1004 					sep->se_ctrladdr_size =
1005 						sizeof(sep->se_ctrladdr6);
1006 				}
1007 				if (sp->s_port !=
1008 				    sep->se_ctrladdr6.sin6_port) {
1009 					sep->se_ctrladdr6.sin6_port =
1010 						sp->s_port;
1011 					sep->se_reset = 1;
1012 				}
1013 				break;
1014 #endif
1015 			}
1016 			if (sep->se_reset != 0 && sep->se_fd >= 0)
1017 				close_sep(sep);
1018 		} else {
1019 			rpc = getrpcbyname(sep->se_service);
1020 			if (rpc == 0) {
1021 				syslog(LOG_ERR, "%s/%s unknown RPC service",
1022 					sep->se_service, sep->se_proto);
1023 				if (sep->se_fd != -1)
1024 					(void) close(sep->se_fd);
1025 				sep->se_fd = -1;
1026 					continue;
1027 			}
1028 			if (rpc->r_number != sep->se_rpc_prog) {
1029 				if (sep->se_rpc_prog)
1030 					unregisterrpc(sep);
1031 				sep->se_rpc_prog = rpc->r_number;
1032 				if (sep->se_fd != -1)
1033 					(void) close(sep->se_fd);
1034 				sep->se_fd = -1;
1035 			}
1036 		}
1037 		if (sep->se_fd == -1)
1038 			setup(sep);
1039 	}
1040 	endconfig();
1041 	/*
1042 	 * Purge anything not looked at above.
1043 	 */
1044 	omask = sigblock(SIGBLOCK);
1045 	sepp = &servtab;
1046 	while ((sep = *sepp)) {
1047 		if (sep->se_checked) {
1048 			sepp = &sep->se_next;
1049 			continue;
1050 		}
1051 		*sepp = sep->se_next;
1052 		if (sep->se_fd >= 0)
1053 			close_sep(sep);
1054 		if (debug)
1055 			print_service("FREE", sep);
1056 		if (sep->se_rpc && sep->se_rpc_prog > 0)
1057 			unregisterrpc(sep);
1058 		freeconfig(sep);
1059 		free((char *)sep);
1060 	}
1061 	(void) sigsetmask(omask);
1062 }
1063 
1064 void
1065 unregisterrpc(sep)
1066 	struct servtab *sep;
1067 {
1068         int i;
1069         struct servtab *sepp;
1070 	long omask;
1071 
1072 	omask = sigblock(SIGBLOCK);
1073         for (sepp = servtab; sepp; sepp = sepp->se_next) {
1074                 if (sepp == sep)
1075                         continue;
1076 		if (sep->se_checked == 0 ||
1077                     !sepp->se_rpc ||
1078                     sep->se_rpc_prog != sepp->se_rpc_prog)
1079 			continue;
1080                 return;
1081         }
1082         if (debug)
1083                 print_service("UNREG", sep);
1084         for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++)
1085                 pmap_unset(sep->se_rpc_prog, i);
1086         if (sep->se_fd != -1)
1087                 (void) close(sep->se_fd);
1088         sep->se_fd = -1;
1089 	(void) sigsetmask(omask);
1090 }
1091 
1092 void
1093 flag_retry(signo)
1094 	int signo;
1095 {
1096 	flag_signal('A');
1097 }
1098 
1099 void
1100 retry()
1101 {
1102 	struct servtab *sep;
1103 
1104 	timingout = 0;
1105 	for (sep = servtab; sep; sep = sep->se_next)
1106 		if (sep->se_fd == -1 && !ISMUX(sep))
1107 			setup(sep);
1108 }
1109 
1110 void
1111 setup(sep)
1112 	struct servtab *sep;
1113 {
1114 	int on = 1;
1115 
1116 	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1117 		if (debug)
1118 			warn("socket failed on %s/%s",
1119 				sep->se_service, sep->se_proto);
1120 		syslog(LOG_ERR, "%s/%s: socket: %m",
1121 		    sep->se_service, sep->se_proto);
1122 		return;
1123 	}
1124 #define	turnon(fd, opt) \
1125 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1126 	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1127 	    turnon(sep->se_fd, SO_DEBUG) < 0)
1128 		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1129 	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1130 		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1131 #ifdef SO_PRIVSTATE
1132 	if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1133 		syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1134 #endif
1135 	/* tftpd opens a new connection then needs more infos */
1136 	if ((sep->se_family == AF_INET6) &&
1137 	    (strcmp(sep->se_proto, "udp") == 0) &&
1138 	    (sep->se_accept == 0) &&
1139 	    (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO,
1140 			(char *)&on, sizeof (on)) < 0))
1141 		syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
1142 #ifdef IPV6_BINDV6ONLY
1143 	if (sep->se_family == AF_INET6) {
1144 		int flag = sep->se_nomapped ? 1 : 0;
1145 		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
1146 			       (char *)&flag, sizeof (flag)) < 0)
1147 			syslog(LOG_ERR, "setsockopt (IPV6_BINDV6ONLY): %m");
1148 	}
1149 #endif /* IPV6_BINDV6ONLY */
1150 #undef turnon
1151 	if (sep->se_type == TTCP_TYPE)
1152 		if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1153 		    (char *)&on, sizeof (on)) < 0)
1154 			syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1155 #ifdef IPV6_FAITH
1156 	if (sep->se_type == FAITH_TYPE) {
1157 		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
1158 				sizeof(on)) < 0) {
1159 			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1160 		}
1161 	}
1162 #endif
1163 #ifdef IPSEC
1164 	ipsecsetup(sep);
1165 #endif
1166 	if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1167 	    sep->se_ctrladdr_size) < 0) {
1168 		if (debug)
1169 			warn("bind failed on %s/%s",
1170 				sep->se_service, sep->se_proto);
1171 		syslog(LOG_ERR, "%s/%s: bind: %m",
1172 		    sep->se_service, sep->se_proto);
1173 		(void) close(sep->se_fd);
1174 		sep->se_fd = -1;
1175 		if (!timingout) {
1176 			timingout = 1;
1177 			alarm(RETRYTIME);
1178 		}
1179 		return;
1180 	}
1181         if (sep->se_rpc) {
1182                 int i, len = sep->se_ctrladdr_size;
1183 
1184 		if (sep->se_family != AF_INET) {
1185                         syslog(LOG_ERR,
1186 			       "%s/%s: unsupported address family for rpc",
1187                                sep->se_service, sep->se_proto);
1188                         (void) close(sep->se_fd);
1189                         sep->se_fd = -1;
1190                         return;
1191 		}
1192                 if (getsockname(sep->se_fd,
1193 				(struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1194                         syslog(LOG_ERR, "%s/%s: getsockname: %m",
1195                                sep->se_service, sep->se_proto);
1196                         (void) close(sep->se_fd);
1197                         sep->se_fd = -1;
1198                         return;
1199                 }
1200                 if (debug)
1201                         print_service("REG ", sep);
1202                 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1203                         pmap_unset(sep->se_rpc_prog, i);
1204                         pmap_set(sep->se_rpc_prog, i,
1205                                  (sep->se_socktype == SOCK_DGRAM)
1206                                  ? IPPROTO_UDP : IPPROTO_TCP,
1207 				 ntohs(sep->se_ctrladdr4.sin_port));
1208                 }
1209         }
1210 	if (sep->se_socktype == SOCK_STREAM)
1211 		listen(sep->se_fd, 64);
1212 	enable(sep);
1213 	if (debug) {
1214 		warnx("registered %s on %d",
1215 			sep->se_server, sep->se_fd);
1216 	}
1217 }
1218 
1219 #ifdef IPSEC
1220 void
1221 ipsecsetup(sep)
1222 	struct servtab *sep;
1223 {
1224 	char *buf;
1225 	char *policy_in = NULL;
1226 	char *policy_out = NULL;
1227 	int level;
1228 	int opt;
1229 
1230 	switch (sep->se_family) {
1231 	case AF_INET:
1232 		level = IPPROTO_IP;
1233 		opt = IP_IPSEC_POLICY;
1234 		break;
1235 #ifdef INET6
1236 	case AF_INET6:
1237 		level = IPPROTO_IPV6;
1238 		opt = IPV6_IPSEC_POLICY;
1239 		break;
1240 #endif
1241 	default:
1242 		return;
1243 	}
1244 
1245 	if (!sep->se_policy || sep->se_policy[0] == '\0') {
1246 		policy_in = "in entrust";
1247 		policy_out = "out entrust";
1248 	} else {
1249 		if (!strncmp("in", sep->se_policy, 2))
1250 			policy_in = sep->se_policy;
1251 		else if (!strncmp("out", sep->se_policy, 3))
1252 			policy_out = sep->se_policy;
1253 		else {
1254 			syslog(LOG_ERR, "invalid security policy \"%s\"",
1255 				sep->se_policy);
1256 			return;
1257 		}
1258 	}
1259 
1260 	if (policy_in != NULL) {
1261 		buf = ipsec_set_policy(policy_in, strlen(policy_in));
1262 		if (buf != NULL) {
1263 			if (setsockopt(sep->se_fd, level, opt,
1264 					buf, ipsec_get_policylen(buf)) < 0 &&
1265 			    debug != 0)
1266 				warnx("%s/%s: ipsec initialization failed; %s",
1267 				      sep->se_service, sep->se_proto,
1268 				      policy_in);
1269 			free(buf);
1270 		} else
1271 			syslog(LOG_ERR, "invalid security policy \"%s\"",
1272 				policy_in);
1273 	}
1274 	if (policy_out != NULL) {
1275 		buf = ipsec_set_policy(policy_out, strlen(policy_out));
1276 		if (buf != NULL) {
1277 			if (setsockopt(sep->se_fd, level, opt,
1278 					buf, ipsec_get_policylen(buf)) < 0 &&
1279 			    debug != 0)
1280 				warnx("%s/%s: ipsec initialization failed; %s",
1281 				      sep->se_service, sep->se_proto,
1282 				      policy_out);
1283 			free(buf);
1284 		} else
1285 			syslog(LOG_ERR, "invalid security policy \"%s\"",
1286 				policy_out);
1287 	}
1288 }
1289 #endif
1290 
1291 /*
1292  * Finish with a service and its socket.
1293  */
1294 void
1295 close_sep(sep)
1296 	struct servtab *sep;
1297 {
1298 	if (sep->se_fd >= 0) {
1299 		if (FD_ISSET(sep->se_fd, &allsock))
1300 			disable(sep);
1301 		(void) close(sep->se_fd);
1302 		sep->se_fd = -1;
1303 	}
1304 	sep->se_count = 0;
1305 	sep->se_numchild = 0;	/* forget about any existing children */
1306 }
1307 
1308 int
1309 matchservent(name1, name2, proto)
1310 	char *name1, *name2, *proto;
1311 {
1312 	char **alias;
1313 	struct servent *se;
1314 
1315 	if (strcmp(name1, name2) == 0)
1316 		return(1);
1317 	if ((se = getservbyname(name1, proto)) != NULL) {
1318 		if (strcmp(name2, se->s_name) == 0)
1319 			return(1);
1320 		for (alias = se->s_aliases; *alias; alias++)
1321 			if (strcmp(name2, *alias) == 0)
1322 				return(1);
1323 	}
1324 	return(0);
1325 }
1326 
1327 struct servtab *
1328 enter(cp)
1329 	struct servtab *cp;
1330 {
1331 	struct servtab *sep;
1332 	long omask;
1333 
1334 	sep = (struct servtab *)malloc(sizeof (*sep));
1335 	if (sep == (struct servtab *)0) {
1336 		syslog(LOG_ERR, "malloc: %m");
1337 		exit(EX_OSERR);
1338 	}
1339 	*sep = *cp;
1340 	sep->se_fd = -1;
1341 	omask = sigblock(SIGBLOCK);
1342 	sep->se_next = servtab;
1343 	servtab = sep;
1344 	sigsetmask(omask);
1345 	return (sep);
1346 }
1347 
1348 void
1349 enable(struct servtab *sep)
1350 {
1351 	if (debug)
1352 		warnx(
1353 		    "enabling %s, fd %d", sep->se_service, sep->se_fd);
1354 #ifdef SANITY_CHECK
1355 	if (sep->se_fd < 0) {
1356 		syslog(LOG_ERR,
1357 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1358 		exit(EX_SOFTWARE);
1359 	}
1360 	if (ISMUX(sep)) {
1361 		syslog(LOG_ERR,
1362 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1363 		exit(EX_SOFTWARE);
1364 	}
1365 	if (FD_ISSET(sep->se_fd, &allsock)) {
1366 		syslog(LOG_ERR,
1367 		    "%s: %s: not off", __FUNCTION__, sep->se_service);
1368 		exit(EX_SOFTWARE);
1369 	}
1370 	nsock++;
1371 #endif
1372 	FD_SET(sep->se_fd, &allsock);
1373 	if (sep->se_fd > maxsock)
1374 		maxsock = sep->se_fd;
1375 }
1376 
1377 void
1378 disable(struct servtab *sep)
1379 {
1380 	if (debug)
1381 		warnx(
1382 		    "disabling %s, fd %d", sep->se_service, sep->se_fd);
1383 #ifdef SANITY_CHECK
1384 	if (sep->se_fd < 0) {
1385 		syslog(LOG_ERR,
1386 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1387 		exit(EX_SOFTWARE);
1388 	}
1389 	if (ISMUX(sep)) {
1390 		syslog(LOG_ERR,
1391 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1392 		exit(EX_SOFTWARE);
1393 	}
1394 	if (!FD_ISSET(sep->se_fd, &allsock)) {
1395 		syslog(LOG_ERR,
1396 		    "%s: %s: not on", __FUNCTION__, sep->se_service);
1397 		exit(EX_SOFTWARE);
1398 	}
1399 	if (nsock == 0) {
1400 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
1401 		exit(EX_SOFTWARE);
1402 	}
1403 	nsock--;
1404 #endif
1405 	FD_CLR(sep->se_fd, &allsock);
1406 	if (sep->se_fd == maxsock)
1407 		maxsock--;
1408 }
1409 
1410 FILE	*fconfig = NULL;
1411 struct	servtab serv;
1412 char	line[LINE_MAX];
1413 
1414 int
1415 setconfig()
1416 {
1417 
1418 	if (fconfig != NULL) {
1419 		fseek(fconfig, 0L, SEEK_SET);
1420 		return (1);
1421 	}
1422 	fconfig = fopen(CONFIG, "r");
1423 	return (fconfig != NULL);
1424 }
1425 
1426 void
1427 endconfig()
1428 {
1429 	if (fconfig) {
1430 		(void) fclose(fconfig);
1431 		fconfig = NULL;
1432 	}
1433 }
1434 
1435 struct servtab *
1436 getconfigent()
1437 {
1438 	struct servtab *sep = &serv;
1439 	int argc;
1440 	char *cp, *arg, *s;
1441 	char *versp;
1442 	static char TCPMUX_TOKEN[] = "tcpmux/";
1443 #define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1444 #ifdef IPSEC
1445 	char *policy = NULL;
1446 #endif
1447 	int v4bind = 0;
1448 #ifdef INET6
1449 	int v6bind = 0;
1450 #endif
1451 
1452 more:
1453 	while ((cp = nextline(fconfig)) != NULL) {
1454 #ifdef IPSEC
1455 		/* lines starting with #@ is not a comment, but the policy */
1456 		if (cp[0] == '#' && cp[1] == '@') {
1457 			char *p;
1458 			for (p = cp + 2; p && *p && isspace(*p); p++)
1459 				;
1460 			if (*p == '\0') {
1461 				if (policy)
1462 					free(policy);
1463 				policy = NULL;
1464 			} else if (ipsec_get_policylen(p) >= 0) {
1465 				if (policy)
1466 					free(policy);
1467 				policy = newstr(p);
1468 			} else {
1469 				syslog(LOG_ERR,
1470 					"%s: invalid ipsec policy \"%s\"",
1471 					CONFIG, p);
1472 				exit(EX_CONFIG);
1473 			}
1474 		}
1475 #endif
1476 		if (*cp == '#' || *cp == '\0')
1477 			continue;
1478 		break;
1479 	}
1480 	if (cp == NULL)
1481 		return ((struct servtab *)0);
1482 	/*
1483 	 * clear the static buffer, since some fields (se_ctrladdr,
1484 	 * for example) don't get initialized here.
1485 	 */
1486 	memset((caddr_t)sep, 0, sizeof *sep);
1487 	arg = skip(&cp);
1488 	if (cp == NULL) {
1489 		/* got an empty line containing just blanks/tabs. */
1490 		goto more;
1491 	}
1492 	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1493 		char *c = arg + MUX_LEN;
1494 		if (*c == '+') {
1495 			sep->se_type = MUXPLUS_TYPE;
1496 			c++;
1497 		} else
1498 			sep->se_type = MUX_TYPE;
1499 		sep->se_service = newstr(c);
1500 	} else {
1501 		sep->se_service = newstr(arg);
1502 		sep->se_type = NORM_TYPE;
1503 	}
1504 	arg = sskip(&cp);
1505 	if (strcmp(arg, "stream") == 0)
1506 		sep->se_socktype = SOCK_STREAM;
1507 	else if (strcmp(arg, "dgram") == 0)
1508 		sep->se_socktype = SOCK_DGRAM;
1509 	else if (strcmp(arg, "rdm") == 0)
1510 		sep->se_socktype = SOCK_RDM;
1511 	else if (strcmp(arg, "seqpacket") == 0)
1512 		sep->se_socktype = SOCK_SEQPACKET;
1513 	else if (strcmp(arg, "raw") == 0)
1514 		sep->se_socktype = SOCK_RAW;
1515 	else
1516 		sep->se_socktype = -1;
1517 
1518 	arg = sskip(&cp);
1519 	if (strncmp(arg, "tcp", 3) == 0) {
1520 		sep->se_proto = newstr(strsep(&arg, "/"));
1521 		if (arg != NULL) {
1522 			if (strcmp(arg, "ttcp") == 0)
1523 				sep->se_type = TTCP_TYPE;
1524 			else if (strcmp(arg, "faith") == 0)
1525 				sep->se_type = FAITH_TYPE;
1526 		}
1527 	} else
1528 		sep->se_proto = newstr(arg);
1529         if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1530 		if (no_v4bind != 0) {
1531 			syslog(LOG_INFO, "IPv4 bind is ignored for %s",
1532 			       sep->se_service);
1533 			freeconfig(sep);
1534 			goto more;
1535 		}
1536                 memmove(sep->se_proto, sep->se_proto + 4,
1537                     strlen(sep->se_proto) + 1 - 4);
1538                 sep->se_rpc = 1;
1539                 sep->se_rpc_prog = sep->se_rpc_lowvers =
1540 			sep->se_rpc_lowvers = 0;
1541 		memcpy(&sep->se_ctrladdr4, bind_sa4,
1542 		       sizeof(sep->se_ctrladdr4));
1543                 if ((versp = rindex(sep->se_service, '/'))) {
1544                         *versp++ = '\0';
1545                         switch (sscanf(versp, "%d-%d",
1546                                        &sep->se_rpc_lowvers,
1547                                        &sep->se_rpc_highvers)) {
1548                         case 2:
1549                                 break;
1550                         case 1:
1551                                 sep->se_rpc_highvers =
1552                                         sep->se_rpc_lowvers;
1553                                 break;
1554                         default:
1555                                 syslog(LOG_ERR,
1556 					"bad RPC version specifier; %s",
1557 					sep->se_service);
1558                                 freeconfig(sep);
1559                                 goto more;
1560                         }
1561                 }
1562                 else {
1563                         sep->se_rpc_lowvers =
1564                                 sep->se_rpc_highvers = 1;
1565                 }
1566         }
1567 	sep->se_nomapped = 0;
1568 	while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
1569 #ifdef INET6
1570 		if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
1571 			if (no_v6bind != 0) {
1572 				syslog(LOG_INFO, "IPv6 bind is ignored for %s",
1573 				       sep->se_service);
1574 				freeconfig(sep);
1575 				goto more;
1576 			}
1577 			sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1578 			v6bind = 1;
1579 			continue;
1580 		}
1581 #endif
1582 		if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
1583 			sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1584 			v4bind = 1;
1585 			continue;
1586 		}
1587 		/* illegal version num */
1588 		syslog(LOG_ERR,	"bad IP version for %s", sep->se_proto);
1589 		freeconfig(sep);
1590 		goto more;
1591 	}
1592 #ifdef INET6
1593 	if (v6bind != 0) {
1594 		sep->se_family = AF_INET6;
1595 		if (v4bind == 0 || no_v4bind != 0)
1596 			sep->se_nomapped = 1;
1597 	} else
1598 #endif
1599 	{ /* default to v4 bind if not v6 bind */
1600 		if (no_v4bind != 0) {
1601 			syslog(LOG_INFO, "IPv4 bind is ignored for %s",
1602 			       sep->se_service);
1603 			freeconfig(sep);
1604 			goto more;
1605 		}
1606 		sep->se_family = AF_INET;
1607 	}
1608 	/* init ctladdr */
1609 	switch(sep->se_family) {
1610 	case AF_INET:
1611 		memcpy(&sep->se_ctrladdr4, bind_sa4,
1612 		       sizeof(sep->se_ctrladdr4));
1613 		sep->se_ctrladdr_size =	sizeof(sep->se_ctrladdr4);
1614 		sep->se_ctladdrinitok = 1;
1615 		break;
1616 #ifdef INET6
1617 	case AF_INET6:
1618 		memcpy(&sep->se_ctrladdr6, bind_sa6,
1619 		       sizeof(sep->se_ctrladdr6));
1620 		sep->se_ctrladdr_size =	sizeof(sep->se_ctrladdr6);
1621 		sep->se_ctladdrinitok = 1;
1622 		break;
1623 #endif
1624 	}
1625 	arg = sskip(&cp);
1626 	if (!strncmp(arg, "wait", 4))
1627 		sep->se_accept = 0;
1628 	else if (!strncmp(arg, "nowait", 6))
1629 		sep->se_accept = 1;
1630 	else {
1631 		syslog(LOG_ERR,
1632 			"%s: bad wait/nowait for service %s",
1633 			CONFIG, sep->se_service);
1634 		goto more;
1635 	}
1636 	sep->se_maxchild = -1;
1637 	sep->se_maxcpm = -1;
1638 	if ((s = strchr(arg, '/')) != NULL) {
1639 		char *eptr;
1640 		u_long val;
1641 
1642 		val = strtoul(s + 1, &eptr, 10);
1643 		if (eptr == s + 1 || val > MAX_MAXCHLD) {
1644 			syslog(LOG_ERR,
1645 				"%s: bad max-child for service %s",
1646 				CONFIG, sep->se_service);
1647 			goto more;
1648 		}
1649 		if (debug)
1650 			if (!sep->se_accept && val != 1)
1651 				warnx("maxchild=%lu for wait service %s"
1652 				    " not recommended", val, sep->se_service);
1653 		sep->se_maxchild = val;
1654 		if (*eptr == '/')
1655 			sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1656 		/*
1657 		 * explicitly do not check for \0 for future expansion /
1658 		 * backwards compatibility
1659 		 */
1660 	}
1661 	if (ISMUX(sep)) {
1662 		/*
1663 		 * Silently enforce "nowait" mode for TCPMUX services
1664 		 * since they don't have an assigned port to listen on.
1665 		 */
1666 		sep->se_accept = 1;
1667 		if (strcmp(sep->se_proto, "tcp")) {
1668 			syslog(LOG_ERR,
1669 				"%s: bad protocol for tcpmux service %s",
1670 				CONFIG, sep->se_service);
1671 			goto more;
1672 		}
1673 		if (sep->se_socktype != SOCK_STREAM) {
1674 			syslog(LOG_ERR,
1675 				"%s: bad socket type for tcpmux service %s",
1676 				CONFIG, sep->se_service);
1677 			goto more;
1678 		}
1679 	}
1680 	sep->se_user = newstr(sskip(&cp));
1681 #ifdef LOGIN_CAP
1682 	if ((s = strrchr(sep->se_user, '/')) != NULL) {
1683 		*s = '\0';
1684 		sep->se_class = newstr(s + 1);
1685 	} else
1686 		sep->se_class = newstr(RESOURCE_RC);
1687 #endif
1688 	if ((s = strrchr(sep->se_user, ':')) != NULL) {
1689 		*s = '\0';
1690 		sep->se_group = newstr(s + 1);
1691 	} else
1692 		sep->se_group = NULL;
1693 	sep->se_server = newstr(sskip(&cp));
1694 	if ((sep->se_server_name = rindex(sep->se_server, '/')))
1695 		sep->se_server_name++;
1696 	if (strcmp(sep->se_server, "internal") == 0) {
1697 		struct biltin *bi;
1698 
1699 		for (bi = biltins; bi->bi_service; bi++)
1700 			if (bi->bi_socktype == sep->se_socktype &&
1701 			    matchservent(bi->bi_service, sep->se_service,
1702 			    sep->se_proto))
1703 				break;
1704 		if (bi->bi_service == 0) {
1705 			syslog(LOG_ERR, "internal service %s unknown",
1706 				sep->se_service);
1707 			goto more;
1708 		}
1709 		sep->se_accept = 1;	/* force accept mode for built-ins */
1710 		sep->se_bi = bi;
1711 	} else
1712 		sep->se_bi = NULL;
1713 	if (sep->se_maxcpm < 0)
1714 		sep->se_maxcpm = maxcpm;
1715 	if (sep->se_maxchild < 0) {	/* apply default max-children */
1716 		if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1717 			sep->se_maxchild = sep->se_bi->bi_maxchild;
1718 		else if (sep->se_accept)
1719 			sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1720 		else
1721 			sep->se_maxchild = 1;
1722 	}
1723 	if (sep->se_maxchild > 0) {
1724 		sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1725 		if (sep->se_pids == NULL) {
1726 			syslog(LOG_ERR, "malloc: %m");
1727 			exit(EX_OSERR);
1728 		}
1729 	}
1730 	argc = 0;
1731 	for (arg = skip(&cp); cp; arg = skip(&cp))
1732 		if (argc < MAXARGV) {
1733 			sep->se_argv[argc++] = newstr(arg);
1734 		} else {
1735 			syslog(LOG_ERR,
1736 				"%s: too many arguments for service %s",
1737 				CONFIG, sep->se_service);
1738 			goto more;
1739 		}
1740 	while (argc <= MAXARGV)
1741 		sep->se_argv[argc++] = NULL;
1742 #ifdef IPSEC
1743 	sep->se_policy = policy ? newstr(policy) : NULL;
1744 #endif
1745 	return (sep);
1746 }
1747 
1748 void
1749 freeconfig(cp)
1750 	struct servtab *cp;
1751 {
1752 	int i;
1753 
1754 	if (cp->se_service)
1755 		free(cp->se_service);
1756 	if (cp->se_proto)
1757 		free(cp->se_proto);
1758 	if (cp->se_user)
1759 		free(cp->se_user);
1760 	if (cp->se_group)
1761 		free(cp->se_group);
1762 #ifdef LOGIN_CAP
1763 	if (cp->se_class)
1764 		free(cp->se_class);
1765 #endif
1766 	if (cp->se_server)
1767 		free(cp->se_server);
1768 	if (cp->se_pids)
1769 		free(cp->se_pids);
1770 	for (i = 0; i < MAXARGV; i++)
1771 		if (cp->se_argv[i])
1772 			free(cp->se_argv[i]);
1773 #ifdef IPSEC
1774 	if (cp->se_policy)
1775 		free(cp->se_policy);
1776 #endif
1777 }
1778 
1779 
1780 /*
1781  * Safe skip - if skip returns null, log a syntax error in the
1782  * configuration file and exit.
1783  */
1784 char *
1785 sskip(cpp)
1786 	char **cpp;
1787 {
1788 	char *cp;
1789 
1790 	cp = skip(cpp);
1791 	if (cp == NULL) {
1792 		syslog(LOG_ERR, "%s: syntax error", CONFIG);
1793 		exit(EX_DATAERR);
1794 	}
1795 	return (cp);
1796 }
1797 
1798 char *
1799 skip(cpp)
1800 	char **cpp;
1801 {
1802 	char *cp = *cpp;
1803 	char *start;
1804 	char quote = '\0';
1805 
1806 again:
1807 	while (*cp == ' ' || *cp == '\t')
1808 		cp++;
1809 	if (*cp == '\0') {
1810 		int c;
1811 
1812 		c = getc(fconfig);
1813 		(void) ungetc(c, fconfig);
1814 		if (c == ' ' || c == '\t')
1815 			if ((cp = nextline(fconfig)))
1816 				goto again;
1817 		*cpp = (char *)0;
1818 		return ((char *)0);
1819 	}
1820 	if (*cp == '"' || *cp == '\'')
1821 		quote = *cp++;
1822 	start = cp;
1823 	if (quote)
1824 		while (*cp && *cp != quote)
1825 			cp++;
1826 	else
1827 		while (*cp && *cp != ' ' && *cp != '\t')
1828 			cp++;
1829 	if (*cp != '\0')
1830 		*cp++ = '\0';
1831 	*cpp = cp;
1832 	return (start);
1833 }
1834 
1835 char *
1836 nextline(fd)
1837 	FILE *fd;
1838 {
1839 	char *cp;
1840 
1841 	if (fgets(line, sizeof (line), fd) == NULL)
1842 		return ((char *)0);
1843 	cp = strchr(line, '\n');
1844 	if (cp)
1845 		*cp = '\0';
1846 	return (line);
1847 }
1848 
1849 char *
1850 newstr(cp)
1851 	char *cp;
1852 {
1853 	if ((cp = strdup(cp ? cp : "")))
1854 		return (cp);
1855 	syslog(LOG_ERR, "strdup: %m");
1856 	exit(EX_OSERR);
1857 }
1858 
1859 #ifdef OLD_SETPROCTITLE
1860 void
1861 inetd_setproctitle(a, s)
1862 	char *a;
1863 	int s;
1864 {
1865 	int size;
1866 	char *cp;
1867 	struct sockaddr_storage ss;
1868 	char buf[80], pbuf[INET6_ADDRSTRLEN];
1869 
1870 	cp = Argv[0];
1871 	size = sizeof(ss);
1872 	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1873 		getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
1874 			    NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
1875 		(void) sprintf(buf, "-%s [%s]", a, pbuf);
1876 	} else
1877 		(void) sprintf(buf, "-%s", a);
1878 	strncpy(cp, buf, LastArg - cp);
1879 	cp += strlen(cp);
1880 	while (cp < LastArg)
1881 		*cp++ = ' ';
1882 }
1883 #else
1884 void
1885 inetd_setproctitle(a, s)
1886 	char *a;
1887 	int s;
1888 {
1889 	int size;
1890 	struct sockaddr_storage ss;
1891 	char buf[80], pbuf[INET6_ADDRSTRLEN];
1892 
1893 	size = sizeof(ss);
1894 	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1895 		getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
1896 			    NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
1897 		(void) sprintf(buf, "%s [%s]", a, pbuf);
1898 	} else
1899 		(void) sprintf(buf, "%s", a);
1900 	setproctitle("%s", buf);
1901 }
1902 #endif
1903 
1904 
1905 /*
1906  * Internet services provided internally by inetd:
1907  */
1908 
1909 int check_loop(sa, sep)
1910 	struct sockaddr *sa;
1911 	struct servtab *sep;
1912 {
1913 	struct servtab *se2;
1914 	char pname[INET6_ADDRSTRLEN];
1915 
1916 	for (se2 = servtab; se2; se2 = se2->se_next) {
1917 		if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
1918 			continue;
1919 
1920 		switch (se2->se_family) {
1921 		case AF_INET:
1922 			if (((struct sockaddr_in *)sa)->sin_port ==
1923 			    se2->se_ctrladdr4.sin_port)
1924 				goto isloop;
1925 			continue;
1926 #ifdef INET6
1927 		case AF_INET6:
1928 			if (((struct sockaddr_in *)sa)->sin_port ==
1929 			    se2->se_ctrladdr4.sin_port)
1930 				goto isloop;
1931 			continue;
1932 #endif
1933 		default:
1934 			continue;
1935 		}
1936 	isloop:
1937 		getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
1938 			    NI_NUMERICHOST|NI_WITHSCOPEID);
1939 		syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
1940 		       sep->se_service, sep->se_proto,
1941 		       se2->se_service, se2->se_proto,
1942 		       pname);
1943 		return 1;
1944 	}
1945 	return 0;
1946 }
1947 
1948 /*
1949  * print_service:
1950  *	Dump relevant information to stderr
1951  */
1952 void
1953 print_service(action, sep)
1954 	char *action;
1955 	struct servtab *sep;
1956 {
1957 	fprintf(stderr,
1958 	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
1959 #ifdef LOGIN_CAP
1960 	    "class=%s"
1961 #endif
1962 	    " builtin=%p server=%s"
1963 #ifdef IPSEC
1964 	    " policy=\"%s\""
1965 #endif
1966 	    "\n",
1967 	    action, sep->se_service, sep->se_proto,
1968 	    sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
1969 #ifdef LOGIN_CAP
1970 	    sep->se_class,
1971 #endif
1972 	    (void *) sep->se_bi, sep->se_server
1973 #ifdef IPSEC
1974 	    , (sep->se_policy ? sep->se_policy : "")
1975 #endif
1976 	    );
1977 }
1978 
1979 #define CPMHSIZE	256
1980 #define CPMHMASK	(CPMHSIZE-1)
1981 #define CHTGRAN		10
1982 #define CHTSIZE		6
1983 
1984 typedef struct CTime {
1985 	unsigned long 	ct_Ticks;
1986 	int		ct_Count;
1987 } CTime;
1988 
1989 typedef struct CHash {
1990 	union {
1991 		struct in_addr	c4_Addr;
1992 		struct in6_addr	c6_Addr;
1993 	} cu_Addr;
1994 #define	ch_Addr4	cu_Addr.c4_Addr
1995 #define	ch_Addr6	cu_Addr.c6_Addr
1996 	int		ch_Family;
1997 	time_t		ch_LTime;
1998 	char		*ch_Service;
1999 	CTime		ch_Times[CHTSIZE];
2000 } CHash;
2001 
2002 CHash	CHashAry[CPMHSIZE];
2003 
2004 int
2005 cpmip(sep, ctrl)
2006 	struct servtab *sep;
2007 	int ctrl;
2008 {
2009 	struct sockaddr_storage rss;
2010 	int rssLen = sizeof(rss);
2011 	int r = 0;
2012 
2013 	/*
2014 	 * If getpeername() fails, just let it through (if logging is
2015 	 * enabled the condition is caught elsewhere)
2016 	 */
2017 
2018 	if (sep->se_maxcpm > 0 &&
2019 	    getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
2020 		time_t t = time(NULL);
2021 		int hv = 0xABC3D20F;
2022 		int i;
2023 		int cnt = 0;
2024 		CHash *chBest = NULL;
2025 		unsigned int ticks = t / CHTGRAN;
2026 		struct sockaddr_in *sin;
2027 #ifdef INET6
2028 		struct sockaddr_in6 *sin6;
2029 #endif
2030 
2031 		sin = (struct sockaddr_in *)&rss;
2032 #ifdef INET6
2033 		sin6 = (struct sockaddr_in6 *)&rss;
2034 #endif
2035 		{
2036 			char *p;
2037 			int i, addrlen;
2038 
2039 			switch (rss.ss_family) {
2040 			case AF_INET:
2041 				p = (char *)&sin->sin_addr;
2042 				addrlen = sizeof(struct in_addr);
2043 				break;
2044 #ifdef INET6
2045 			case AF_INET6:
2046 				p = (char *)&sin6->sin6_addr;
2047 				addrlen = sizeof(struct in6_addr);
2048 				break;
2049 #endif
2050 			default:
2051 				/* should not happen */
2052 				return -1;
2053 			}
2054 
2055 			for (i = 0; i < addrlen; ++i, ++p) {
2056 				hv = (hv << 5) ^ (hv >> 23) ^ *p;
2057 			}
2058 			hv = (hv ^ (hv >> 16));
2059 		}
2060 		for (i = 0; i < 5; ++i) {
2061 			CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2062 
2063 			if (rss.ss_family == AF_INET &&
2064 			    ch->ch_Family == AF_INET &&
2065 			    sin->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
2066 			    ch->ch_Service && strcmp(sep->se_service,
2067 			    ch->ch_Service) == 0) {
2068 				chBest = ch;
2069 				break;
2070 			}
2071 #ifdef INET6
2072 			if (rss.ss_family == AF_INET6 &&
2073 			    ch->ch_Family == AF_INET6 &&
2074 			    IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2075 					       &ch->ch_Addr6) != 0 &&
2076 			    ch->ch_Service && strcmp(sep->se_service,
2077 			    ch->ch_Service) == 0) {
2078 				chBest = ch;
2079 				break;
2080 			}
2081 #endif
2082 			if (chBest == NULL || ch->ch_LTime == 0 ||
2083 			    ch->ch_LTime < chBest->ch_LTime) {
2084 				chBest = ch;
2085 			}
2086 		}
2087 		if ((rss.ss_family == AF_INET &&
2088 		     (chBest->ch_Family != AF_INET ||
2089 		      sin->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
2090 		    chBest->ch_Service == NULL ||
2091 		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2092 			chBest->ch_Family = sin->sin_family;
2093 			chBest->ch_Addr4 = sin->sin_addr;
2094 			if (chBest->ch_Service)
2095 				free(chBest->ch_Service);
2096 			chBest->ch_Service = strdup(sep->se_service);
2097 			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2098 		}
2099 #ifdef INET6
2100 		if ((rss.ss_family == AF_INET6 &&
2101 		     (chBest->ch_Family != AF_INET6 ||
2102 		      IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2103 					 &chBest->ch_Addr6) == 0)) ||
2104 		    chBest->ch_Service == NULL ||
2105 		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2106 			chBest->ch_Family = sin6->sin6_family;
2107 			chBest->ch_Addr6 = sin6->sin6_addr;
2108 			if (chBest->ch_Service)
2109 				free(chBest->ch_Service);
2110 			chBest->ch_Service = strdup(sep->se_service);
2111 			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2112 		}
2113 #endif
2114 		chBest->ch_LTime = t;
2115 		{
2116 			CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2117 			if (ct->ct_Ticks != ticks) {
2118 				ct->ct_Ticks = ticks;
2119 				ct->ct_Count = 0;
2120 			}
2121 			++ct->ct_Count;
2122 		}
2123 		for (i = 0; i < CHTSIZE; ++i) {
2124 			CTime *ct = &chBest->ch_Times[i];
2125 			if (ct->ct_Ticks <= ticks &&
2126 			    ct->ct_Ticks >= ticks - CHTSIZE) {
2127 				cnt += ct->ct_Count;
2128 			}
2129 		}
2130 		if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
2131 			char pname[INET6_ADDRSTRLEN];
2132 
2133 			getnameinfo((struct sockaddr *)&rss,
2134 				    ((struct sockaddr *)&rss)->sa_len,
2135 				    pname, sizeof(pname), NULL, 0,
2136 				    NI_NUMERICHOST|NI_WITHSCOPEID);
2137 			r = -1;
2138 			syslog(LOG_ERR,
2139 			    "%s from %s exceeded counts/min (limit %d/min)",
2140 			    sep->se_service, pname,
2141 			    sep->se_maxcpm);
2142 		}
2143 	}
2144 	return(r);
2145 }
2146