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