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