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