xref: /freebsd/usr.sbin/inetd/inetd.c (revision ce4946daa5ce852d28008dac492029500ab2ee95)
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			tcp[4][6][/faith,ttcp], udp[4][6]
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			rpc/tcp, rpc/udp
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 	union {
279 		struct sockaddr peer_un;
280 		struct sockaddr_in peer_un4;
281 		struct sockaddr_in6 peer_un6;
282 		struct sockaddr_storage peer_max;
283 	} p_un;
284 #define peer	p_un.peer_un
285 #define peer4	p_un.peer_un4
286 #define peer6	p_un.peer_un6
287 #define peermax	p_un.peer_max
288 	int i;
289 	struct addrinfo hints, *res;
290 	char *servname;
291 	int error;
292 
293 
294 #ifdef OLD_SETPROCTITLE
295 	Argv = argv;
296 	if (envp == 0 || *envp == 0)
297 		envp = argv;
298 	while (*envp)
299 		envp++;
300 	LastArg = envp[-1] + strlen(envp[-1]);
301 #endif
302 
303 	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
304 
305 	while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:")) != -1)
306 		switch(ch) {
307 		case 'd':
308 			debug = 1;
309 			options |= SO_DEBUG;
310 			break;
311 		case 'l':
312 			log = 1;
313 			break;
314 		case 'R':
315 			getvalue(optarg, &toomany,
316 				"-R %s: bad value for service invocation rate");
317 			break;
318 		case 'c':
319 			getvalue(optarg, &maxchild,
320 				"-c %s: bad value for maximum children");
321 			break;
322 		case 'C':
323 			getvalue(optarg, &maxcpm,
324 				"-C %s: bad value for maximum children/minute");
325 			break;
326 		case 'a':
327 			hostname = optarg;
328 			break;
329 		case 'p':
330 			pid_file = optarg;
331 			break;
332 		case 'w':
333 			wrap_ex++;
334 			break;
335 		case 'W':
336 			wrap_bi++;
337 			break;
338 		case '?':
339 		default:
340 			syslog(LOG_ERR,
341 				"usage: inetd [-dlwW] [-a address] [-R rate]"
342 				" [-c maximum] [-C rate]"
343 				" [-p pidfile] [conf-file]");
344 			exit(EX_USAGE);
345 		}
346 	/*
347 	 * Initialize Bind Addrs.
348 	 *   When hostname is NULL, wild card bind addrs are obtained from
349 	 *   getaddrinfo(). But getaddrinfo() requires at least one of
350 	 *   hostname or servname is non NULL.
351 	 *   So when hostname is NULL, set dummy value to servname.
352 	 */
353 	servname = (hostname == NULL) ? "discard" /* dummy */ : NULL;
354 
355 	bzero(&hints, sizeof(struct addrinfo));
356 	hints.ai_flags = AI_PASSIVE;
357 	hints.ai_family = AF_UNSPEC;
358 	error = getaddrinfo(hostname, servname, &hints, &res);
359 	if (error != 0) {
360 		syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
361 		if (error == EAI_SYSTEM)
362 			syslog(LOG_ERR, "%s", strerror(errno));
363 		exit(EX_USAGE);
364 	}
365 	do {
366 		if (res->ai_addr == NULL) {
367 			syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
368 			exit(EX_USAGE);
369 		}
370 		switch (res->ai_addr->sa_family) {
371 		case AF_INET:
372 			if (no_v4bind == 0)
373 				continue;
374 			bind_sa4 = (struct sockaddr_in *)res->ai_addr;
375 			/* init port num in case servname is dummy */
376 			bind_sa4->sin_port = 0;
377 			no_v4bind = 0;
378 			continue;
379 #ifdef INET6
380 		case AF_INET6:
381 			if (no_v6bind == 0)
382 				continue;
383 			bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
384 			/* init port num in case servname is dummy */
385 			bind_sa6->sin6_port = 0;
386 			no_v6bind = 0;
387 			continue;
388 #endif
389 		}
390 		if (no_v4bind == 0
391 #ifdef INET6
392 		    && no_v6bind == 0
393 #endif
394 		    )
395 			break;
396 	} while ((res = res->ai_next) != NULL);
397 	if (no_v4bind != 0
398 #ifdef INET6
399 	    && no_v6bind != 0
400 #endif
401 	    ) {
402 		syslog(LOG_ERR, "-a %s: unknown address family", hostname);
403 		exit(EX_USAGE);
404 	}
405 
406 	argc -= optind;
407 	argv += optind;
408 
409 	if (argc > 0)
410 		CONFIG = argv[0];
411 	if (debug == 0) {
412 		FILE *fp;
413 		if (daemon(0, 0) < 0) {
414 			syslog(LOG_WARNING, "daemon(0,0) failed: %m");
415 		}
416 		/*
417 		 * In case somebody has started inetd manually, we need to
418 		 * clear the logname, so that old servers run as root do not
419 		 * get the user's logname..
420 		 */
421 		if (setlogin("") < 0) {
422 			syslog(LOG_WARNING, "cannot clear logname: %m");
423 			/* no big deal if it fails.. */
424 		}
425 		pid = getpid();
426 		fp = fopen(pid_file, "w");
427 		if (fp) {
428 			fprintf(fp, "%ld\n", (long)pid);
429 			fclose(fp);
430 		} else {
431 			syslog(LOG_WARNING, "%s: %m", pid_file);
432 		}
433 	}
434 	sa.sa_flags = 0;
435 	sigemptyset(&sa.sa_mask);
436 	sigaddset(&sa.sa_mask, SIGALRM);
437 	sigaddset(&sa.sa_mask, SIGCHLD);
438 	sigaddset(&sa.sa_mask, SIGHUP);
439 	sa.sa_handler = flag_retry;
440 	sigaction(SIGALRM, &sa, &saalrm);
441 	config();
442 	sa.sa_handler = flag_config;
443 	sigaction(SIGHUP, &sa, &sahup);
444 	sa.sa_handler = flag_reapchild;
445 	sigaction(SIGCHLD, &sa, &sachld);
446 	sa.sa_handler = SIG_IGN;
447 	sigaction(SIGPIPE, &sa, &sapipe);
448 
449 	{
450 		/* space for daemons to overwrite environment for ps */
451 #define	DUMMYSIZE	100
452 		char dummy[DUMMYSIZE];
453 
454 		(void)memset(dummy, 'x', DUMMYSIZE - 1);
455 		dummy[DUMMYSIZE - 1] = '\0';
456 		(void)setenv("inetd_dummy", dummy, 1);
457 	}
458 
459 	if (pipe(signalpipe) != 0) {
460 		syslog(LOG_ERR, "pipe: %m");
461 		exit(EX_OSERR);
462 	}
463 	FD_SET(signalpipe[0], &allsock);
464 #ifdef SANITY_CHECK
465 	nsock++;
466 #endif
467 	if (signalpipe[0] > maxsock)
468 	    maxsock = signalpipe[0];
469 	if (signalpipe[1] > maxsock)
470 	    maxsock = signalpipe[1];
471 
472 	for (;;) {
473 	    int n, ctrl;
474 	    fd_set readable;
475 
476 #ifdef SANITY_CHECK
477 	    if (nsock == 0) {
478 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
479 		exit(EX_SOFTWARE);
480 	    }
481 #endif
482 	    readable = allsock;
483 	    if ((n = select(maxsock + 1, &readable, (fd_set *)0,
484 		(fd_set *)0, (struct timeval *)0)) <= 0) {
485 		    if (n < 0 && errno != EINTR) {
486 			syslog(LOG_WARNING, "select: %m");
487 			sleep(1);
488 		    }
489 		    continue;
490 	    }
491 	    /* handle any queued signal flags */
492 	    if (FD_ISSET(signalpipe[0], &readable)) {
493 		int nsig;
494 		if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) {
495 		    syslog(LOG_ERR, "ioctl: %m");
496 		    exit(EX_OSERR);
497 		}
498 		while (--nsig >= 0) {
499 		    char c;
500 		    if (read(signalpipe[0], &c, 1) != 1) {
501 			syslog(LOG_ERR, "read: %m");
502 			exit(EX_OSERR);
503 		    }
504 		    if (debug)
505 			warnx("handling signal flag %c", c);
506 		    switch(c) {
507 		    case 'A': /* sigalrm */
508 			retry();
509 			break;
510 		    case 'C': /* sigchld */
511 			reapchild();
512 			break;
513 		    case 'H': /* sighup */
514 			config();
515 			break;
516 		    }
517 		}
518 	    }
519 	    for (sep = servtab; n && sep; sep = sep->se_next)
520 	        if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
521 		    n--;
522 		    if (debug)
523 			    warnx("someone wants %s", sep->se_service);
524 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
525 			    i = 1;
526 			    if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
527 				    syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m");
528 			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
529 				(socklen_t *)0);
530 			    if (debug)
531 				    warnx("accept, ctrl %d", ctrl);
532 			    if (ctrl < 0) {
533 				    if (errno != EINTR)
534 					    syslog(LOG_WARNING,
535 						"accept (for %s): %m",
536 						sep->se_service);
537                                       if (sep->se_accept &&
538                                           sep->se_socktype == SOCK_STREAM)
539                                               close(ctrl);
540 				    continue;
541 			    }
542 			    i = 0;
543 			    if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
544 				    syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m");
545 			    if (ioctl(ctrl, FIONBIO, &i) < 0)
546 				    syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m");
547 			    if (cpmip(sep, ctrl) < 0) {
548 				close(ctrl);
549 				continue;
550 			    }
551 		    } else
552 			    ctrl = sep->se_fd;
553 		    if (log && !ISWRAP(sep)) {
554 			    char pname[INET6_ADDRSTRLEN] = "unknown";
555 			    socklen_t sl;
556 			    sl = sizeof peermax;
557 			    if (getpeername(ctrl, (struct sockaddr *)
558 					    &peermax, &sl)) {
559 				    sl = sizeof peermax;
560 				    if (recvfrom(ctrl, buf, sizeof(buf),
561 					MSG_PEEK,
562 					(struct sockaddr *)&peermax,
563 					&sl) >= 0) {
564 				      getnameinfo((struct sockaddr *)&peermax,
565 						  peer.sa_len,
566 						  pname, sizeof(pname),
567 						  NULL, 0,
568 						  NI_NUMERICHOST|
569 						  NI_WITHSCOPEID);
570 				    }
571 			    } else {
572 			            getnameinfo((struct sockaddr *)&peermax,
573 						peer.sa_len,
574 						pname, sizeof(pname),
575 						NULL, 0,
576 						NI_NUMERICHOST|
577 						NI_WITHSCOPEID);
578 			    }
579 			    syslog(LOG_INFO,"%s from %s", sep->se_service, pname);
580 		    }
581 		    (void) sigblock(SIGBLOCK);
582 		    pid = 0;
583 		    /*
584 		     * Fork for all external services, builtins which need to
585 		     * fork and anything we're wrapping (as wrapping might
586 		     * block or use hosts_options(5) twist).
587 		     */
588 		    dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep);
589 		    if (dofork) {
590 			    if (sep->se_count++ == 0)
591 				(void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
592 			    else if (toomany > 0 && sep->se_count >= toomany) {
593 				struct timeval now;
594 
595 				(void)gettimeofday(&now, (struct timezone *)NULL);
596 				if (now.tv_sec - sep->se_time.tv_sec >
597 				    CNT_INTVL) {
598 					sep->se_time = now;
599 					sep->se_count = 1;
600 				} else {
601 					syslog(LOG_ERR,
602 			"%s/%s server failing (looping), service terminated",
603 					    sep->se_service, sep->se_proto);
604 					if (sep->se_accept &&
605 					    sep->se_socktype == SOCK_STREAM)
606 						close(ctrl);
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     int c;
785 {
786 	char ch = c;
787 
788 	if (write(signalpipe[1], &ch, 1) != 1) {
789 		syslog(LOG_ERR, "write: %m");
790 		_exit(EX_OSERR);
791 	}
792 }
793 
794 /*
795  * Record a new child pid for this service. If we've reached the
796  * limit on children, then stop accepting incoming requests.
797  */
798 
799 void
800 addchild(struct servtab *sep, pid_t pid)
801 {
802 	if (sep->se_maxchild <= 0)
803 		return;
804 #ifdef SANITY_CHECK
805 	if (sep->se_numchild >= sep->se_maxchild) {
806 		syslog(LOG_ERR, "%s: %d >= %d",
807 		    __FUNCTION__, sep->se_numchild, sep->se_maxchild);
808 		exit(EX_SOFTWARE);
809 	}
810 #endif
811 	sep->se_pids[sep->se_numchild++] = pid;
812 	if (sep->se_numchild == sep->se_maxchild)
813 		disable(sep);
814 }
815 
816 /*
817  * Some child process has exited. See if it's on somebody's list.
818  */
819 
820 void
821 flag_reapchild(signo)
822 	int signo;
823 {
824 	flag_signal('C');
825 }
826 
827 void
828 reapchild()
829 {
830 	int k, status;
831 	pid_t pid;
832 	struct servtab *sep;
833 
834 	for (;;) {
835 		pid = wait3(&status, WNOHANG, (struct rusage *)0);
836 		if (pid <= 0)
837 			break;
838 		if (debug)
839 			warnx("%d reaped, status %#x", pid, status);
840 		for (sep = servtab; sep; sep = sep->se_next) {
841 			for (k = 0; k < sep->se_numchild; k++)
842 				if (sep->se_pids[k] == pid)
843 					break;
844 			if (k == sep->se_numchild)
845 				continue;
846 			if (sep->se_numchild == sep->se_maxchild)
847 				enable(sep);
848 			sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
849 			if (status)
850 				syslog(LOG_WARNING,
851 				    "%s[%d]: exit status 0x%x",
852 				    sep->se_server, pid, status);
853 			break;
854 		}
855 	}
856 }
857 
858 void
859 flag_config(signo)
860 	int signo;
861 {
862 	flag_signal('H');
863 }
864 
865 void config()
866 {
867 	struct servtab *sep, *new, **sepp;
868 	long omask;
869 
870 	if (!setconfig()) {
871 		syslog(LOG_ERR, "%s: %m", CONFIG);
872 		return;
873 	}
874 	for (sep = servtab; sep; sep = sep->se_next)
875 		sep->se_checked = 0;
876 	while ((new = getconfigent())) {
877 		if (getpwnam(new->se_user) == NULL) {
878 			syslog(LOG_ERR,
879 				"%s/%s: no such user '%s', service ignored",
880 				new->se_service, new->se_proto, new->se_user);
881 			continue;
882 		}
883 		if (new->se_group && getgrnam(new->se_group) == NULL) {
884 			syslog(LOG_ERR,
885 				"%s/%s: no such group '%s', service ignored",
886 				new->se_service, new->se_proto, new->se_group);
887 			continue;
888 		}
889 #ifdef LOGIN_CAP
890 		if (login_getclass(new->se_class) == NULL) {
891 			/* error syslogged by getclass */
892 			syslog(LOG_ERR,
893 				"%s/%s: %s: login class error, service ignored",
894 				new->se_service, new->se_proto, new->se_class);
895 			continue;
896 		}
897 #endif
898 		for (sep = servtab; sep; sep = sep->se_next)
899 			if (strcmp(sep->se_service, new->se_service) == 0 &&
900 			    strcmp(sep->se_proto, new->se_proto) == 0 &&
901 			    sep->se_family == new->se_family)
902 				break;
903 		if (sep != 0) {
904 			int i;
905 
906 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
907 			omask = sigblock(SIGBLOCK);
908 			if (sep->se_nomapped != new->se_nomapped) {
909 				sep->se_nomapped = new->se_nomapped;
910 				sep->se_reset = 1;
911 			}
912 			/* copy over outstanding child pids */
913 			if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
914 				new->se_numchild = sep->se_numchild;
915 				if (new->se_numchild > new->se_maxchild)
916 					new->se_numchild = new->se_maxchild;
917 				memcpy(new->se_pids, sep->se_pids,
918 				    new->se_numchild * sizeof(*new->se_pids));
919 			}
920 			SWAP(sep->se_pids, new->se_pids);
921 			sep->se_maxchild = new->se_maxchild;
922 			sep->se_numchild = new->se_numchild;
923 			sep->se_maxcpm = new->se_maxcpm;
924 			sep->se_bi = new->se_bi;
925 			/* might need to turn on or off service now */
926 			if (sep->se_fd >= 0) {
927 			      if (sep->se_maxchild > 0
928 				  && sep->se_numchild == sep->se_maxchild) {
929 				      if (FD_ISSET(sep->se_fd, &allsock))
930 					  disable(sep);
931 			      } else {
932 				      if (!FD_ISSET(sep->se_fd, &allsock))
933 					  enable(sep);
934 			      }
935 			}
936 			sep->se_accept = new->se_accept;
937 			SWAP(sep->se_user, new->se_user);
938 			SWAP(sep->se_group, new->se_group);
939 #ifdef LOGIN_CAP
940 			SWAP(sep->se_class, new->se_class);
941 #endif
942 			SWAP(sep->se_server, new->se_server);
943 			SWAP(sep->se_server_name, new->se_server_name);
944 			for (i = 0; i < MAXARGV; i++)
945 				SWAP(sep->se_argv[i], new->se_argv[i]);
946 #ifdef IPSEC
947 			SWAP(sep->se_policy, new->se_policy);
948 			ipsecsetup(sep);
949 #endif
950 			sigsetmask(omask);
951 			freeconfig(new);
952 			if (debug)
953 				print_service("REDO", sep);
954 		} else {
955 			sep = enter(new);
956 			if (debug)
957 				print_service("ADD ", sep);
958 		}
959 		sep->se_checked = 1;
960 		if (ISMUX(sep)) {
961 			sep->se_fd = -1;
962 			continue;
963 		}
964 		switch (sep->se_family) {
965 		case AF_INET:
966 			if (no_v4bind != 0) {
967 				sep->se_fd = -1;
968 				continue;
969 			}
970 			break;
971 #ifdef INET6
972 		case AF_INET6:
973 			if (no_v6bind != 0) {
974 				sep->se_fd = -1;
975 				continue;
976 			}
977 			break;
978 #endif
979 		}
980 		if (!sep->se_rpc) {
981 			sp = getservbyname(sep->se_service, sep->se_proto);
982 			if (sp == 0) {
983 				syslog(LOG_ERR, "%s/%s: unknown service",
984 				sep->se_service, sep->se_proto);
985 				sep->se_checked = 0;
986 				continue;
987 			}
988 			switch (sep->se_family) {
989 			case AF_INET:
990 				if (sep->se_ctladdrinitok == 0) {
991 					memcpy(&sep->se_ctrladdr4, bind_sa4,
992 					       sizeof(sep->se_ctrladdr4));
993 					sep->se_ctrladdr_size =
994 						sizeof(sep->se_ctrladdr4);
995 				}
996 				if (sp->s_port != sep->se_ctrladdr4.sin_port) {
997 					sep->se_ctrladdr4.sin_port =
998 						sp->s_port;
999 					sep->se_reset = 1;
1000 				}
1001 				break;
1002 #ifdef INET6
1003 			case AF_INET6:
1004 				if (sep->se_ctladdrinitok == 0) {
1005 					memcpy(&sep->se_ctrladdr6, bind_sa6,
1006 					       sizeof(sep->se_ctrladdr6));
1007 					sep->se_ctrladdr_size =
1008 						sizeof(sep->se_ctrladdr6);
1009 				}
1010 				if (sp->s_port !=
1011 				    sep->se_ctrladdr6.sin6_port) {
1012 					sep->se_ctrladdr6.sin6_port =
1013 						sp->s_port;
1014 					sep->se_reset = 1;
1015 				}
1016 				break;
1017 #endif
1018 			}
1019 			if (sep->se_reset != 0 && sep->se_fd >= 0)
1020 				close_sep(sep);
1021 		} else {
1022 			rpc = getrpcbyname(sep->se_service);
1023 			if (rpc == 0) {
1024 				syslog(LOG_ERR, "%s/%s unknown RPC service",
1025 					sep->se_service, sep->se_proto);
1026 				if (sep->se_fd != -1)
1027 					(void) close(sep->se_fd);
1028 				sep->se_fd = -1;
1029 					continue;
1030 			}
1031 			if (rpc->r_number != sep->se_rpc_prog) {
1032 				if (sep->se_rpc_prog)
1033 					unregisterrpc(sep);
1034 				sep->se_rpc_prog = rpc->r_number;
1035 				if (sep->se_fd != -1)
1036 					(void) close(sep->se_fd);
1037 				sep->se_fd = -1;
1038 			}
1039 		}
1040 		if (sep->se_fd == -1)
1041 			setup(sep);
1042 	}
1043 	endconfig();
1044 	/*
1045 	 * Purge anything not looked at above.
1046 	 */
1047 	omask = sigblock(SIGBLOCK);
1048 	sepp = &servtab;
1049 	while ((sep = *sepp)) {
1050 		if (sep->se_checked) {
1051 			sepp = &sep->se_next;
1052 			continue;
1053 		}
1054 		*sepp = sep->se_next;
1055 		if (sep->se_fd >= 0)
1056 			close_sep(sep);
1057 		if (debug)
1058 			print_service("FREE", sep);
1059 		if (sep->se_rpc && sep->se_rpc_prog > 0)
1060 			unregisterrpc(sep);
1061 		freeconfig(sep);
1062 		free(sep);
1063 	}
1064 	(void) sigsetmask(omask);
1065 }
1066 
1067 void
1068 unregisterrpc(sep)
1069 	struct servtab *sep;
1070 {
1071         int i;
1072         struct servtab *sepp;
1073 	long omask;
1074 
1075 	omask = sigblock(SIGBLOCK);
1076         for (sepp = servtab; sepp; sepp = sepp->se_next) {
1077                 if (sepp == sep)
1078                         continue;
1079 		if (sep->se_checked == 0 ||
1080                     !sepp->se_rpc ||
1081                     sep->se_rpc_prog != sepp->se_rpc_prog)
1082 			continue;
1083                 return;
1084         }
1085         if (debug)
1086                 print_service("UNREG", sep);
1087         for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++)
1088                 pmap_unset(sep->se_rpc_prog, i);
1089         if (sep->se_fd != -1)
1090                 (void) close(sep->se_fd);
1091         sep->se_fd = -1;
1092 	(void) sigsetmask(omask);
1093 }
1094 
1095 void
1096 flag_retry(signo)
1097 	int signo;
1098 {
1099 	flag_signal('A');
1100 }
1101 
1102 void
1103 retry()
1104 {
1105 	struct servtab *sep;
1106 
1107 	timingout = 0;
1108 	for (sep = servtab; sep; sep = sep->se_next)
1109 		if (sep->se_fd == -1 && !ISMUX(sep))
1110 			setup(sep);
1111 }
1112 
1113 void
1114 setup(sep)
1115 	struct servtab *sep;
1116 {
1117 	int on = 1;
1118 
1119 	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1120 		if (debug)
1121 			warn("socket failed on %s/%s",
1122 				sep->se_service, sep->se_proto);
1123 		syslog(LOG_ERR, "%s/%s: socket: %m",
1124 		    sep->se_service, sep->se_proto);
1125 		return;
1126 	}
1127 #define	turnon(fd, opt) \
1128 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1129 	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1130 	    turnon(sep->se_fd, SO_DEBUG) < 0)
1131 		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1132 	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1133 		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1134 #ifdef SO_PRIVSTATE
1135 	if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1136 		syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1137 #endif
1138 	/* tftpd opens a new connection then needs more infos */
1139 	if ((sep->se_family == AF_INET6) &&
1140 	    (strcmp(sep->se_proto, "udp") == 0) &&
1141 	    (sep->se_accept == 0) &&
1142 	    (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO,
1143 			(char *)&on, sizeof (on)) < 0))
1144 		syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
1145 #ifdef IPV6_BINDV6ONLY
1146 	if (sep->se_family == AF_INET6) {
1147 		int flag = sep->se_nomapped ? 1 : 0;
1148 		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
1149 			       (char *)&flag, sizeof (flag)) < 0)
1150 			syslog(LOG_ERR, "setsockopt (IPV6_BINDV6ONLY): %m");
1151 	}
1152 #endif /* IPV6_BINDV6ONLY */
1153 #undef turnon
1154 	if (sep->se_type == TTCP_TYPE)
1155 		if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1156 		    (char *)&on, sizeof (on)) < 0)
1157 			syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1158 #ifdef IPV6_FAITH
1159 	if (sep->se_type == FAITH_TYPE) {
1160 		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
1161 				sizeof(on)) < 0) {
1162 			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1163 		}
1164 	}
1165 #endif
1166 #ifdef IPSEC
1167 	ipsecsetup(sep);
1168 #endif
1169 	if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1170 	    sep->se_ctrladdr_size) < 0) {
1171 		if (debug)
1172 			warn("bind failed on %s/%s",
1173 				sep->se_service, sep->se_proto);
1174 		syslog(LOG_ERR, "%s/%s: bind: %m",
1175 		    sep->se_service, sep->se_proto);
1176 		(void) close(sep->se_fd);
1177 		sep->se_fd = -1;
1178 		if (!timingout) {
1179 			timingout = 1;
1180 			alarm(RETRYTIME);
1181 		}
1182 		return;
1183 	}
1184         if (sep->se_rpc) {
1185 		int i;
1186 		socklen_t 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(sep)
1354 	struct servtab *sep;
1355 {
1356 	if (debug)
1357 		warnx(
1358 		    "enabling %s, fd %d", sep->se_service, sep->se_fd);
1359 #ifdef SANITY_CHECK
1360 	if (sep->se_fd < 0) {
1361 		syslog(LOG_ERR,
1362 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1363 		exit(EX_SOFTWARE);
1364 	}
1365 	if (ISMUX(sep)) {
1366 		syslog(LOG_ERR,
1367 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1368 		exit(EX_SOFTWARE);
1369 	}
1370 	if (FD_ISSET(sep->se_fd, &allsock)) {
1371 		syslog(LOG_ERR,
1372 		    "%s: %s: not off", __FUNCTION__, sep->se_service);
1373 		exit(EX_SOFTWARE);
1374 	}
1375 	nsock++;
1376 #endif
1377 	FD_SET(sep->se_fd, &allsock);
1378 	if (sep->se_fd > maxsock)
1379 		maxsock = sep->se_fd;
1380 }
1381 
1382 void
1383 disable(sep)
1384 	struct servtab *sep;
1385 {
1386 	if (debug)
1387 		warnx(
1388 		    "disabling %s, fd %d", sep->se_service, sep->se_fd);
1389 #ifdef SANITY_CHECK
1390 	if (sep->se_fd < 0) {
1391 		syslog(LOG_ERR,
1392 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1393 		exit(EX_SOFTWARE);
1394 	}
1395 	if (ISMUX(sep)) {
1396 		syslog(LOG_ERR,
1397 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1398 		exit(EX_SOFTWARE);
1399 	}
1400 	if (!FD_ISSET(sep->se_fd, &allsock)) {
1401 		syslog(LOG_ERR,
1402 		    "%s: %s: not on", __FUNCTION__, sep->se_service);
1403 		exit(EX_SOFTWARE);
1404 	}
1405 	if (nsock == 0) {
1406 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
1407 		exit(EX_SOFTWARE);
1408 	}
1409 	nsock--;
1410 #endif
1411 	FD_CLR(sep->se_fd, &allsock);
1412 	if (sep->se_fd == maxsock)
1413 		maxsock--;
1414 }
1415 
1416 FILE	*fconfig = NULL;
1417 struct	servtab serv;
1418 char	line[LINE_MAX];
1419 
1420 int
1421 setconfig()
1422 {
1423 
1424 	if (fconfig != NULL) {
1425 		fseek(fconfig, 0L, SEEK_SET);
1426 		return (1);
1427 	}
1428 	fconfig = fopen(CONFIG, "r");
1429 	return (fconfig != NULL);
1430 }
1431 
1432 void
1433 endconfig()
1434 {
1435 	if (fconfig) {
1436 		(void) fclose(fconfig);
1437 		fconfig = NULL;
1438 	}
1439 }
1440 
1441 struct servtab *
1442 getconfigent()
1443 {
1444 	struct servtab *sep = &serv;
1445 	int argc;
1446 	char *cp, *arg, *s;
1447 	char *versp;
1448 	static char TCPMUX_TOKEN[] = "tcpmux/";
1449 #define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1450 #ifdef IPSEC
1451 	char *policy = NULL;
1452 #endif
1453 	int v4bind = 0;
1454 #ifdef INET6
1455 	int v6bind = 0;
1456 #endif
1457 
1458 more:
1459 	while ((cp = nextline(fconfig)) != NULL) {
1460 #ifdef IPSEC
1461 		/* lines starting with #@ is not a comment, but the policy */
1462 		if (cp[0] == '#' && cp[1] == '@') {
1463 			char *p;
1464 			for (p = cp + 2; p && *p && isspace(*p); p++)
1465 				;
1466 			if (*p == '\0') {
1467 				if (policy)
1468 					free(policy);
1469 				policy = NULL;
1470 			} else if (ipsec_get_policylen(p) >= 0) {
1471 				if (policy)
1472 					free(policy);
1473 				policy = newstr(p);
1474 			} else {
1475 				syslog(LOG_ERR,
1476 					"%s: invalid ipsec policy \"%s\"",
1477 					CONFIG, p);
1478 				exit(EX_CONFIG);
1479 			}
1480 		}
1481 #endif
1482 		if (*cp == '#' || *cp == '\0')
1483 			continue;
1484 		break;
1485 	}
1486 	if (cp == NULL)
1487 		return ((struct servtab *)0);
1488 	/*
1489 	 * clear the static buffer, since some fields (se_ctrladdr,
1490 	 * for example) don't get initialized here.
1491 	 */
1492 	memset(sep, 0, sizeof *sep);
1493 	arg = skip(&cp);
1494 	if (cp == NULL) {
1495 		/* got an empty line containing just blanks/tabs. */
1496 		goto more;
1497 	}
1498 	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1499 		char *c = arg + MUX_LEN;
1500 		if (*c == '+') {
1501 			sep->se_type = MUXPLUS_TYPE;
1502 			c++;
1503 		} else
1504 			sep->se_type = MUX_TYPE;
1505 		sep->se_service = newstr(c);
1506 	} else {
1507 		sep->se_service = newstr(arg);
1508 		sep->se_type = NORM_TYPE;
1509 	}
1510 	arg = sskip(&cp);
1511 	if (strcmp(arg, "stream") == 0)
1512 		sep->se_socktype = SOCK_STREAM;
1513 	else if (strcmp(arg, "dgram") == 0)
1514 		sep->se_socktype = SOCK_DGRAM;
1515 	else if (strcmp(arg, "rdm") == 0)
1516 		sep->se_socktype = SOCK_RDM;
1517 	else if (strcmp(arg, "seqpacket") == 0)
1518 		sep->se_socktype = SOCK_SEQPACKET;
1519 	else if (strcmp(arg, "raw") == 0)
1520 		sep->se_socktype = SOCK_RAW;
1521 	else
1522 		sep->se_socktype = -1;
1523 
1524 	arg = sskip(&cp);
1525 	if (strncmp(arg, "tcp", 3) == 0) {
1526 		sep->se_proto = newstr(strsep(&arg, "/"));
1527 		if (arg != NULL) {
1528 			if (strcmp(arg, "ttcp") == 0)
1529 				sep->se_type = TTCP_TYPE;
1530 			else if (strcmp(arg, "faith") == 0)
1531 				sep->se_type = FAITH_TYPE;
1532 		}
1533 	} else
1534 		sep->se_proto = newstr(arg);
1535         if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1536 		if (no_v4bind != 0) {
1537 			syslog(LOG_INFO, "IPv4 bind is ignored for %s",
1538 			       sep->se_service);
1539 			freeconfig(sep);
1540 			goto more;
1541 		}
1542                 memmove(sep->se_proto, sep->se_proto + 4,
1543                     strlen(sep->se_proto) + 1 - 4);
1544                 sep->se_rpc = 1;
1545                 sep->se_rpc_prog = sep->se_rpc_lowvers =
1546 			sep->se_rpc_lowvers = 0;
1547 		memcpy(&sep->se_ctrladdr4, bind_sa4,
1548 		       sizeof(sep->se_ctrladdr4));
1549                 if ((versp = rindex(sep->se_service, '/'))) {
1550                         *versp++ = '\0';
1551                         switch (sscanf(versp, "%d-%d",
1552                                        &sep->se_rpc_lowvers,
1553                                        &sep->se_rpc_highvers)) {
1554                         case 2:
1555                                 break;
1556                         case 1:
1557                                 sep->se_rpc_highvers =
1558                                         sep->se_rpc_lowvers;
1559                                 break;
1560                         default:
1561                                 syslog(LOG_ERR,
1562 					"bad RPC version specifier; %s",
1563 					sep->se_service);
1564                                 freeconfig(sep);
1565                                 goto more;
1566                         }
1567                 }
1568                 else {
1569                         sep->se_rpc_lowvers =
1570                                 sep->se_rpc_highvers = 1;
1571                 }
1572         }
1573 	sep->se_nomapped = 0;
1574 	while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
1575 #ifdef INET6
1576 		if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
1577 			if (no_v6bind != 0) {
1578 				syslog(LOG_INFO, "IPv6 bind is ignored for %s",
1579 				       sep->se_service);
1580 				freeconfig(sep);
1581 				goto more;
1582 			}
1583 			sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1584 			v6bind = 1;
1585 			continue;
1586 		}
1587 #endif
1588 		if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
1589 			sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1590 			v4bind = 1;
1591 			continue;
1592 		}
1593 		/* illegal version num */
1594 		syslog(LOG_ERR,	"bad IP version for %s", sep->se_proto);
1595 		freeconfig(sep);
1596 		goto more;
1597 	}
1598 #ifdef INET6
1599 	if (v6bind != 0) {
1600 		sep->se_family = AF_INET6;
1601 		if (v4bind == 0 || no_v4bind != 0)
1602 			sep->se_nomapped = 1;
1603 	} else
1604 #endif
1605 	{ /* default to v4 bind if not v6 bind */
1606 		if (no_v4bind != 0) {
1607 			syslog(LOG_INFO, "IPv4 bind is ignored for %s",
1608 			       sep->se_service);
1609 			freeconfig(sep);
1610 			goto more;
1611 		}
1612 		sep->se_family = AF_INET;
1613 	}
1614 	/* init ctladdr */
1615 	switch(sep->se_family) {
1616 	case AF_INET:
1617 		memcpy(&sep->se_ctrladdr4, bind_sa4,
1618 		       sizeof(sep->se_ctrladdr4));
1619 		sep->se_ctrladdr_size =	sizeof(sep->se_ctrladdr4);
1620 		sep->se_ctladdrinitok = 1;
1621 		break;
1622 #ifdef INET6
1623 	case AF_INET6:
1624 		memcpy(&sep->se_ctrladdr6, bind_sa6,
1625 		       sizeof(sep->se_ctrladdr6));
1626 		sep->se_ctrladdr_size =	sizeof(sep->se_ctrladdr6);
1627 		sep->se_ctladdrinitok = 1;
1628 		break;
1629 #endif
1630 	}
1631 	arg = sskip(&cp);
1632 	if (!strncmp(arg, "wait", 4))
1633 		sep->se_accept = 0;
1634 	else if (!strncmp(arg, "nowait", 6))
1635 		sep->se_accept = 1;
1636 	else {
1637 		syslog(LOG_ERR,
1638 			"%s: bad wait/nowait for service %s",
1639 			CONFIG, sep->se_service);
1640 		goto more;
1641 	}
1642 	sep->se_maxchild = -1;
1643 	sep->se_maxcpm = -1;
1644 	if ((s = strchr(arg, '/')) != NULL) {
1645 		char *eptr;
1646 		u_long val;
1647 
1648 		val = strtoul(s + 1, &eptr, 10);
1649 		if (eptr == s + 1 || val > MAX_MAXCHLD) {
1650 			syslog(LOG_ERR,
1651 				"%s: bad max-child for service %s",
1652 				CONFIG, sep->se_service);
1653 			goto more;
1654 		}
1655 		if (debug)
1656 			if (!sep->se_accept && val != 1)
1657 				warnx("maxchild=%lu for wait service %s"
1658 				    " not recommended", val, sep->se_service);
1659 		sep->se_maxchild = val;
1660 		if (*eptr == '/')
1661 			sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1662 		/*
1663 		 * explicitly do not check for \0 for future expansion /
1664 		 * backwards compatibility
1665 		 */
1666 	}
1667 	if (ISMUX(sep)) {
1668 		/*
1669 		 * Silently enforce "nowait" mode for TCPMUX services
1670 		 * since they don't have an assigned port to listen on.
1671 		 */
1672 		sep->se_accept = 1;
1673 		if (strcmp(sep->se_proto, "tcp")) {
1674 			syslog(LOG_ERR,
1675 				"%s: bad protocol for tcpmux service %s",
1676 				CONFIG, sep->se_service);
1677 			goto more;
1678 		}
1679 		if (sep->se_socktype != SOCK_STREAM) {
1680 			syslog(LOG_ERR,
1681 				"%s: bad socket type for tcpmux service %s",
1682 				CONFIG, sep->se_service);
1683 			goto more;
1684 		}
1685 	}
1686 	sep->se_user = newstr(sskip(&cp));
1687 #ifdef LOGIN_CAP
1688 	if ((s = strrchr(sep->se_user, '/')) != NULL) {
1689 		*s = '\0';
1690 		sep->se_class = newstr(s + 1);
1691 	} else
1692 		sep->se_class = newstr(RESOURCE_RC);
1693 #endif
1694 	if ((s = strrchr(sep->se_user, ':')) != NULL) {
1695 		*s = '\0';
1696 		sep->se_group = newstr(s + 1);
1697 	} else
1698 		sep->se_group = NULL;
1699 	sep->se_server = newstr(sskip(&cp));
1700 	if ((sep->se_server_name = rindex(sep->se_server, '/')))
1701 		sep->se_server_name++;
1702 	if (strcmp(sep->se_server, "internal") == 0) {
1703 		struct biltin *bi;
1704 
1705 		for (bi = biltins; bi->bi_service; bi++)
1706 			if (bi->bi_socktype == sep->se_socktype &&
1707 			    matchservent(bi->bi_service, sep->se_service,
1708 			    sep->se_proto))
1709 				break;
1710 		if (bi->bi_service == 0) {
1711 			syslog(LOG_ERR, "internal service %s unknown",
1712 				sep->se_service);
1713 			goto more;
1714 		}
1715 		sep->se_accept = 1;	/* force accept mode for built-ins */
1716 		sep->se_bi = bi;
1717 	} else
1718 		sep->se_bi = NULL;
1719 	if (sep->se_maxcpm < 0)
1720 		sep->se_maxcpm = maxcpm;
1721 	if (sep->se_maxchild < 0) {	/* apply default max-children */
1722 		if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1723 			sep->se_maxchild = sep->se_bi->bi_maxchild;
1724 		else if (sep->se_accept)
1725 			sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1726 		else
1727 			sep->se_maxchild = 1;
1728 	}
1729 	if (sep->se_maxchild > 0) {
1730 		sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1731 		if (sep->se_pids == NULL) {
1732 			syslog(LOG_ERR, "malloc: %m");
1733 			exit(EX_OSERR);
1734 		}
1735 	}
1736 	argc = 0;
1737 	for (arg = skip(&cp); cp; arg = skip(&cp))
1738 		if (argc < MAXARGV) {
1739 			sep->se_argv[argc++] = newstr(arg);
1740 		} else {
1741 			syslog(LOG_ERR,
1742 				"%s: too many arguments for service %s",
1743 				CONFIG, sep->se_service);
1744 			goto more;
1745 		}
1746 	while (argc <= MAXARGV)
1747 		sep->se_argv[argc++] = NULL;
1748 #ifdef IPSEC
1749 	sep->se_policy = policy ? newstr(policy) : NULL;
1750 #endif
1751 	return (sep);
1752 }
1753 
1754 void
1755 freeconfig(cp)
1756 	struct servtab *cp;
1757 {
1758 	int i;
1759 
1760 	if (cp->se_service)
1761 		free(cp->se_service);
1762 	if (cp->se_proto)
1763 		free(cp->se_proto);
1764 	if (cp->se_user)
1765 		free(cp->se_user);
1766 	if (cp->se_group)
1767 		free(cp->se_group);
1768 #ifdef LOGIN_CAP
1769 	if (cp->se_class)
1770 		free(cp->se_class);
1771 #endif
1772 	if (cp->se_server)
1773 		free(cp->se_server);
1774 	if (cp->se_pids)
1775 		free(cp->se_pids);
1776 	for (i = 0; i < MAXARGV; i++)
1777 		if (cp->se_argv[i])
1778 			free(cp->se_argv[i]);
1779 #ifdef IPSEC
1780 	if (cp->se_policy)
1781 		free(cp->se_policy);
1782 #endif
1783 }
1784 
1785 
1786 /*
1787  * Safe skip - if skip returns null, log a syntax error in the
1788  * configuration file and exit.
1789  */
1790 char *
1791 sskip(cpp)
1792 	char **cpp;
1793 {
1794 	char *cp;
1795 
1796 	cp = skip(cpp);
1797 	if (cp == NULL) {
1798 		syslog(LOG_ERR, "%s: syntax error", CONFIG);
1799 		exit(EX_DATAERR);
1800 	}
1801 	return (cp);
1802 }
1803 
1804 char *
1805 skip(cpp)
1806 	char **cpp;
1807 {
1808 	char *cp = *cpp;
1809 	char *start;
1810 	char quote = '\0';
1811 
1812 again:
1813 	while (*cp == ' ' || *cp == '\t')
1814 		cp++;
1815 	if (*cp == '\0') {
1816 		int c;
1817 
1818 		c = getc(fconfig);
1819 		(void) ungetc(c, fconfig);
1820 		if (c == ' ' || c == '\t')
1821 			if ((cp = nextline(fconfig)))
1822 				goto again;
1823 		*cpp = (char *)0;
1824 		return ((char *)0);
1825 	}
1826 	if (*cp == '"' || *cp == '\'')
1827 		quote = *cp++;
1828 	start = cp;
1829 	if (quote)
1830 		while (*cp && *cp != quote)
1831 			cp++;
1832 	else
1833 		while (*cp && *cp != ' ' && *cp != '\t')
1834 			cp++;
1835 	if (*cp != '\0')
1836 		*cp++ = '\0';
1837 	*cpp = cp;
1838 	return (start);
1839 }
1840 
1841 char *
1842 nextline(fd)
1843 	FILE *fd;
1844 {
1845 	char *cp;
1846 
1847 	if (fgets(line, sizeof (line), fd) == NULL)
1848 		return ((char *)0);
1849 	cp = strchr(line, '\n');
1850 	if (cp)
1851 		*cp = '\0';
1852 	return (line);
1853 }
1854 
1855 char *
1856 newstr(cp)
1857 	char *cp;
1858 {
1859 	if ((cp = strdup(cp ? cp : "")))
1860 		return (cp);
1861 	syslog(LOG_ERR, "strdup: %m");
1862 	exit(EX_OSERR);
1863 }
1864 
1865 #ifdef OLD_SETPROCTITLE
1866 void
1867 inetd_setproctitle(a, s)
1868 	char *a;
1869 	int s;
1870 {
1871 	int size;
1872 	char *cp;
1873 	struct sockaddr_storage ss;
1874 	char buf[80], pbuf[INET6_ADDRSTRLEN];
1875 
1876 	cp = Argv[0];
1877 	size = sizeof(ss);
1878 	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1879 		getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
1880 			    NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
1881 		(void) sprintf(buf, "-%s [%s]", a, pbuf);
1882 	} else
1883 		(void) sprintf(buf, "-%s", a);
1884 	strncpy(cp, buf, LastArg - cp);
1885 	cp += strlen(cp);
1886 	while (cp < LastArg)
1887 		*cp++ = ' ';
1888 }
1889 #else
1890 void
1891 inetd_setproctitle(a, s)
1892 	char *a;
1893 	int s;
1894 {
1895 	socklen_t size;
1896 	struct sockaddr_storage ss;
1897 	char buf[80], pbuf[INET6_ADDRSTRLEN];
1898 
1899 	size = sizeof(ss);
1900 	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1901 		getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
1902 			    NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
1903 		(void) sprintf(buf, "%s [%s]", a, pbuf);
1904 	} else
1905 		(void) sprintf(buf, "%s", a);
1906 	setproctitle("%s", buf);
1907 }
1908 #endif
1909 
1910 
1911 /*
1912  * Internet services provided internally by inetd:
1913  */
1914 
1915 int check_loop(sa, sep)
1916 	struct sockaddr *sa;
1917 	struct servtab *sep;
1918 {
1919 	struct servtab *se2;
1920 	char pname[INET6_ADDRSTRLEN];
1921 
1922 	for (se2 = servtab; se2; se2 = se2->se_next) {
1923 		if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
1924 			continue;
1925 
1926 		switch (se2->se_family) {
1927 		case AF_INET:
1928 			if (((struct sockaddr_in *)sa)->sin_port ==
1929 			    se2->se_ctrladdr4.sin_port)
1930 				goto isloop;
1931 			continue;
1932 #ifdef INET6
1933 		case AF_INET6:
1934 			if (((struct sockaddr_in *)sa)->sin_port ==
1935 			    se2->se_ctrladdr4.sin_port)
1936 				goto isloop;
1937 			continue;
1938 #endif
1939 		default:
1940 			continue;
1941 		}
1942 	isloop:
1943 		getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
1944 			    NI_NUMERICHOST|NI_WITHSCOPEID);
1945 		syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
1946 		       sep->se_service, sep->se_proto,
1947 		       se2->se_service, se2->se_proto,
1948 		       pname);
1949 		return 1;
1950 	}
1951 	return 0;
1952 }
1953 
1954 /*
1955  * print_service:
1956  *	Dump relevant information to stderr
1957  */
1958 void
1959 print_service(action, sep)
1960 	char *action;
1961 	struct servtab *sep;
1962 {
1963 	fprintf(stderr,
1964 	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
1965 #ifdef LOGIN_CAP
1966 	    "class=%s"
1967 #endif
1968 	    " builtin=%p server=%s"
1969 #ifdef IPSEC
1970 	    " policy=\"%s\""
1971 #endif
1972 	    "\n",
1973 	    action, sep->se_service, sep->se_proto,
1974 	    sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
1975 #ifdef LOGIN_CAP
1976 	    sep->se_class,
1977 #endif
1978 	    (void *) sep->se_bi, sep->se_server
1979 #ifdef IPSEC
1980 	    , (sep->se_policy ? sep->se_policy : "")
1981 #endif
1982 	    );
1983 }
1984 
1985 #define CPMHSIZE	256
1986 #define CPMHMASK	(CPMHSIZE-1)
1987 #define CHTGRAN		10
1988 #define CHTSIZE		6
1989 
1990 typedef struct CTime {
1991 	unsigned long 	ct_Ticks;
1992 	int		ct_Count;
1993 } CTime;
1994 
1995 typedef struct CHash {
1996 	union {
1997 		struct in_addr	c4_Addr;
1998 		struct in6_addr	c6_Addr;
1999 	} cu_Addr;
2000 #define	ch_Addr4	cu_Addr.c4_Addr
2001 #define	ch_Addr6	cu_Addr.c6_Addr
2002 	int		ch_Family;
2003 	time_t		ch_LTime;
2004 	char		*ch_Service;
2005 	CTime		ch_Times[CHTSIZE];
2006 } CHash;
2007 
2008 CHash	CHashAry[CPMHSIZE];
2009 
2010 int
2011 cpmip(sep, ctrl)
2012 	struct servtab *sep;
2013 	int ctrl;
2014 {
2015 	struct sockaddr_storage rss;
2016 	socklen_t rssLen = sizeof(rss);
2017 	int r = 0;
2018 
2019 	/*
2020 	 * If getpeername() fails, just let it through (if logging is
2021 	 * enabled the condition is caught elsewhere)
2022 	 */
2023 
2024 	if (sep->se_maxcpm > 0 &&
2025 	    getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
2026 		time_t t = time(NULL);
2027 		int hv = 0xABC3D20F;
2028 		int i;
2029 		int cnt = 0;
2030 		CHash *chBest = NULL;
2031 		unsigned int ticks = t / CHTGRAN;
2032 		struct sockaddr_in *sin;
2033 #ifdef INET6
2034 		struct sockaddr_in6 *sin6;
2035 #endif
2036 
2037 		sin = (struct sockaddr_in *)&rss;
2038 #ifdef INET6
2039 		sin6 = (struct sockaddr_in6 *)&rss;
2040 #endif
2041 		{
2042 			char *p;
2043 			int i, addrlen;
2044 
2045 			switch (rss.ss_family) {
2046 			case AF_INET:
2047 				p = (char *)&sin->sin_addr;
2048 				addrlen = sizeof(struct in_addr);
2049 				break;
2050 #ifdef INET6
2051 			case AF_INET6:
2052 				p = (char *)&sin6->sin6_addr;
2053 				addrlen = sizeof(struct in6_addr);
2054 				break;
2055 #endif
2056 			default:
2057 				/* should not happen */
2058 				return -1;
2059 			}
2060 
2061 			for (i = 0; i < addrlen; ++i, ++p) {
2062 				hv = (hv << 5) ^ (hv >> 23) ^ *p;
2063 			}
2064 			hv = (hv ^ (hv >> 16));
2065 		}
2066 		for (i = 0; i < 5; ++i) {
2067 			CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2068 
2069 			if (rss.ss_family == AF_INET &&
2070 			    ch->ch_Family == AF_INET &&
2071 			    sin->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
2072 			    ch->ch_Service && strcmp(sep->se_service,
2073 			    ch->ch_Service) == 0) {
2074 				chBest = ch;
2075 				break;
2076 			}
2077 #ifdef INET6
2078 			if (rss.ss_family == AF_INET6 &&
2079 			    ch->ch_Family == AF_INET6 &&
2080 			    IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2081 					       &ch->ch_Addr6) != 0 &&
2082 			    ch->ch_Service && strcmp(sep->se_service,
2083 			    ch->ch_Service) == 0) {
2084 				chBest = ch;
2085 				break;
2086 			}
2087 #endif
2088 			if (chBest == NULL || ch->ch_LTime == 0 ||
2089 			    ch->ch_LTime < chBest->ch_LTime) {
2090 				chBest = ch;
2091 			}
2092 		}
2093 		if ((rss.ss_family == AF_INET &&
2094 		     (chBest->ch_Family != AF_INET ||
2095 		      sin->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
2096 		    chBest->ch_Service == NULL ||
2097 		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2098 			chBest->ch_Family = sin->sin_family;
2099 			chBest->ch_Addr4 = sin->sin_addr;
2100 			if (chBest->ch_Service)
2101 				free(chBest->ch_Service);
2102 			chBest->ch_Service = strdup(sep->se_service);
2103 			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2104 		}
2105 #ifdef INET6
2106 		if ((rss.ss_family == AF_INET6 &&
2107 		     (chBest->ch_Family != AF_INET6 ||
2108 		      IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2109 					 &chBest->ch_Addr6) == 0)) ||
2110 		    chBest->ch_Service == NULL ||
2111 		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2112 			chBest->ch_Family = sin6->sin6_family;
2113 			chBest->ch_Addr6 = sin6->sin6_addr;
2114 			if (chBest->ch_Service)
2115 				free(chBest->ch_Service);
2116 			chBest->ch_Service = strdup(sep->se_service);
2117 			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2118 		}
2119 #endif
2120 		chBest->ch_LTime = t;
2121 		{
2122 			CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2123 			if (ct->ct_Ticks != ticks) {
2124 				ct->ct_Ticks = ticks;
2125 				ct->ct_Count = 0;
2126 			}
2127 			++ct->ct_Count;
2128 		}
2129 		for (i = 0; i < CHTSIZE; ++i) {
2130 			CTime *ct = &chBest->ch_Times[i];
2131 			if (ct->ct_Ticks <= ticks &&
2132 			    ct->ct_Ticks >= ticks - CHTSIZE) {
2133 				cnt += ct->ct_Count;
2134 			}
2135 		}
2136 		if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
2137 			char pname[INET6_ADDRSTRLEN];
2138 
2139 			getnameinfo((struct sockaddr *)&rss,
2140 				    ((struct sockaddr *)&rss)->sa_len,
2141 				    pname, sizeof(pname), NULL, 0,
2142 				    NI_NUMERICHOST|NI_WITHSCOPEID);
2143 			r = -1;
2144 			syslog(LOG_ERR,
2145 			    "%s from %s exceeded counts/min (limit %d/min)",
2146 			    sep->se_service, pname,
2147 			    sep->se_maxcpm);
2148 		}
2149 	}
2150 	return(r);
2151 }
2152