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