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