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