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