inetd.c revision 1.124
1/*	$NetBSD: inetd.c,v 1.124 2017/10/17 07:13:19 ozaki-r Exp $	*/
2
3/*-
4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Matthias Scheler.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1983, 1991, 1993, 1994
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 *    may be used to endorse or promote products derived from this software
47 *    without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62#include <sys/cdefs.h>
63#ifndef lint
64__COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\
65 The Regents of the University of California.  All rights reserved.");
66#if 0
67static char sccsid[] = "@(#)inetd.c	8.4 (Berkeley) 4/13/94";
68#else
69__RCSID("$NetBSD: inetd.c,v 1.124 2017/10/17 07:13:19 ozaki-r Exp $");
70#endif
71#endif /* not lint */
72
73/*
74 * Inetd - Internet super-server
75 *
76 * This program invokes all internet services as needed.  Connection-oriented
77 * services are invoked each time a connection is made, by creating a process.
78 * This process is passed the connection as file descriptor 0 and is expected
79 * to do a getpeername to find out the source host and port.
80 *
81 * Datagram oriented services are invoked when a datagram
82 * arrives; a process is created and passed a pending message
83 * on file descriptor 0.  Datagram servers may either connect
84 * to their peer, freeing up the original socket for inetd
85 * to receive further messages on, or ``take over the socket'',
86 * processing all arriving datagrams and, eventually, timing
87 * out.	 The first type of server is said to be ``multi-threaded'';
88 * the second type of server ``single-threaded''.
89 *
90 * Inetd uses a configuration file which is read at startup
91 * and, possibly, at some later time in response to a hangup signal.
92 * The configuration file is ``free format'' with fields given in the
93 * order shown below.  Continuation lines for an entry must being with
94 * a space or tab.  All fields must be present in each entry.
95 *
96 *	service name			must be in /etc/services or must
97 *					name a tcpmux service
98 *	socket type[:accf[,arg]]	stream/dgram/raw/rdm/seqpacket,
99					only stream can name an accept filter
100 *	protocol			must be in /etc/protocols
101 *	wait/nowait[:max]		single-threaded/multi-threaded, max #
102 *	user[:group]			user/group to run daemon as
103 *	server program			full path name
104 *	server program arguments	maximum of MAXARGS (20)
105 *
106 * For RPC services
107 *      service name/version            must be in /etc/rpc
108 *	socket type			stream/dgram/raw/rdm/seqpacket
109 *	protocol			must be in /etc/protocols
110 *	wait/nowait[:max]		single-threaded/multi-threaded
111 *	user[:group]			user to run daemon as
112 *	server program			full path name
113 *	server program arguments	maximum of MAXARGS (20)
114 *
115 * For non-RPC services, the "service name" can be of the form
116 * hostaddress:servicename, in which case the hostaddress is used
117 * as the host portion of the address to listen on.  If hostaddress
118 * consists of a single `*' character, INADDR_ANY is used.
119 *
120 * A line can also consist of just
121 *	hostaddress:
122 * where hostaddress is as in the preceding paragraph.  Such a line must
123 * have no further fields; the specified hostaddress is remembered and
124 * used for all further lines that have no hostaddress specified,
125 * until the next such line (or EOF).  (This is why * is provided to
126 * allow explicit specification of INADDR_ANY.)  A line
127 *	*:
128 * is implicitly in effect at the beginning of the file.
129 *
130 * The hostaddress specifier may (and often will) contain dots;
131 * the service name must not.
132 *
133 * For RPC services, host-address specifiers are accepted and will
134 * work to some extent; however, because of limitations in the
135 * portmapper interface, it will not work to try to give more than
136 * one line for any given RPC service, even if the host-address
137 * specifiers are different.
138 *
139 * TCP services without official port numbers are handled with the
140 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
141 * requests. When a connection is made from a foreign host, the service
142 * requested is passed to tcpmux, which looks it up in the servtab list
143 * and returns the proper entry for the service. Tcpmux returns a
144 * negative reply if the service doesn't exist, otherwise the invoked
145 * server is expected to return the positive reply if the service type in
146 * inetd.conf file has the prefix "tcpmux/". If the service type has the
147 * prefix "tcpmux/+", tcpmux will return the positive reply for the
148 * process; this is for compatibility with older server code, and also
149 * allows you to invoke programs that use stdin/stdout without putting any
150 * special server code in them. Services that use tcpmux are "nowait"
151 * because they do not have a well-known port and hence cannot listen
152 * for new requests.
153 *
154 * Comment lines are indicated by a `#' in column 1.
155 *
156 * #ifdef IPSEC
157 * Comment lines that start with "#@" denote IPsec policy string, as described
158 * in ipsec_set_policy(3).  This will affect all the following items in
159 * inetd.conf(8).  To reset the policy, just use "#@" line.  By default,
160 * there's no IPsec policy.
161 * #endif
162 */
163
164/*
165 * Here's the scoop concerning the user:group feature:
166 *
167 * 1) set-group-option off.
168 *
169 * 	a) user = root:	NO setuid() or setgid() is done
170 *
171 * 	b) other:	setuid()
172 * 			setgid(primary group as found in passwd)
173 * 			initgroups(name, primary group)
174 *
175 * 2) set-group-option on.
176 *
177 * 	a) user = root:	NO setuid()
178 * 			setgid(specified group)
179 * 			NO initgroups()
180 *
181 * 	b) other:	setuid()
182 * 			setgid(specified group)
183 * 			initgroups(name, specified group)
184 *
185 */
186
187#include <sys/param.h>
188#include <sys/stat.h>
189#include <sys/ioctl.h>
190#include <sys/socket.h>
191#include <sys/un.h>
192#include <sys/wait.h>
193#include <sys/time.h>
194#include <sys/resource.h>
195#include <sys/event.h>
196
197#ifndef NO_RPC
198#define RPC
199#endif
200
201#include <net/if.h>
202
203#include <netinet/in.h>
204#include <arpa/inet.h>
205#ifdef RPC
206#include <rpc/rpc.h>
207#include <rpc/rpcb_clnt.h>
208#include <netconfig.h>
209#endif
210
211#include <ctype.h>
212#include <errno.h>
213#include <fcntl.h>
214#include <grp.h>
215#include <netdb.h>
216#include <pwd.h>
217#include <signal.h>
218#include <stdio.h>
219#include <stdlib.h>
220#include <string.h>
221#include <syslog.h>
222#include <unistd.h>
223#include <util.h>
224#include <ifaddrs.h>
225
226#include "pathnames.h"
227
228#ifdef IPSEC
229#include <netipsec/ipsec.h>
230#ifndef IPSEC_POLICY_IPSEC	/* no ipsec support on old ipsec */
231#undef IPSEC
232#endif
233#include "ipsec.h"
234#endif
235
236#ifdef LIBWRAP
237# include <tcpd.h>
238#ifndef LIBWRAP_ALLOW_FACILITY
239# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
240#endif
241#ifndef LIBWRAP_ALLOW_SEVERITY
242# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
243#endif
244#ifndef LIBWRAP_DENY_FACILITY
245# define LIBWRAP_DENY_FACILITY LOG_AUTH
246#endif
247#ifndef LIBWRAP_DENY_SEVERITY
248# define LIBWRAP_DENY_SEVERITY LOG_WARNING
249#endif
250int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
251int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
252#endif
253
254#define	TOOMANY		40		/* don't start more than TOOMANY */
255#define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
256#define	RETRYTIME	(60*10)		/* retry after bind or server fail */
257
258#define	A_CNT(a)	(sizeof (a) / sizeof (a[0]))
259
260int	debug;
261#ifdef LIBWRAP
262int	lflag;
263#endif
264int	maxsock;
265int	kq;
266int	options;
267int	timingout;
268const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
269
270#ifndef OPEN_MAX
271#define OPEN_MAX	64
272#endif
273
274/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
275#define FD_MARGIN	(8)
276rlim_t		rlim_ofile_cur = OPEN_MAX;
277
278struct rlimit	rlim_ofile;
279
280struct kevent	changebuf[64];
281size_t		changes;
282
283struct	servtab {
284	char	*se_hostaddr;		/* host address to listen on */
285	char	*se_service;		/* name of service */
286	int	se_socktype;		/* type of socket to use */
287	int	se_family;		/* address family */
288	char	*se_proto;		/* protocol used */
289	int	se_sndbuf;		/* sndbuf size */
290	int	se_rcvbuf;		/* rcvbuf size */
291	int	se_rpcprog;		/* rpc program number */
292	int	se_rpcversl;		/* rpc program lowest version */
293	int	se_rpcversh;		/* rpc program highest version */
294#define isrpcservice(sep)	((sep)->se_rpcversl != 0)
295	pid_t	se_wait;		/* single threaded server */
296	short	se_checked;		/* looked at during merge */
297	char	*se_user;		/* user name to run as */
298	char	*se_group;		/* group name to run as */
299	struct	biltin *se_bi;		/* if built-in, description */
300	char	*se_server;		/* server program */
301#define	MAXARGV 20
302	char	*se_argv[MAXARGV+1];	/* program arguments */
303#ifdef IPSEC
304	char	*se_policy;		/* IPsec poilcy string */
305#endif
306	struct accept_filter_arg se_accf; /* accept filter for stream service */
307	int	se_fd;			/* open descriptor */
308	int	se_type;		/* type */
309	union {
310		struct	sockaddr se_un_ctrladdr;
311		struct	sockaddr_in se_un_ctrladdr_in;
312		struct	sockaddr_in6 se_un_ctrladdr_in6;
313		struct	sockaddr_un se_un_ctrladdr_un;
314	} se_un;			/* bound address */
315#define se_ctrladdr	se_un.se_un_ctrladdr
316#define se_ctrladdr_in	se_un.se_un_ctrladdr_in
317#define se_ctrladdr_un	se_un.se_un_ctrladdr_un
318	int	se_ctrladdr_size;
319	int	se_max;			/* max # of instances of this service */
320	int	se_count;		/* number started since se_time */
321	struct	timeval se_time;	/* start of se_count */
322	struct	servtab *se_next;
323} *servtab;
324
325#define NORM_TYPE	0
326#define MUX_TYPE	1
327#define MUXPLUS_TYPE	2
328#define FAITH_TYPE	3
329#define ISMUX(sep)	(((sep)->se_type == MUX_TYPE) || \
330			 ((sep)->se_type == MUXPLUS_TYPE))
331#define ISMUXPLUS(sep)	((sep)->se_type == MUXPLUS_TYPE)
332
333
334static void	chargen_dg(int, struct servtab *);
335static void	chargen_stream(int, struct servtab *);
336static void	close_sep(struct servtab *);
337static void	config(void);
338static void	daytime_dg(int, struct servtab *);
339static void	daytime_stream(int, struct servtab *);
340static void	discard_dg(int, struct servtab *);
341static void	discard_stream(int, struct servtab *);
342static void	echo_dg(int, struct servtab *);
343static void	echo_stream(int, struct servtab *);
344static void	endconfig(void);
345static struct servtab *enter(struct servtab *);
346static void	freeconfig(struct servtab *);
347static struct servtab *getconfigent(void);
348__dead static void	goaway(void);
349static void	machtime_dg(int, struct servtab *);
350static void	machtime_stream(int, struct servtab *);
351static char    *newstr(const char *);
352static char    *nextline(FILE *);
353static void	print_service(const char *, struct servtab *);
354static void	reapchild(void);
355static void	retry(void);
356static void	run_service(int, struct servtab *, int);
357static int	setconfig(void);
358static void	setup(struct servtab *);
359static char    *sskip(char **);
360static char    *skip(char **);
361static void	tcpmux(int, struct servtab *);
362__dead static void	usage(void);
363static void	register_rpc(struct servtab *);
364static void	unregister_rpc(struct servtab *);
365static void	bump_nofile(void);
366static void	inetd_setproctitle(char *, int);
367static void	initring(void);
368static uint32_t	machtime(void);
369static int	port_good_dg(struct sockaddr *);
370static int 	dg_broadcast(struct in_addr *);
371static int	my_kevent(const struct kevent *, size_t, struct kevent *,
372		size_t);
373static struct kevent *	allocchange(void);
374static int	get_line(int, char *, int);
375static void	spawn(struct servtab *, int);
376
377struct biltin {
378	const char *bi_service;		/* internally provided service name */
379	int	bi_socktype;		/* type of socket supported */
380	short	bi_fork;		/* 1 if should fork before call */
381	short	bi_wait;		/* 1 if should wait for child */
382	void	(*bi_fn)(int, struct servtab *);
383					/* function which performs it */
384} biltins[] = {
385	/* Echo received data */
386	{ "echo",	SOCK_STREAM,	1, 0,	echo_stream },
387	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg },
388
389	/* Internet /dev/null */
390	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream },
391	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg },
392
393	/* Return 32 bit time since 1970 */
394	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream },
395	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg },
396
397	/* Return human-readable time */
398	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream },
399	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg },
400
401	/* Familiar character generator */
402	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream },
403	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg },
404
405	{ "tcpmux",	SOCK_STREAM,	1, 0,	tcpmux },
406
407	{ NULL, 0, 0, 0, NULL }
408};
409
410/* list of "bad" ports. I.e. ports that are most obviously used for
411 * "cycling packets" denial of service attacks. See /etc/services.
412 * List must end with port number "0".
413 */
414
415u_int16_t bad_ports[] =  { 7, 9, 13, 19, 37, 0 };
416
417
418#define NUMINT	(sizeof(intab) / sizeof(struct inent))
419const char	*CONFIG = _PATH_INETDCONF;
420
421static int my_signals[] =
422    { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE };
423
424int
425main(int argc, char *argv[])
426{
427	int		ch, n, reload = 1;
428
429	while ((ch = getopt(argc, argv,
430#ifdef LIBWRAP
431					"dl"
432#else
433					"d"
434#endif
435					   )) != -1)
436		switch(ch) {
437		case 'd':
438			debug = 1;
439			options |= SO_DEBUG;
440			break;
441#ifdef LIBWRAP
442		case 'l':
443			lflag = 1;
444			break;
445#endif
446		case '?':
447		default:
448			usage();
449		}
450	argc -= optind;
451	argv += optind;
452
453	if (argc > 0)
454		CONFIG = argv[0];
455
456	if (!debug)
457		daemon(0, 0);
458	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
459	pidfile(NULL);
460
461	kq = kqueue();
462	if (kq < 0) {
463		syslog(LOG_ERR, "kqueue: %m");
464		return (EXIT_FAILURE);
465	}
466
467	if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
468		syslog(LOG_ERR, "getrlimit: %m");
469	} else {
470		rlim_ofile_cur = rlim_ofile.rlim_cur;
471		if (rlim_ofile_cur == RLIM_INFINITY)	/* ! */
472			rlim_ofile_cur = OPEN_MAX;
473	}
474
475	for (n = 0; n < (int)A_CNT(my_signals); n++) {
476		int	signum;
477
478		signum = my_signals[n];
479		if (signum != SIGCHLD)
480			(void) signal(signum, SIG_IGN);
481
482		if (signum != SIGPIPE) {
483			struct kevent	*ev;
484
485			ev = allocchange();
486			EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE,
487			    0, 0, 0);
488		}
489	}
490
491	for (;;) {
492		int		ctrl;
493		struct kevent	eventbuf[64], *ev;
494		struct servtab	*sep;
495
496		if (reload) {
497			reload = 0;
498			config();
499		}
500
501		n = my_kevent(changebuf, changes, eventbuf, A_CNT(eventbuf));
502		changes = 0;
503
504		for (ev = eventbuf; n > 0; ev++, n--) {
505			if (ev->filter == EVFILT_SIGNAL) {
506				switch (ev->ident) {
507				case SIGALRM:
508					retry();
509					break;
510				case SIGCHLD:
511					reapchild();
512					break;
513				case SIGTERM:
514				case SIGINT:
515					goaway();
516					break;
517				case SIGHUP:
518					reload = 1;
519					break;
520				}
521				continue;
522			}
523			if (ev->filter != EVFILT_READ)
524				continue;
525			sep = (struct servtab *)ev->udata;
526			/* Paranoia */
527			if ((int)ev->ident != sep->se_fd)
528				continue;
529			if (debug)
530				fprintf(stderr, "someone wants %s\n",
531				    sep->se_service);
532			if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
533				/* XXX here do the libwrap check-before-accept*/
534				ctrl = accept(sep->se_fd, NULL, NULL);
535				if (debug)
536					fprintf(stderr, "accept, ctrl %d\n",
537					    ctrl);
538				if (ctrl < 0) {
539					if (errno != EINTR)
540						syslog(LOG_WARNING,
541						    "accept (for %s): %m",
542						    sep->se_service);
543					continue;
544				}
545			} else
546				ctrl = sep->se_fd;
547			spawn(sep, ctrl);
548		}
549	}
550}
551
552static void
553spawn(struct servtab *sep, int ctrl)
554{
555	int dofork;
556	pid_t pid;
557
558	pid = 0;
559#ifdef LIBWRAP_INTERNAL
560	dofork = 1;
561#else
562	dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
563#endif
564	if (dofork) {
565		if (sep->se_count++ == 0)
566			(void)gettimeofday(&sep->se_time, NULL);
567		else if (sep->se_count >= sep->se_max) {
568			struct timeval now;
569
570			(void)gettimeofday(&now, NULL);
571			if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
572				sep->se_time = now;
573				sep->se_count = 1;
574			} else {
575				syslog(LOG_ERR,
576				    "%s/%s max spawn rate (%d in %d seconds) "
577				    "exceeded; service not started",
578				    sep->se_service, sep->se_proto,
579				    sep->se_max, CNT_INTVL);
580				if (!sep->se_wait && sep->se_socktype ==
581				    SOCK_STREAM)
582					close(ctrl);
583				close_sep(sep);
584				if (!timingout) {
585					timingout = 1;
586					alarm(RETRYTIME);
587				}
588				return;
589			}
590		}
591		pid = fork();
592		if (pid < 0) {
593			syslog(LOG_ERR, "fork: %m");
594			if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
595				close(ctrl);
596			sleep(1);
597			return;
598		}
599		if (pid != 0 && sep->se_wait) {
600			struct kevent	*ev;
601
602			sep->se_wait = pid;
603			ev = allocchange();
604			EV_SET(ev, sep->se_fd, EVFILT_READ,
605			    EV_DELETE, 0, 0, 0);
606		}
607		if (pid == 0) {
608			size_t	n;
609
610			for (n = 0; n < A_CNT(my_signals); n++)
611				(void) signal(my_signals[n], SIG_DFL);
612			if (debug)
613				setsid();
614		}
615	}
616	if (pid == 0) {
617		run_service(ctrl, sep, dofork);
618		if (dofork)
619			exit(0);
620	}
621	if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
622		close(ctrl);
623}
624
625static void
626run_service(int ctrl, struct servtab *sep, int didfork)
627{
628	struct passwd *pwd;
629	struct group *grp = NULL;	/* XXX gcc */
630	char buf[NI_MAXSERV];
631	struct servtab *s;
632#ifdef LIBWRAP
633	char abuf[BUFSIZ];
634	struct request_info req;
635	int denied;
636	char *service = NULL;	/* XXX gcc */
637#endif
638
639#ifdef LIBWRAP
640#ifndef LIBWRAP_INTERNAL
641	if (sep->se_bi == 0)
642#endif
643	if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
644		request_init(&req, RQ_DAEMON, sep->se_argv[0] ?
645		    sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
646		fromhost(&req);
647		denied = !hosts_access(&req);
648		if (denied || lflag) {
649			if (getnameinfo(&sep->se_ctrladdr,
650			    (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0,
651			    buf, sizeof(buf), 0) != 0) {
652				/* shouldn't happen */
653				(void)snprintf(buf, sizeof buf, "%d",
654				    ntohs(sep->se_ctrladdr_in.sin_port));
655			}
656			service = buf;
657			if (req.client->sin) {
658				sockaddr_snprintf(abuf, sizeof(abuf), "%a",
659				    req.client->sin);
660			} else {
661				strcpy(abuf, "(null)");
662			}
663		}
664		if (denied) {
665			syslog(deny_severity,
666			    "refused connection from %.500s(%s), service %s (%s)",
667			    eval_client(&req), abuf, service, sep->se_proto);
668			goto reject;
669		}
670		if (lflag) {
671			syslog(allow_severity,
672			    "connection from %.500s(%s), service %s (%s)",
673			    eval_client(&req), abuf, service, sep->se_proto);
674		}
675	}
676#endif /* LIBWRAP */
677
678	if (sep->se_bi) {
679		if (didfork) {
680			for (s = servtab; s; s = s->se_next)
681				if (s->se_fd != -1 && s->se_fd != ctrl) {
682					close(s->se_fd);
683					s->se_fd = -1;
684				}
685		}
686		(*sep->se_bi->bi_fn)(ctrl, sep);
687	} else {
688		if ((pwd = getpwnam(sep->se_user)) == NULL) {
689			syslog(LOG_ERR, "%s/%s: %s: No such user",
690			    sep->se_service, sep->se_proto, sep->se_user);
691			goto reject;
692		}
693		if (sep->se_group &&
694		    (grp = getgrnam(sep->se_group)) == NULL) {
695			syslog(LOG_ERR, "%s/%s: %s: No such group",
696			    sep->se_service, sep->se_proto, sep->se_group);
697			goto reject;
698		}
699		if (pwd->pw_uid) {
700			if (sep->se_group)
701				pwd->pw_gid = grp->gr_gid;
702			if (setgid(pwd->pw_gid) < 0) {
703				syslog(LOG_ERR,
704				 "%s/%s: can't set gid %d: %m", sep->se_service,
705				    sep->se_proto, pwd->pw_gid);
706				goto reject;
707			}
708			(void) initgroups(pwd->pw_name,
709			    pwd->pw_gid);
710			if (setuid(pwd->pw_uid) < 0) {
711				syslog(LOG_ERR,
712				 "%s/%s: can't set uid %d: %m", sep->se_service,
713				    sep->se_proto, pwd->pw_uid);
714				goto reject;
715			}
716		} else if (sep->se_group) {
717			(void) setgid((gid_t)grp->gr_gid);
718		}
719		if (debug)
720			fprintf(stderr, "%d execl %s\n",
721			    getpid(), sep->se_server);
722		/* Set our control descriptor to not close-on-exec... */
723		if (fcntl(ctrl, F_SETFD, 0) < 0)
724			syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl);
725		/* ...and dup it to stdin, stdout, and stderr. */
726		if (ctrl != 0) {
727			dup2(ctrl, 0);
728			close(ctrl);
729			ctrl = 0;
730		}
731		dup2(0, 1);
732		dup2(0, 2);
733		if (rlim_ofile.rlim_cur != rlim_ofile_cur &&
734		    setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
735			syslog(LOG_ERR, "setrlimit: %m");
736		execv(sep->se_server, sep->se_argv);
737		syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server);
738	reject:
739		if (sep->se_socktype != SOCK_STREAM)
740			recv(ctrl, buf, sizeof (buf), 0);
741		_exit(1);
742	}
743}
744
745static void
746reapchild(void)
747{
748	int status;
749	pid_t pid;
750	struct servtab *sep;
751
752	for (;;) {
753		pid = wait3(&status, WNOHANG, NULL);
754		if (pid <= 0)
755			break;
756		if (debug)
757			(void) fprintf(stderr, "%d reaped, status %#x\n",
758			    pid, status);
759		for (sep = servtab; sep != NULL; sep = sep->se_next)
760			if (sep->se_wait == pid) {
761				struct kevent	*ev;
762
763				if (WIFEXITED(status) && WEXITSTATUS(status))
764					syslog(LOG_WARNING,
765					    "%s: exit status %u",
766					    sep->se_server, WEXITSTATUS(status));
767				else if (WIFSIGNALED(status))
768					syslog(LOG_WARNING,
769					    "%s: exit signal %u",
770					    sep->se_server, WTERMSIG(status));
771				sep->se_wait = 1;
772				ev = allocchange();
773				EV_SET(ev, sep->se_fd, EVFILT_READ,
774				    EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep);
775				if (debug)
776					fprintf(stderr, "restored %s, fd %d\n",
777					    sep->se_service, sep->se_fd);
778			}
779	}
780}
781
782static void
783config(void)
784{
785	struct servtab *sep, *cp, **sepp;
786	size_t n;
787
788	if (!setconfig()) {
789		syslog(LOG_ERR, "%s: %m", CONFIG);
790		return;
791	}
792	for (sep = servtab; sep != NULL; sep = sep->se_next)
793		sep->se_checked = 0;
794	while ((cp = getconfigent()) != NULL) {
795		for (sep = servtab; sep != NULL; sep = sep->se_next)
796			if (strcmp(sep->se_service, cp->se_service) == 0 &&
797			    strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
798			    strcmp(sep->se_proto, cp->se_proto) == 0 &&
799			    ISMUX(sep) == ISMUX(cp))
800				break;
801		if (sep != NULL) {
802			int i;
803
804#define SWAP(type, a, b) {type c = a; a = b; b = c;}
805
806			/*
807			 * sep->se_wait may be holding the pid of a daemon
808			 * that we're waiting for.  If so, don't overwrite
809			 * it unless the config file explicitly says don't
810			 * wait.
811			 */
812			if (cp->se_bi == 0 &&
813			    (sep->se_wait == 1 || cp->se_wait == 0))
814				sep->se_wait = cp->se_wait;
815			SWAP(char *, sep->se_user, cp->se_user);
816			SWAP(char *, sep->se_group, cp->se_group);
817			SWAP(char *, sep->se_server, cp->se_server);
818			for (i = 0; i < MAXARGV; i++)
819				SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
820#ifdef IPSEC
821			SWAP(char *, sep->se_policy, cp->se_policy);
822#endif
823			SWAP(int, cp->se_type, sep->se_type);
824			SWAP(int, cp->se_max, sep->se_max);
825#undef SWAP
826			if (isrpcservice(sep))
827				unregister_rpc(sep);
828			sep->se_rpcversl = cp->se_rpcversl;
829			sep->se_rpcversh = cp->se_rpcversh;
830			freeconfig(cp);
831			if (debug)
832				print_service("REDO", sep);
833		} else {
834			sep = enter(cp);
835			if (debug)
836				print_service("ADD ", sep);
837		}
838		sep->se_checked = 1;
839
840		switch (sep->se_family) {
841		case AF_LOCAL:
842			if (sep->se_fd != -1)
843				break;
844			n = strlen(sep->se_service);
845			if (n >= sizeof(sep->se_ctrladdr_un.sun_path)) {
846				syslog(LOG_ERR, "%s: address too long",
847				    sep->se_service);
848				sep->se_checked = 0;
849				continue;
850			}
851			(void)unlink(sep->se_service);
852			strlcpy(sep->se_ctrladdr_un.sun_path,
853			    sep->se_service, n + 1);
854			sep->se_ctrladdr_un.sun_family = AF_LOCAL;
855			sep->se_ctrladdr_size = (int)(n +
856			    sizeof(sep->se_ctrladdr_un) -
857			    sizeof(sep->se_ctrladdr_un.sun_path));
858			if (!ISMUX(sep))
859				setup(sep);
860			break;
861		case AF_INET:
862#ifdef INET6
863		case AF_INET6:
864#endif
865		    {
866			struct addrinfo hints, *res;
867			char *host;
868			const char *port;
869			int error;
870			int s;
871
872			/* check if the family is supported */
873			s = socket(sep->se_family, SOCK_DGRAM, 0);
874			if (s < 0) {
875				syslog(LOG_WARNING,
876				    "%s/%s: %s: the address family is not "
877				    "supported by the kernel",
878				    sep->se_service, sep->se_proto,
879				    sep->se_hostaddr);
880				sep->se_checked = 0;
881				continue;
882			}
883			close(s);
884
885			memset(&hints, 0, sizeof(hints));
886			hints.ai_family = sep->se_family;
887			hints.ai_socktype = sep->se_socktype;
888			hints.ai_flags = AI_PASSIVE;
889			if (!strcmp(sep->se_hostaddr, "*"))
890				host = NULL;
891			else
892				host = sep->se_hostaddr;
893			if (isrpcservice(sep) || ISMUX(sep))
894				port = "0";
895			else
896				port = sep->se_service;
897			error = getaddrinfo(host, port, &hints, &res);
898			if (error) {
899				if (error == EAI_SERVICE) {
900					/* gai_strerror not friendly enough */
901					syslog(LOG_WARNING, "%s/%s: "
902					    "unknown service",
903					    sep->se_service, sep->se_proto);
904				} else {
905					syslog(LOG_ERR, "%s/%s: %s: %s",
906					    sep->se_service, sep->se_proto,
907					    sep->se_hostaddr,
908					    gai_strerror(error));
909				}
910				sep->se_checked = 0;
911				continue;
912			}
913			if (res->ai_next) {
914				syslog(LOG_ERR,
915					"%s/%s: %s: resolved to multiple addr",
916				    sep->se_service, sep->se_proto,
917				    sep->se_hostaddr);
918				sep->se_checked = 0;
919				freeaddrinfo(res);
920				continue;
921			}
922			memcpy(&sep->se_ctrladdr, res->ai_addr,
923				res->ai_addrlen);
924			if (ISMUX(sep)) {
925				sep->se_fd = -1;
926				freeaddrinfo(res);
927				continue;
928			}
929			sep->se_ctrladdr_size = res->ai_addrlen;
930			freeaddrinfo(res);
931#ifdef RPC
932			if (isrpcservice(sep)) {
933				struct rpcent *rp;
934
935				sep->se_rpcprog = atoi(sep->se_service);
936				if (sep->se_rpcprog == 0) {
937					rp = getrpcbyname(sep->se_service);
938					if (rp == 0) {
939						syslog(LOG_ERR,
940						    "%s/%s: unknown service",
941						    sep->se_service,
942						    sep->se_proto);
943						sep->se_checked = 0;
944						continue;
945					}
946					sep->se_rpcprog = rp->r_number;
947				}
948				if (sep->se_fd == -1 && !ISMUX(sep))
949					setup(sep);
950				if (sep->se_fd != -1)
951					register_rpc(sep);
952			} else
953#endif
954			{
955				if (sep->se_fd >= 0)
956					close_sep(sep);
957				if (sep->se_fd == -1 && !ISMUX(sep))
958					setup(sep);
959			}
960		    }
961		}
962	}
963	endconfig();
964	/*
965	 * Purge anything not looked at above.
966	 */
967	sepp = &servtab;
968	while ((sep = *sepp) != NULL) {
969		if (sep->se_checked) {
970			sepp = &sep->se_next;
971			continue;
972		}
973		*sepp = sep->se_next;
974		if (sep->se_fd >= 0)
975			close_sep(sep);
976		if (isrpcservice(sep))
977			unregister_rpc(sep);
978		if (sep->se_family == AF_LOCAL)
979			(void)unlink(sep->se_service);
980		if (debug)
981			print_service("FREE", sep);
982		freeconfig(sep);
983		free(sep);
984	}
985}
986
987static void
988retry(void)
989{
990	struct servtab *sep;
991
992	timingout = 0;
993	for (sep = servtab; sep != NULL; sep = sep->se_next) {
994		if (sep->se_fd == -1 && !ISMUX(sep)) {
995			switch (sep->se_family) {
996			case AF_LOCAL:
997			case AF_INET:
998#ifdef INET6
999			case AF_INET6:
1000#endif
1001				setup(sep);
1002				if (sep->se_fd >= 0 && isrpcservice(sep))
1003					register_rpc(sep);
1004				break;
1005			}
1006		}
1007	}
1008}
1009
1010static void
1011goaway(void)
1012{
1013	struct servtab *sep;
1014
1015	for (sep = servtab; sep != NULL; sep = sep->se_next) {
1016		if (sep->se_fd == -1)
1017			continue;
1018
1019		switch (sep->se_family) {
1020		case AF_LOCAL:
1021			(void)unlink(sep->se_service);
1022			break;
1023		case AF_INET:
1024#ifdef INET6
1025		case AF_INET6:
1026#endif
1027			if (sep->se_wait == 1 && isrpcservice(sep))
1028				unregister_rpc(sep);
1029			break;
1030		}
1031		(void)close(sep->se_fd);
1032		sep->se_fd = -1;
1033	}
1034	exit(0);
1035}
1036
1037static void
1038setup(struct servtab *sep)
1039{
1040	int		on = 1;
1041#ifdef INET6
1042	int		off = 0;
1043#endif
1044	struct kevent	*ev;
1045
1046	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1047		if (debug)
1048			fprintf(stderr, "socket failed on %s/%s: %s\n",
1049			    sep->se_service, sep->se_proto, strerror(errno));
1050		syslog(LOG_ERR, "%s/%s: socket: %m",
1051		    sep->se_service, sep->se_proto);
1052		return;
1053	}
1054	/* Set all listening sockets to close-on-exec. */
1055	if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
1056		syslog(LOG_ERR, "%s/%s: fcntl(F_SETFD, FD_CLOEXEC): %m",
1057		    sep->se_service, sep->se_proto);
1058		close(sep->se_fd);
1059		sep->se_fd = -1;
1060		return;
1061	}
1062
1063#define	turnon(fd, opt) \
1064setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on))
1065	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1066	    turnon(sep->se_fd, SO_DEBUG) < 0)
1067		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1068	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1069		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1070#undef turnon
1071
1072	/* Set the socket buffer sizes, if specified. */
1073	if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1074	    SO_SNDBUF, &sep->se_sndbuf, (socklen_t)sizeof(sep->se_sndbuf)) < 0)
1075		syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m",
1076		    sep->se_sndbuf);
1077	if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1078	    SO_RCVBUF, &sep->se_rcvbuf, (socklen_t)sizeof(sep->se_rcvbuf)) < 0)
1079		syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m",
1080		    sep->se_rcvbuf);
1081#ifdef INET6
1082	if (sep->se_family == AF_INET6) {
1083		int *v;
1084		v = (sep->se_type == FAITH_TYPE) ? &on : &off;
1085		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH,
1086		    v, (socklen_t)sizeof(*v)) < 0)
1087			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1088	}
1089#endif
1090#ifdef IPSEC
1091	/* Avoid setting a policy if a policy specifier doesn't exist. */
1092	if (sep->se_policy != NULL) {
1093		int e = ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy);
1094		if (e < 0) {
1095			syslog(LOG_ERR, "%s/%s: ipsec setup failed",
1096			    sep->se_service, sep->se_proto);
1097			(void)close(sep->se_fd);
1098			sep->se_fd = -1;
1099			return;
1100		}
1101	}
1102#endif
1103
1104	if (bind(sep->se_fd, &sep->se_ctrladdr,
1105	    (socklen_t)sep->se_ctrladdr_size) < 0) {
1106		if (debug)
1107			fprintf(stderr, "bind failed on %s/%s: %s\n",
1108			    sep->se_service, sep->se_proto, strerror(errno));
1109		syslog(LOG_ERR, "%s/%s: bind: %m",
1110		    sep->se_service, sep->se_proto);
1111		(void) close(sep->se_fd);
1112		sep->se_fd = -1;
1113		if (!timingout) {
1114			timingout = 1;
1115			alarm(RETRYTIME);
1116		}
1117		return;
1118	}
1119	if (sep->se_socktype == SOCK_STREAM)
1120		listen(sep->se_fd, 10);
1121
1122	/* Set the accept filter, if specified. To be done after listen.*/
1123	if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1124	    SO_ACCEPTFILTER, &sep->se_accf,
1125	    (socklen_t)sizeof(sep->se_accf)) < 0)
1126		syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m",
1127		    sep->se_accf.af_name);
1128
1129	ev = allocchange();
1130	EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
1131	    (intptr_t)sep);
1132	if (sep->se_fd > maxsock) {
1133		maxsock = sep->se_fd;
1134		if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
1135			bump_nofile();
1136	}
1137	if (debug)
1138		fprintf(stderr, "registered %s on %d\n",
1139		    sep->se_server, sep->se_fd);
1140}
1141
1142/*
1143 * Finish with a service and its socket.
1144 */
1145static void
1146close_sep(struct servtab *sep)
1147{
1148	if (sep->se_fd >= 0) {
1149		(void) close(sep->se_fd);
1150		sep->se_fd = -1;
1151	}
1152	sep->se_count = 0;
1153}
1154
1155static void
1156register_rpc(struct servtab *sep)
1157{
1158#ifdef RPC
1159	struct netbuf nbuf;
1160	struct sockaddr_storage ss;
1161	struct netconfig *nconf;
1162	socklen_t socklen;
1163	int n;
1164
1165	if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1166		syslog(LOG_ERR, "%s: getnetconfigent failed",
1167		    sep->se_proto);
1168		return;
1169	}
1170	socklen = sizeof ss;
1171	if (getsockname(sep->se_fd, (struct sockaddr *)(void *)&ss, &socklen) < 0) {
1172		syslog(LOG_ERR, "%s/%s: getsockname: %m",
1173		    sep->se_service, sep->se_proto);
1174		return;
1175	}
1176
1177	nbuf.buf = &ss;
1178	nbuf.len = ss.ss_len;
1179	nbuf.maxlen = sizeof (struct sockaddr_storage);
1180	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1181		if (debug)
1182			fprintf(stderr, "rpcb_set: %u %d %s %s\n",
1183			    sep->se_rpcprog, n, nconf->nc_netid,
1184			    taddr2uaddr(nconf, &nbuf));
1185		(void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf);
1186		if (!rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf))
1187			syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s",
1188			    sep->se_rpcprog, n, nconf->nc_netid,
1189			    taddr2uaddr(nconf, &nbuf), clnt_spcreateerror(""));
1190	}
1191#endif /* RPC */
1192}
1193
1194static void
1195unregister_rpc(struct servtab *sep)
1196{
1197#ifdef RPC
1198	int n;
1199	struct netconfig *nconf;
1200
1201	if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1202		syslog(LOG_ERR, "%s: getnetconfigent failed",
1203		    sep->se_proto);
1204		return;
1205	}
1206
1207	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1208		if (debug)
1209			fprintf(stderr, "rpcb_unset(%u, %d, %s)\n",
1210			    sep->se_rpcprog, n, nconf->nc_netid);
1211		if (!rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf))
1212			syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n",
1213			    sep->se_rpcprog, n, nconf->nc_netid);
1214	}
1215#endif /* RPC */
1216}
1217
1218
1219static struct servtab *
1220enter(struct servtab *cp)
1221{
1222	struct servtab *sep;
1223
1224	sep = malloc(sizeof (*sep));
1225	if (sep == NULL) {
1226		syslog(LOG_ERR, "Out of memory.");
1227		exit(1);
1228	}
1229	*sep = *cp;
1230	sep->se_fd = -1;
1231	sep->se_rpcprog = -1;
1232	sep->se_next = servtab;
1233	servtab = sep;
1234	return (sep);
1235}
1236
1237FILE	*fconfig = NULL;
1238struct	servtab serv;
1239char	line[LINE_MAX];
1240char    *defhost;
1241#ifdef IPSEC
1242static char *policy = NULL;
1243#endif
1244
1245static int
1246setconfig(void)
1247{
1248	if (defhost)
1249		free(defhost);
1250	defhost = newstr("*");
1251#ifdef IPSEC
1252	if (policy)
1253		free(policy);
1254	policy = NULL;
1255#endif
1256	if (fconfig != NULL) {
1257		fseek(fconfig, 0L, SEEK_SET);
1258		return (1);
1259	}
1260	fconfig = fopen(CONFIG, "r");
1261	return (fconfig != NULL);
1262}
1263
1264static void
1265endconfig(void)
1266{
1267	if (fconfig != NULL) {
1268		(void) fclose(fconfig);
1269		fconfig = NULL;
1270	}
1271	if (defhost != NULL) {
1272		free(defhost);
1273		defhost = NULL;
1274	}
1275}
1276
1277static struct servtab *
1278getconfigent(void)
1279{
1280	struct servtab *sep = &serv;
1281	int argc, val;
1282	char *cp, *cp0, *arg, *buf0, *buf1, *sz0, *sz1;
1283	static char TCPMUX_TOKEN[] = "tcpmux/";
1284#define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1285	char *hostdelim;
1286
1287more:
1288	while ((cp = nextline(fconfig)) != NULL) {
1289#ifdef IPSEC
1290		/* lines starting with #@ is not a comment, but the policy */
1291		if (cp[0] == '#' && cp[1] == '@') {
1292			char *p;
1293			for (p = cp + 2; p && *p && isspace((unsigned char)*p); p++)
1294				;
1295			if (*p == '\0') {
1296				if (policy)
1297					free(policy);
1298				policy = NULL;
1299			} else {
1300				if (ipsecsetup_test(p) < 0) {
1301					syslog(LOG_ERR,
1302						"%s: invalid ipsec policy \"%s\"",
1303						CONFIG, p);
1304					exit(1);
1305				} else {
1306					if (policy)
1307						free(policy);
1308					policy = newstr(p);
1309				}
1310			}
1311		}
1312#endif
1313		if (*cp == '#' || *cp == '\0')
1314			continue;
1315		break;
1316	}
1317	if (cp == NULL)
1318		return (NULL);
1319	/*
1320	 * clear the static buffer, since some fields (se_ctrladdr,
1321	 * for example) don't get initialized here.
1322	 */
1323	memset(sep, 0, sizeof *sep);
1324	arg = skip(&cp);
1325	if (cp == NULL) {
1326		/* got an empty line containing just blanks/tabs. */
1327		goto more;
1328	}
1329	/* Check for a host name. */
1330	hostdelim = strrchr(arg, ':');
1331	if (hostdelim) {
1332		*hostdelim = '\0';
1333		if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1334			hostdelim[-1] = '\0';
1335			sep->se_hostaddr = newstr(arg + 1);
1336		} else
1337			sep->se_hostaddr = newstr(arg);
1338		arg = hostdelim + 1;
1339		/*
1340		 * If the line is of the form `host:', then just change the
1341		 * default host for the following lines.
1342		 */
1343		if (*arg == '\0') {
1344			arg = skip(&cp);
1345			if (cp == NULL) {
1346				free(defhost);
1347				defhost = sep->se_hostaddr;
1348				goto more;
1349			}
1350		}
1351	} else
1352		sep->se_hostaddr = newstr(defhost);
1353	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1354		char *c = arg + MUX_LEN;
1355		if (*c == '+') {
1356			sep->se_type = MUXPLUS_TYPE;
1357			c++;
1358		} else
1359			sep->se_type = MUX_TYPE;
1360		sep->se_service = newstr(c);
1361	} else {
1362		sep->se_service = newstr(arg);
1363		sep->se_type = NORM_TYPE;
1364	}
1365
1366	arg = sskip(&cp);
1367	if (strncmp(arg, "stream", sizeof("stream") - 1) == 0) {
1368		char *accf, *accf_arg;
1369
1370		sep->se_socktype = SOCK_STREAM;
1371
1372		/* one and only one accept filter */
1373		accf = strchr(arg, ':');
1374		if (accf) {
1375	    		if (accf != strrchr(arg, ':') ||/* more than one */
1376	    		    *(accf + 1) == '\0') {	/* nothing beyond */
1377				sep->se_socktype = -1;
1378			} else {
1379				accf++;			/* skip delimiter */
1380				strlcpy(sep->se_accf.af_name, accf,
1381					sizeof(sep->se_accf.af_name));
1382				accf_arg = strchr(accf, ',');
1383				if (accf_arg) {	/* zero or one arg, no more */
1384					if (strrchr(accf, ',') != accf_arg) {
1385						sep->se_socktype = -1;
1386					} else {
1387						accf_arg++;
1388						strlcpy(sep->se_accf.af_arg,
1389							accf_arg,
1390							sizeof(sep->se_accf.af_arg));
1391					}
1392				}
1393			}
1394		}
1395	}
1396
1397	else if (strcmp(arg, "dgram") == 0)
1398		sep->se_socktype = SOCK_DGRAM;
1399	else if (strcmp(arg, "rdm") == 0)
1400		sep->se_socktype = SOCK_RDM;
1401	else if (strcmp(arg, "seqpacket") == 0)
1402		sep->se_socktype = SOCK_SEQPACKET;
1403	else if (strcmp(arg, "raw") == 0)
1404		sep->se_socktype = SOCK_RAW;
1405	else
1406		sep->se_socktype = -1;
1407
1408	arg = sskip(&cp);
1409	if (sep->se_type == NORM_TYPE &&
1410	    strncmp(arg, "faith/", strlen("faith/")) == 0) {
1411		arg += strlen("faith/");
1412		sep->se_type = FAITH_TYPE;
1413	}
1414	sep->se_proto = newstr(arg);
1415
1416#define	MALFORMED(arg) \
1417do { \
1418	syslog(LOG_ERR, "%s: malformed buffer size option `%s'", \
1419	    sep->se_service, (arg)); \
1420	goto more; \
1421	/*NOTREACHED*/ \
1422} while (/*CONSTCOND*/0)
1423
1424#define	GETVAL(arg) \
1425do { \
1426	if (!isdigit((unsigned char)*(arg))) \
1427		MALFORMED(arg); \
1428	val = (int)strtol((arg), &cp0, 10); \
1429	if (cp0 != NULL) { \
1430		if (cp0[1] != '\0') \
1431			MALFORMED((arg)); \
1432		if (cp0[0] == 'k') \
1433			val *= 1024; \
1434		if (cp0[0] == 'm') \
1435			val *= 1024 * 1024; \
1436	} \
1437	if (val < 1) { \
1438		syslog(LOG_ERR, "%s: invalid buffer size `%s'", \
1439		    sep->se_service, (arg)); \
1440		goto more; \
1441	} \
1442	/*NOTREACHED*/ \
1443} while (/*CONSTCOND*/0)
1444
1445#define	ASSIGN(arg) \
1446do { \
1447	if (strcmp((arg), "sndbuf") == 0) \
1448		sep->se_sndbuf = val; \
1449	else if (strcmp((arg), "rcvbuf") == 0) \
1450		sep->se_rcvbuf = val; \
1451	else \
1452		MALFORMED((arg)); \
1453} while (/*CONSTCOND*/0)
1454
1455	/*
1456	 * Extract the send and receive buffer sizes before parsing
1457	 * the protocol.
1458	 */
1459	sep->se_sndbuf = sep->se_rcvbuf = 0;
1460	buf0 = buf1 = sz0 = sz1 = NULL;
1461	if ((buf0 = strchr(sep->se_proto, ',')) != NULL) {
1462		/* Not meaningful for Tcpmux services. */
1463		if (ISMUX(sep)) {
1464			syslog(LOG_ERR, "%s: can't specify buffer sizes for "
1465			    "tcpmux services", sep->se_service);
1466			goto more;
1467		}
1468
1469		/* Skip the , */
1470		*buf0++ = '\0';
1471
1472		/* Check to see if another socket buffer size was specified. */
1473		if ((buf1 = strchr(buf0, ',')) != NULL) {
1474			/* Skip the , */
1475			*buf1++ = '\0';
1476
1477			/* Make sure a 3rd one wasn't specified. */
1478			if (strchr(buf1, ',') != NULL) {
1479				syslog(LOG_ERR, "%s: too many buffer sizes",
1480				    sep->se_service);
1481				goto more;
1482			}
1483
1484			/* Locate the size. */
1485			if ((sz1 = strchr(buf1, '=')) == NULL)
1486				MALFORMED(buf1);
1487
1488			/* Skip the = */
1489			*sz1++ = '\0';
1490		}
1491
1492		/* Locate the size. */
1493		if ((sz0 = strchr(buf0, '=')) == NULL)
1494			MALFORMED(buf0);
1495
1496		/* Skip the = */
1497		*sz0++ = '\0';
1498
1499		GETVAL(sz0);
1500		ASSIGN(buf0);
1501
1502		if (buf1 != NULL) {
1503			GETVAL(sz1);
1504			ASSIGN(buf1);
1505		}
1506	}
1507
1508#undef ASSIGN
1509#undef GETVAL
1510#undef MALFORMED
1511
1512	if (strcmp(sep->se_proto, "unix") == 0) {
1513		sep->se_family = AF_LOCAL;
1514	} else {
1515		val = (int)strlen(sep->se_proto);
1516		if (!val) {
1517			syslog(LOG_ERR, "%s: invalid protocol specified",
1518			    sep->se_service);
1519			goto more;
1520		}
1521		val = sep->se_proto[val - 1];
1522		switch (val) {
1523		case '4':	/*tcp4 or udp4*/
1524			sep->se_family = AF_INET;
1525			break;
1526#ifdef INET6
1527		case '6':	/*tcp6 or udp6*/
1528			sep->se_family = AF_INET6;
1529			break;
1530#endif
1531		default:
1532			sep->se_family = AF_INET;	/*will become AF_INET6*/
1533			break;
1534		}
1535		if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1536#ifdef RPC
1537			char *cp1, *ccp;
1538			cp1 = strchr(sep->se_service, '/');
1539			if (cp1 == 0) {
1540				syslog(LOG_ERR, "%s: no rpc version",
1541				    sep->se_service);
1542				goto more;
1543			}
1544			*cp1++ = '\0';
1545			sep->se_rpcversl = sep->se_rpcversh =
1546			    (int)strtol(cp1, &ccp, 0);
1547			if (ccp == cp1) {
1548		badafterall:
1549				syslog(LOG_ERR, "%s/%s: bad rpc version",
1550				    sep->se_service, cp1);
1551				goto more;
1552			}
1553			if (*ccp == '-') {
1554				cp1 = ccp + 1;
1555				sep->se_rpcversh = (int)strtol(cp1, &ccp, 0);
1556				if (ccp == cp1)
1557					goto badafterall;
1558			}
1559#else
1560			syslog(LOG_ERR, "%s: rpc services not suported",
1561			    sep->se_service);
1562			goto more;
1563#endif /* RPC */
1564		}
1565	}
1566	arg = sskip(&cp);
1567	{
1568		char *cp1;
1569		if ((cp1 = strchr(arg, ':')) == NULL)
1570			cp1 = strchr(arg, '.');
1571		if (cp1 != NULL) {
1572			*cp1++ = '\0';
1573			sep->se_max = atoi(cp1);
1574		} else
1575			sep->se_max = TOOMANY;
1576	}
1577	sep->se_wait = strcmp(arg, "wait") == 0;
1578	if (ISMUX(sep)) {
1579		/*
1580		 * Silently enforce "nowait" for TCPMUX services since
1581		 * they don't have an assigned port to listen on.
1582		 */
1583		sep->se_wait = 0;
1584
1585		if (strncmp(sep->se_proto, "tcp", 3)) {
1586			syslog(LOG_ERR,
1587			    "%s: bad protocol for tcpmux service %s",
1588			    CONFIG, sep->se_service);
1589			goto more;
1590		}
1591		if (sep->se_socktype != SOCK_STREAM) {
1592			syslog(LOG_ERR,
1593			    "%s: bad socket type for tcpmux service %s",
1594			    CONFIG, sep->se_service);
1595			goto more;
1596		}
1597	}
1598	sep->se_user = newstr(sskip(&cp));
1599	if ((sep->se_group = strchr(sep->se_user, ':')) != NULL)
1600		*sep->se_group++ = '\0';
1601	else if ((sep->se_group = strchr(sep->se_user, '.')) != NULL)
1602		*sep->se_group++ = '\0';
1603
1604	sep->se_server = newstr(sskip(&cp));
1605	if (strcmp(sep->se_server, "internal") == 0) {
1606		struct biltin *bi;
1607
1608		for (bi = biltins; bi->bi_service; bi++)
1609			if (bi->bi_socktype == sep->se_socktype &&
1610			    strcmp(bi->bi_service, sep->se_service) == 0)
1611				break;
1612		if (bi->bi_service == 0) {
1613			syslog(LOG_ERR, "internal service %s unknown",
1614			    sep->se_service);
1615			goto more;
1616		}
1617		sep->se_bi = bi;
1618		sep->se_wait = bi->bi_wait;
1619	} else
1620		sep->se_bi = NULL;
1621	argc = 0;
1622	for (arg = skip(&cp); cp; arg = skip(&cp)) {
1623		if (argc < MAXARGV)
1624			sep->se_argv[argc++] = newstr(arg);
1625	}
1626	while (argc <= MAXARGV)
1627		sep->se_argv[argc++] = NULL;
1628#ifdef IPSEC
1629	sep->se_policy = policy ? newstr(policy) : NULL;
1630#endif
1631	return (sep);
1632}
1633
1634static void
1635freeconfig(struct servtab *cp)
1636{
1637	int i;
1638
1639	if (cp->se_hostaddr)
1640		free(cp->se_hostaddr);
1641	if (cp->se_service)
1642		free(cp->se_service);
1643	if (cp->se_proto)
1644		free(cp->se_proto);
1645	if (cp->se_user)
1646		free(cp->se_user);
1647	/* Note: se_group is part of the newstr'ed se_user */
1648	if (cp->se_server)
1649		free(cp->se_server);
1650	for (i = 0; i < MAXARGV; i++)
1651		if (cp->se_argv[i])
1652			free(cp->se_argv[i]);
1653#ifdef IPSEC
1654	if (cp->se_policy)
1655		free(cp->se_policy);
1656#endif
1657}
1658
1659
1660/*
1661 * Safe skip - if skip returns null, log a syntax error in the
1662 * configuration file and exit.
1663 */
1664static char *
1665sskip(char **cpp)
1666{
1667	char *cp;
1668
1669	cp = skip(cpp);
1670	if (cp == NULL) {
1671		syslog(LOG_ERR, "%s: syntax error", CONFIG);
1672		exit(1);
1673	}
1674	return (cp);
1675}
1676
1677static char *
1678skip(char **cpp)
1679{
1680	char *cp = *cpp;
1681	char *start;
1682	char quote;
1683
1684	if (*cpp == NULL)
1685		return (NULL);
1686
1687again:
1688	while (*cp == ' ' || *cp == '\t')
1689		cp++;
1690	if (*cp == '\0') {
1691		int c;
1692
1693		c = getc(fconfig);
1694		(void) ungetc(c, fconfig);
1695		if (c == ' ' || c == '\t')
1696			if ((cp = nextline(fconfig)) != NULL)
1697				goto again;
1698		*cpp = NULL;
1699		return (NULL);
1700	}
1701	start = cp;
1702	quote = '\0';
1703	while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) {
1704		if (*cp == '\'' || *cp == '"') {
1705			if (quote && *cp != quote)
1706				cp++;
1707			else {
1708				if (quote)
1709					quote = '\0';
1710				else
1711					quote = *cp;
1712				memmove(cp, cp+1, strlen(cp));
1713			}
1714		} else
1715			cp++;
1716	}
1717	if (*cp != '\0')
1718		*cp++ = '\0';
1719	*cpp = cp;
1720	return (start);
1721}
1722
1723static char *
1724nextline(FILE *fd)
1725{
1726	char *cp;
1727
1728	if (fgets(line, (int)sizeof(line), fd) == NULL)
1729		return (NULL);
1730	cp = strchr(line, '\n');
1731	if (cp)
1732		*cp = '\0';
1733	return (line);
1734}
1735
1736static char *
1737newstr(const char *cp)
1738{
1739	char *dp;
1740	if ((dp = strdup((cp != NULL) ? cp : "")) != NULL)
1741		return (dp);
1742	syslog(LOG_ERR, "strdup: %m");
1743	exit(1);
1744	/*NOTREACHED*/
1745}
1746
1747static void
1748inetd_setproctitle(char *a, int s)
1749{
1750	socklen_t size;
1751	struct sockaddr_storage ss;
1752	char hbuf[NI_MAXHOST];
1753	const char *hp;
1754	struct sockaddr *sa;
1755
1756	size = sizeof(ss);
1757	sa = (struct sockaddr *)(void *)&ss;
1758	if (getpeername(s, sa, &size) == 0) {
1759		if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
1760		    0, niflags) != 0)
1761			hp = "?";
1762		else
1763			hp = hbuf;
1764		setproctitle("-%s [%s]", a, hp);
1765	} else
1766		setproctitle("-%s", a);
1767}
1768
1769static void
1770bump_nofile(void)
1771{
1772#define FD_CHUNK	32
1773	struct rlimit rl;
1774
1775	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1776		syslog(LOG_ERR, "getrlimit: %m");
1777		return;
1778	}
1779	rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1780	if (rl.rlim_cur <= rlim_ofile_cur) {
1781		syslog(LOG_ERR,
1782		    "bump_nofile: cannot extend file limit, max = %d",
1783		    (int)rl.rlim_cur);
1784		return;
1785	}
1786
1787	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1788		syslog(LOG_ERR, "setrlimit: %m");
1789		return;
1790	}
1791
1792	rlim_ofile_cur = rl.rlim_cur;
1793	return;
1794}
1795
1796/*
1797 * Internet services provided internally by inetd:
1798 */
1799#define	BUFSIZE	4096
1800
1801/* ARGSUSED */
1802static void
1803echo_stream(int s, struct servtab *sep)	/* Echo service -- echo data back */
1804{
1805	char buffer[BUFSIZE];
1806	ssize_t i;
1807
1808	inetd_setproctitle(sep->se_service, s);
1809	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1810	    write(s, buffer, (size_t)i) > 0)
1811		;
1812}
1813
1814/* ARGSUSED */
1815static void
1816echo_dg(int s, struct servtab *sep)	/* Echo service -- echo data back */
1817{
1818	char buffer[BUFSIZE];
1819	ssize_t i;
1820	socklen_t size;
1821	struct sockaddr_storage ss;
1822	struct sockaddr *sa;
1823
1824	sa = (struct sockaddr *)(void *)&ss;
1825	size = sizeof(ss);
1826	if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1827		return;
1828	if (port_good_dg(sa))
1829		(void) sendto(s, buffer, (size_t)i, 0, sa, size);
1830}
1831
1832/* ARGSUSED */
1833static void
1834discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1835{
1836	char buffer[BUFSIZE];
1837
1838	inetd_setproctitle(sep->se_service, s);
1839	while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1840			errno == EINTR)
1841		;
1842}
1843
1844/* ARGSUSED */
1845static void
1846discard_dg(int s, struct servtab *sep)	/* Discard service -- ignore data */
1847
1848{
1849	char buffer[BUFSIZE];
1850
1851	(void) read(s, buffer, sizeof(buffer));
1852}
1853
1854#define LINESIZ 72
1855char ring[128];
1856char *endring;
1857
1858static void
1859initring(void)
1860{
1861	int i;
1862
1863	endring = ring;
1864
1865	for (i = 0; i <= 128; ++i)
1866		if (isprint(i))
1867			*endring++ = i;
1868}
1869
1870/* ARGSUSED */
1871static void
1872chargen_stream(int s,struct servtab *sep)	/* Character generator */
1873{
1874	size_t len;
1875	char *rs, text[LINESIZ+2];
1876
1877	inetd_setproctitle(sep->se_service, s);
1878
1879	if (!endring) {
1880		initring();
1881		rs = ring;
1882	}
1883
1884	text[LINESIZ] = '\r';
1885	text[LINESIZ + 1] = '\n';
1886	for (rs = ring;;) {
1887		if ((len = endring - rs) >= LINESIZ)
1888			memmove(text, rs, LINESIZ);
1889		else {
1890			memmove(text, rs, len);
1891			memmove(text + len, ring, LINESIZ - len);
1892		}
1893		if (++rs == endring)
1894			rs = ring;
1895		if (write(s, text, sizeof(text)) != sizeof(text))
1896			break;
1897	}
1898}
1899
1900/* ARGSUSED */
1901static void
1902chargen_dg(int s, struct servtab *sep)		/* Character generator */
1903{
1904	struct sockaddr_storage ss;
1905	struct sockaddr *sa;
1906	static char *rs;
1907	size_t len;
1908	socklen_t size;
1909	char text[LINESIZ+2];
1910
1911	if (endring == 0) {
1912		initring();
1913		rs = ring;
1914	}
1915
1916	sa = (struct sockaddr *)(void *)&ss;
1917	size = sizeof(ss);
1918	if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
1919		return;
1920
1921	if (!port_good_dg(sa))
1922		return;
1923
1924	if ((len = endring - rs) >= LINESIZ)
1925		memmove(text, rs, LINESIZ);
1926	else {
1927		memmove(text, rs, len);
1928		memmove(text + len, ring, LINESIZ - len);
1929	}
1930	if (++rs == endring)
1931		rs = ring;
1932	text[LINESIZ] = '\r';
1933	text[LINESIZ + 1] = '\n';
1934	(void) sendto(s, text, sizeof(text), 0, sa, size);
1935}
1936
1937/*
1938 * Return a machine readable date and time, in the form of the
1939 * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1940 * returns the number of seconds since midnight, Jan 1, 1970,
1941 * we must add 2208988800 seconds to this figure to make up for
1942 * some seventy years Bell Labs was asleep.
1943 */
1944
1945static uint32_t
1946machtime(void)
1947{
1948	struct timeval tv;
1949
1950	if (gettimeofday(&tv, NULL) < 0) {
1951		if (debug)
1952			fprintf(stderr, "Unable to get time of day\n");
1953		return (0);
1954	}
1955#define	OFFSET ((uint32_t)25567 * 24*60*60)
1956	return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1957#undef OFFSET
1958}
1959
1960/* ARGSUSED */
1961static void
1962machtime_stream(int s, struct servtab *sep)
1963{
1964	uint32_t result;
1965
1966	result = machtime();
1967	(void) write(s, &result, sizeof(result));
1968}
1969
1970/* ARGSUSED */
1971void
1972machtime_dg(int s, struct servtab *sep)
1973{
1974	uint32_t result;
1975	struct sockaddr_storage ss;
1976	struct sockaddr *sa;
1977	socklen_t size;
1978
1979	sa = (struct sockaddr *)(void *)&ss;
1980	size = sizeof(ss);
1981	if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0)
1982		return;
1983	if (!port_good_dg(sa))
1984		return;
1985	result = machtime();
1986	(void)sendto(s, &result, sizeof(result), 0, sa, size);
1987}
1988
1989/* ARGSUSED */
1990static void
1991daytime_stream(int s,struct servtab *sep)
1992/* Return human-readable time of day */
1993{
1994	char buffer[256];
1995	time_t clk;
1996	int len;
1997
1998	clk = time((time_t *) 0);
1999
2000	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
2001	(void) write(s, buffer, len);
2002}
2003
2004/* ARGSUSED */
2005void
2006daytime_dg(int s, struct servtab *sep)
2007/* Return human-readable time of day */
2008{
2009	char buffer[256];
2010	time_t clk;
2011	struct sockaddr_storage ss;
2012	struct sockaddr *sa;
2013	socklen_t size;
2014	int len;
2015
2016	clk = time((time_t *) 0);
2017
2018	sa = (struct sockaddr *)(void *)&ss;
2019	size = sizeof(ss);
2020	if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
2021		return;
2022	if (!port_good_dg(sa))
2023		return;
2024	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
2025	(void) sendto(s, buffer, len, 0, sa, size);
2026}
2027
2028/*
2029 * print_service:
2030 *	Dump relevant information to stderr
2031 */
2032static void
2033print_service(const char *action, struct servtab *sep)
2034{
2035
2036	if (isrpcservice(sep))
2037		fprintf(stderr,
2038		    "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2039#ifdef IPSEC
2040		    " policy=\"%s\""
2041#endif
2042		    "\n",
2043		    action, sep->se_service,
2044		    sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
2045		    sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
2046		    (long)sep->se_bi, sep->se_server
2047#ifdef IPSEC
2048		    , (sep->se_policy ? sep->se_policy : "")
2049#endif
2050		    );
2051	else
2052		fprintf(stderr,
2053		    "%s: %s proto=%s%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2054#ifdef IPSEC
2055		    " policy=%s"
2056#endif
2057		    "\n",
2058		    action, sep->se_service,
2059		    sep->se_type == FAITH_TYPE ? "faith/" : "",
2060		    sep->se_proto,
2061		    sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
2062		    (long)sep->se_bi, sep->se_server
2063#ifdef IPSEC
2064		    , (sep->se_policy ? sep->se_policy : "")
2065#endif
2066		    );
2067}
2068
2069static void
2070usage(void)
2071{
2072#ifdef LIBWRAP
2073	(void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2074#else
2075	(void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2076#endif
2077	exit(1);
2078}
2079
2080
2081/*
2082 *  Based on TCPMUX.C by Mark K. Lottor November 1988
2083 *  sri-nic::ps:<mkl>tcpmux.c
2084 */
2085
2086static int		/* # of characters upto \r,\n or \0 */
2087get_line(int fd,	char *buf, int len)
2088{
2089	int count = 0;
2090	ssize_t n;
2091
2092	do {
2093		n = read(fd, buf, len-count);
2094		if (n == 0)
2095			return (count);
2096		if (n < 0)
2097			return (-1);
2098		while (--n >= 0) {
2099			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2100				return (count);
2101			count++;
2102			buf++;
2103		}
2104	} while (count < len);
2105	return (count);
2106}
2107
2108#define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
2109
2110#define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
2111
2112static void
2113tcpmux(int ctrl, struct servtab *sep)
2114{
2115	char service[MAX_SERV_LEN+1];
2116	int len;
2117
2118	/* Get requested service name */
2119	if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) {
2120		strwrite(ctrl, "-Error reading service name\r\n");
2121		goto reject;
2122	}
2123	service[len] = '\0';
2124
2125	if (debug)
2126		fprintf(stderr, "tcpmux: someone wants %s\n", service);
2127
2128	/*
2129	 * Help is a required command, and lists available services,
2130	 * one per line.
2131	 */
2132	if (!strcasecmp(service, "help")) {
2133		strwrite(ctrl, "+Available services:\r\n");
2134		strwrite(ctrl, "help\r\n");
2135		for (sep = servtab; sep != NULL; sep = sep->se_next) {
2136			if (!ISMUX(sep))
2137				continue;
2138			(void)write(ctrl, sep->se_service,
2139			    strlen(sep->se_service));
2140			strwrite(ctrl, "\r\n");
2141		}
2142		goto reject;
2143	}
2144
2145	/* Try matching a service in inetd.conf with the request */
2146	for (sep = servtab; sep != NULL; sep = sep->se_next) {
2147		if (!ISMUX(sep))
2148			continue;
2149		if (!strcasecmp(service, sep->se_service)) {
2150			if (ISMUXPLUS(sep))
2151				strwrite(ctrl, "+Go\r\n");
2152			run_service(ctrl, sep, 1 /* forked */);
2153			return;
2154		}
2155	}
2156	strwrite(ctrl, "-Service not available\r\n");
2157reject:
2158	_exit(1);
2159}
2160
2161/*
2162 * check if the address/port where send data to is one of the obvious ports
2163 * that are used for denial of service attacks like two echo ports
2164 * just echoing data between them
2165 */
2166static int
2167port_good_dg(struct sockaddr *sa)
2168{
2169	struct in_addr in;
2170	struct sockaddr_in *sin;
2171#ifdef INET6
2172	struct in6_addr *in6;
2173	struct sockaddr_in6 *sin6;
2174#endif
2175	u_int16_t port;
2176	int i;
2177	char hbuf[NI_MAXHOST];
2178
2179	switch (sa->sa_family) {
2180	case AF_INET:
2181		sin = (struct sockaddr_in *)(void *)sa;
2182		in.s_addr = ntohl(sin->sin_addr.s_addr);
2183		port = ntohs(sin->sin_port);
2184#ifdef INET6
2185	v4chk:
2186#endif
2187		if (IN_MULTICAST(in.s_addr))
2188			goto bad;
2189		switch ((in.s_addr & 0xff000000) >> 24) {
2190		case 0: case 127: case 255:
2191			goto bad;
2192		}
2193		if (dg_broadcast(&in))
2194			goto bad;
2195		break;
2196#ifdef INET6
2197	case AF_INET6:
2198		sin6 = (struct sockaddr_in6 *)(void *)sa;
2199		in6 = &sin6->sin6_addr;
2200		port = ntohs(sin6->sin6_port);
2201		if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
2202			goto bad;
2203		if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
2204			memcpy(&in, &in6->s6_addr[12], sizeof(in));
2205			in.s_addr = ntohl(in.s_addr);
2206			goto v4chk;
2207		}
2208		break;
2209#endif
2210	default:
2211		/* XXX unsupported af, is it safe to assume it to be safe? */
2212		return (1);
2213	}
2214
2215	for (i = 0; bad_ports[i] != 0; i++) {
2216		if (port == bad_ports[i])
2217			goto bad;
2218	}
2219
2220	return (1);
2221
2222bad:
2223	if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
2224	    niflags) != 0)
2225		strlcpy(hbuf, "?", sizeof(hbuf));
2226	syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2227		hbuf, port);
2228	return (0);
2229}
2230
2231/* XXX need optimization */
2232static int
2233dg_broadcast(struct in_addr *in)
2234{
2235	struct ifaddrs *ifa, *ifap;
2236	struct sockaddr_in *sin;
2237
2238	if (getifaddrs(&ifap) < 0)
2239		return (0);
2240	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2241		if (ifa->ifa_addr->sa_family != AF_INET ||
2242		    (ifa->ifa_flags & IFF_BROADCAST) == 0)
2243			continue;
2244		sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
2245		if (sin->sin_addr.s_addr == in->s_addr) {
2246			freeifaddrs(ifap);
2247			return (1);
2248		}
2249	}
2250	freeifaddrs(ifap);
2251	return (0);
2252}
2253
2254static int
2255my_kevent(const struct kevent *changelist, size_t nchanges,
2256    struct kevent *eventlist, size_t nevents)
2257{
2258	int	result;
2259
2260	while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2261	    NULL)) < 0)
2262		if (errno != EINTR) {
2263			syslog(LOG_ERR, "kevent: %m");
2264			exit(EXIT_FAILURE);
2265		}
2266
2267	return (result);
2268}
2269
2270static struct kevent *
2271allocchange(void)
2272{
2273	if (changes == A_CNT(changebuf)) {
2274		(void) my_kevent(changebuf, A_CNT(changebuf), NULL, 0);
2275		changes = 0;
2276	}
2277
2278	return (&changebuf[changes++]);
2279}
2280