inetd.c revision 1.105
1/*	$NetBSD: inetd.c,v 1.105 2008/05/26 03:41:25 dholland 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\n\
65	The Regents of the University of California.  All rights reserved.\n");
66#if 0
67static char sccsid[] = "@(#)inetd.c	8.4 (Berkeley) 4/13/94";
68#else
69__RCSID("$NetBSD: inetd.c,v 1.105 2008/05/26 03:41:25 dholland 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			stream/dgram/raw/rdm/seqpacket
99 *	protocol			must be in /etc/protocols
100 *	wait/nowait[:max]		single-threaded/multi-threaded, max #
101 *	user[:group]			user/group to run daemon as
102 *	server program			full path name
103 *	server program arguments	maximum of MAXARGS (20)
104 *
105 * For RPC services
106 *      service name/version            must be in /etc/rpc
107 *	socket type			stream/dgram/raw/rdm/seqpacket
108 *	protocol			must be in /etc/protocols
109 *	wait/nowait[:max]		single-threaded/multi-threaded
110 *	user[:group]			user to run daemon as
111 *	server program			full path name
112 *	server program arguments	maximum of MAXARGS (20)
113 *
114 * For non-RPC services, the "service name" can be of the form
115 * hostaddress:servicename, in which case the hostaddress is used
116 * as the host portion of the address to listen on.  If hostaddress
117 * consists of a single `*' character, INADDR_ANY is used.
118 *
119 * A line can also consist of just
120 *	hostaddress:
121 * where hostaddress is as in the preceding paragraph.  Such a line must
122 * have no further fields; the specified hostaddress is remembered and
123 * used for all further lines that have no hostaddress specified,
124 * until the next such line (or EOF).  (This is why * is provided to
125 * allow explicit specification of INADDR_ANY.)  A line
126 *	*:
127 * is implicitly in effect at the beginning of the file.
128 *
129 * The hostaddress specifier may (and often will) contain dots;
130 * the service name must not.
131 *
132 * For RPC services, host-address specifiers are accepted and will
133 * work to some extent; however, because of limitations in the
134 * portmapper interface, it will not work to try to give more than
135 * one line for any given RPC service, even if the host-address
136 * specifiers are different.
137 *
138 * TCP services without official port numbers are handled with the
139 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
140 * requests. When a connection is made from a foreign host, the service
141 * requested is passed to tcpmux, which looks it up in the servtab list
142 * and returns the proper entry for the service. Tcpmux returns a
143 * negative reply if the service doesn't exist, otherwise the invoked
144 * server is expected to return the positive reply if the service type in
145 * inetd.conf file has the prefix "tcpmux/". If the service type has the
146 * prefix "tcpmux/+", tcpmux will return the positive reply for the
147 * process; this is for compatibility with older server code, and also
148 * allows you to invoke programs that use stdin/stdout without putting any
149 * special server code in them. Services that use tcpmux are "nowait"
150 * because they do not have a well-known port and hence cannot listen
151 * for new requests.
152 *
153 * Comment lines are indicated by a `#' in column 1.
154 *
155 * #ifdef IPSEC
156 * Comment lines that start with "#@" denote IPsec policy string, as described
157 * in ipsec_set_policy(3).  This will affect all the following items in
158 * inetd.conf(8).  To reset the policy, just use "#@" line.  By default,
159 * there's no IPsec policy.
160 * #endif
161 */
162
163/*
164 * Here's the scoop concerning the user:group feature:
165 *
166 * 1) set-group-option off.
167 *
168 * 	a) user = root:	NO setuid() or setgid() is done
169 *
170 * 	b) other:	setuid()
171 * 			setgid(primary group as found in passwd)
172 * 			initgroups(name, primary group)
173 *
174 * 2) set-group-option on.
175 *
176 * 	a) user = root:	NO setuid()
177 * 			setgid(specified group)
178 * 			NO initgroups()
179 *
180 * 	b) other:	setuid()
181 * 			setgid(specified group)
182 * 			initgroups(name, specified group)
183 *
184 */
185
186#include <sys/param.h>
187#include <sys/stat.h>
188#include <sys/ioctl.h>
189#include <sys/socket.h>
190#include <sys/un.h>
191#include <sys/wait.h>
192#include <sys/time.h>
193#include <sys/resource.h>
194#include <sys/event.h>
195
196#ifndef RLIMIT_NOFILE
197#define RLIMIT_NOFILE	RLIMIT_OFILE
198#endif
199
200#ifndef NO_RPC
201#define RPC
202#endif
203
204#include <net/if.h>
205
206#include <netinet/in.h>
207#include <arpa/inet.h>
208#ifdef RPC
209#include <rpc/rpc.h>
210#include <rpc/rpcb_clnt.h>
211#include <netconfig.h>
212#endif
213
214#include <ctype.h>
215#include <errno.h>
216#include <fcntl.h>
217#include <grp.h>
218#include <netdb.h>
219#include <pwd.h>
220#include <signal.h>
221#include <stdio.h>
222#include <stdlib.h>
223#include <string.h>
224#include <syslog.h>
225#include <unistd.h>
226#include <util.h>
227#include <ifaddrs.h>
228
229#include "pathnames.h"
230
231#ifdef IPSEC
232#include <netinet6/ipsec.h>
233#ifndef IPSEC_POLICY_IPSEC	/* no ipsec support on old ipsec */
234#undef IPSEC
235#endif
236#include "ipsec.h"
237#endif
238
239#ifdef LIBWRAP
240# include <tcpd.h>
241#ifndef LIBWRAP_ALLOW_FACILITY
242# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
243#endif
244#ifndef LIBWRAP_ALLOW_SEVERITY
245# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
246#endif
247#ifndef LIBWRAP_DENY_FACILITY
248# define LIBWRAP_DENY_FACILITY LOG_AUTH
249#endif
250#ifndef LIBWRAP_DENY_SEVERITY
251# define LIBWRAP_DENY_SEVERITY LOG_WARNING
252#endif
253int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
254int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
255#endif
256
257#define	TOOMANY		40		/* don't start more than TOOMANY */
258#define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
259#define	RETRYTIME	(60*10)		/* retry after bind or server fail */
260
261#define	A_CNT(a)	(sizeof (a) / sizeof (a[0]))
262
263int	debug;
264#ifdef LIBWRAP
265int	lflag;
266#endif
267int	maxsock;
268int	kq;
269int	options;
270int	timingout;
271struct	servent *sp;
272char	*curdom;
273const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
274
275#ifndef OPEN_MAX
276#define OPEN_MAX	64
277#endif
278
279/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
280#define FD_MARGIN	(8)
281rlim_t		rlim_ofile_cur = OPEN_MAX;
282
283#ifdef RLIMIT_NOFILE
284struct rlimit	rlim_ofile;
285#endif
286
287struct kevent	changebuf[64];
288size_t		changes;
289
290struct	servtab {
291	char	*se_hostaddr;		/* host address to listen on */
292	char	*se_service;		/* name of service */
293	int	se_socktype;		/* type of socket to use */
294	int	se_family;		/* address family */
295	char	*se_proto;		/* protocol used */
296	int	se_sndbuf;		/* sndbuf size */
297	int	se_rcvbuf;		/* rcvbuf size */
298	int	se_rpcprog;		/* rpc program number */
299	int	se_rpcversl;		/* rpc program lowest version */
300	int	se_rpcversh;		/* rpc program highest version */
301#define isrpcservice(sep)	((sep)->se_rpcversl != 0)
302	pid_t	se_wait;		/* single threaded server */
303	short	se_checked;		/* looked at during merge */
304	char	*se_user;		/* user name to run as */
305	char	*se_group;		/* group name to run as */
306	struct	biltin *se_bi;		/* if built-in, description */
307	char	*se_server;		/* server program */
308#define	MAXARGV 20
309	char	*se_argv[MAXARGV+1];	/* program arguments */
310#ifdef IPSEC
311	char	*se_policy;		/* IPsec poilcy string */
312#endif
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#ifdef MULOG
329	int	se_log;
330#define MULOG_RFC931	0x40000000
331#endif
332	struct	servtab *se_next;
333} *servtab;
334
335#define NORM_TYPE	0
336#define MUX_TYPE	1
337#define MUXPLUS_TYPE	2
338#define FAITH_TYPE	3
339#define ISMUX(sep)	(((sep)->se_type == MUX_TYPE) || \
340			 ((sep)->se_type == MUXPLUS_TYPE))
341#define ISMUXPLUS(sep)	((sep)->se_type == MUXPLUS_TYPE)
342
343
344static void	chargen_dg(int, struct servtab *);
345static void	chargen_stream(int, struct servtab *);
346static void	close_sep(struct servtab *);
347static void	config(void);
348static void	daytime_dg(int, struct servtab *);
349static void	daytime_stream(int, struct servtab *);
350static void	discard_dg(int, struct servtab *);
351static void	discard_stream(int, struct servtab *);
352static void	echo_dg(int, struct servtab *);
353static void	echo_stream(int, struct servtab *);
354static void	endconfig(void);
355static struct servtab *enter(struct servtab *);
356static void	freeconfig(struct servtab *);
357static struct servtab *getconfigent(void);
358static void	goaway(void);
359static void	machtime_dg(int, struct servtab *);
360static void	machtime_stream(int, struct servtab *);
361static char    *newstr(char *);
362static char    *nextline(FILE *);
363static void	print_service(char *, struct servtab *);
364static void	reapchild(void);
365static void	retry(void);
366static void	run_service(int, struct servtab *, int);
367static int	setconfig(void);
368static void	setup(struct servtab *);
369static char    *sskip(char **);
370static char    *skip(char **);
371static void	tcpmux(int, struct servtab *);
372static void	usage(void);
373static void	register_rpc(struct servtab *);
374static void	unregister_rpc(struct servtab *);
375static void	bump_nofile(void);
376static void	inetd_setproctitle(char *, int);
377static void	initring(void);
378static uint32_t	machtime(void);
379static int	port_good_dg(struct sockaddr *);
380static int 	dg_broadcast(struct in_addr *);
381static int	my_kevent(const struct kevent *, size_t, struct kevent *,
382		size_t);
383static struct kevent *	allocchange(void);
384static int	getline(int, char *, int);
385static void	spawn(struct servtab *, int);
386#ifdef MULOG
387static void	dolog(struct servtab *, int);
388static void	timeout(int);
389static char    *rfc931_name(struct sockaddr *, int);
390#endif
391
392struct biltin {
393	char	*bi_service;		/* internally provided service name */
394	int	bi_socktype;		/* type of socket supported */
395	short	bi_fork;		/* 1 if should fork before call */
396	short	bi_wait;		/* 1 if should wait for child */
397	void	(*bi_fn)(int, struct servtab *);
398					/* function which performs it */
399} biltins[] = {
400	/* Echo received data */
401	{ "echo",	SOCK_STREAM,	1, 0,	echo_stream },
402	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg },
403
404	/* Internet /dev/null */
405	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream },
406	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg },
407
408	/* Return 32 bit time since 1970 */
409	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream },
410	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg },
411
412	/* Return human-readable time */
413	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream },
414	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg },
415
416	/* Familiar character generator */
417	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream },
418	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg },
419
420	{ "tcpmux",	SOCK_STREAM,	1, 0,	tcpmux },
421
422	{ NULL }
423};
424
425/* list of "bad" ports. I.e. ports that are most obviously used for
426 * "cycling packets" denial of service attacks. See /etc/services.
427 * List must end with port number "0".
428 */
429
430u_int16_t bad_ports[] =  { 7, 9, 13, 19, 37, 0 };
431
432
433#define NUMINT	(sizeof(intab) / sizeof(struct inent))
434char	*CONFIG = _PATH_INETDCONF;
435
436static int my_signals[] =
437    { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE };
438
439int
440main(int argc, char *argv[])
441{
442	int		ch, n, reload = 1;
443
444	while ((ch = getopt(argc, argv,
445#ifdef LIBWRAP
446					"dl"
447#else
448					"d"
449#endif
450					   )) != -1)
451		switch(ch) {
452		case 'd':
453			debug = 1;
454			options |= SO_DEBUG;
455			break;
456#ifdef LIBWRAP
457		case 'l':
458			lflag = 1;
459			break;
460#endif
461		case '?':
462		default:
463			usage();
464		}
465	argc -= optind;
466	argv += optind;
467
468	if (argc > 0)
469		CONFIG = argv[0];
470
471	if (!debug)
472		daemon(0, 0);
473	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
474	pidfile(NULL);
475
476	kq = kqueue();
477	if (kq < 0) {
478		syslog(LOG_ERR, "kqueue: %m");
479		return (EXIT_FAILURE);
480	}
481
482#ifdef RLIMIT_NOFILE
483	if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
484		syslog(LOG_ERR, "getrlimit: %m");
485	} else {
486		rlim_ofile_cur = rlim_ofile.rlim_cur;
487		if (rlim_ofile_cur == RLIM_INFINITY)	/* ! */
488			rlim_ofile_cur = OPEN_MAX;
489	}
490#endif
491
492	for (n = 0; n < (int)A_CNT(my_signals); n++) {
493		int	signum;
494
495		signum = my_signals[n];
496		if (signum != SIGCHLD)
497			(void) signal(signum, SIG_IGN);
498
499		if (signum != SIGPIPE) {
500			struct kevent	*ev;
501
502			ev = allocchange();
503			EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE,
504			    0, 0, 0);
505		}
506	}
507
508	for (;;) {
509		int		ctrl;
510		struct kevent	eventbuf[64], *ev;
511		struct servtab	*sep;
512
513		if (reload) {
514			reload = 0;
515			config();
516		}
517
518		n = my_kevent(changebuf, changes, eventbuf, A_CNT(eventbuf));
519		changes = 0;
520
521		for (ev = eventbuf; n > 0; ev++, n--) {
522			if (ev->filter == EVFILT_SIGNAL) {
523				switch (ev->ident) {
524				case SIGALRM:
525					retry();
526					break;
527				case SIGCHLD:
528					reapchild();
529					break;
530				case SIGTERM:
531				case SIGINT:
532					goaway();
533					break;
534				case SIGHUP:
535					reload = 1;
536					break;
537				}
538				continue;
539			}
540			if (ev->filter != EVFILT_READ)
541				continue;
542			sep = (struct servtab *)ev->udata;
543			/* Paranoia */
544			if ((int)ev->ident != sep->se_fd)
545				continue;
546			if (debug)
547				fprintf(stderr, "someone wants %s\n",
548				    sep->se_service);
549			if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
550				/* XXX here do the libwrap check-before-accept*/
551				ctrl = accept(sep->se_fd, NULL, NULL);
552				if (debug)
553					fprintf(stderr, "accept, ctrl %d\n",
554					    ctrl);
555				if (ctrl < 0) {
556					if (errno != EINTR)
557						syslog(LOG_WARNING,
558						    "accept (for %s): %m",
559						    sep->se_service);
560					continue;
561				}
562			} else
563				ctrl = sep->se_fd;
564			spawn(sep, ctrl);
565		}
566	}
567}
568
569static void
570spawn(struct servtab *sep, int ctrl)
571{
572	int dofork;
573	pid_t pid;
574
575	pid = 0;
576#ifdef LIBWRAP_INTERNAL
577	dofork = 1;
578#else
579	dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
580#endif
581	if (dofork) {
582		if (sep->se_count++ == 0)
583			(void)gettimeofday(&sep->se_time, NULL);
584		else if (sep->se_count >= sep->se_max) {
585			struct timeval now;
586
587			(void)gettimeofday(&now, NULL);
588			if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
589				sep->se_time = now;
590				sep->se_count = 1;
591			} else {
592				syslog(LOG_ERR,
593				    "%s/%s max spawn rate (%d in %d seconds) "
594				    "exceeded; service not started",
595				    sep->se_service, sep->se_proto,
596				    sep->se_max, CNT_INTVL);
597				if (!sep->se_wait && sep->se_socktype ==
598				    SOCK_STREAM)
599					close(ctrl);
600				close_sep(sep);
601				if (!timingout) {
602					timingout = 1;
603					alarm(RETRYTIME);
604				}
605				return;
606			}
607		}
608		pid = fork();
609		if (pid < 0) {
610			syslog(LOG_ERR, "fork: %m");
611			if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
612				close(ctrl);
613			sleep(1);
614			return;
615		}
616		if (pid != 0 && sep->se_wait) {
617			struct kevent	*ev;
618
619			sep->se_wait = pid;
620			ev = allocchange();
621			EV_SET(ev, sep->se_fd, EVFILT_READ,
622			    EV_DELETE, 0, 0, 0);
623		}
624		if (pid == 0) {
625			size_t	n;
626
627			for (n = 0; n < A_CNT(my_signals); n++)
628				(void) signal(my_signals[n], SIG_DFL);
629			if (debug)
630				setsid();
631		}
632	}
633	if (pid == 0) {
634		run_service(ctrl, sep, dofork);
635		if (dofork)
636			exit(0);
637	}
638	if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
639		close(ctrl);
640}
641
642static void
643run_service(int ctrl, struct servtab *sep, int didfork)
644{
645	struct passwd *pwd;
646	struct group *grp = NULL;	/* XXX gcc */
647	char buf[NI_MAXSERV];
648	struct servtab *s;
649#ifdef LIBWRAP
650	struct request_info req;
651	int denied;
652	char *service = NULL;	/* XXX gcc */
653#endif
654
655#ifdef LIBWRAP
656#ifndef LIBWRAP_INTERNAL
657	if (sep->se_bi == 0)
658#endif
659	if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
660		request_init(&req, RQ_DAEMON, sep->se_argv[0] ?
661		    sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
662		fromhost(&req);
663		denied = !hosts_access(&req);
664		if (denied || lflag) {
665			if (getnameinfo(&sep->se_ctrladdr,
666					sep->se_ctrladdr.sa_len, NULL, 0,
667					buf, sizeof(buf), 0) != 0) {
668				/* shouldn't happen */
669				(void)snprintf(buf, sizeof buf, "%d",
670				    ntohs(sep->se_ctrladdr_in.sin_port));
671			}
672			service = buf;
673		}
674		if (denied) {
675			syslog(deny_severity,
676			    "refused connection from %.500s, service %s (%s)",
677			    eval_client(&req), service, sep->se_proto);
678			goto reject;
679		}
680		if (lflag) {
681			syslog(allow_severity,
682			    "connection from %.500s, service %s (%s)",
683			    eval_client(&req), service, sep->se_proto);
684		}
685	}
686#endif /* LIBWRAP */
687
688	if (sep->se_bi) {
689		if (didfork) {
690			for (s = servtab; s; s = s->se_next)
691				if (s->se_fd != -1 && s->se_fd != ctrl)
692					close(s->se_fd);
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#ifdef MULOG
731		if (sep->se_log)
732			dolog(sep, ctrl);
733#endif
734		/* Set our control descriptor to not close-on-exec... */
735		if (fcntl(ctrl, F_SETFD, 0) < 0)
736			syslog(LOG_ERR, "fcntl (F_SETFD, 0): %m");
737		/* ...and dup it to stdin, stdout, and stderr. */
738		if (ctrl != 0) {
739			dup2(ctrl, 0);
740			close(ctrl);
741			ctrl = 0;
742		}
743		dup2(0, 1);
744		dup2(0, 2);
745#ifdef RLIMIT_NOFILE
746		if (rlim_ofile.rlim_cur != rlim_ofile_cur &&
747		    setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
748			syslog(LOG_ERR, "setrlimit: %m");
749#endif
750		execv(sep->se_server, sep->se_argv);
751		syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server);
752	reject:
753		if (sep->se_socktype != SOCK_STREAM)
754			recv(ctrl, buf, sizeof (buf), 0);
755		_exit(1);
756	}
757}
758
759static void
760reapchild(void)
761{
762	int status;
763	pid_t pid;
764	struct servtab *sep;
765
766	for (;;) {
767		pid = wait3(&status, WNOHANG, NULL);
768		if (pid <= 0)
769			break;
770		if (debug)
771			(void) fprintf(stderr, "%d reaped, status %#x\n",
772			    pid, status);
773		for (sep = servtab; sep != NULL; sep = sep->se_next)
774			if (sep->se_wait == pid) {
775				struct kevent	*ev;
776
777				if (WIFEXITED(status) && WEXITSTATUS(status))
778					syslog(LOG_WARNING,
779					    "%s: exit status 0x%x",
780					    sep->se_server, WEXITSTATUS(status));
781				else if (WIFSIGNALED(status))
782					syslog(LOG_WARNING,
783					    "%s: exit signal 0x%x",
784					    sep->se_server, WTERMSIG(status));
785				sep->se_wait = 1;
786				ev = allocchange();
787				EV_SET(ev, sep->se_fd, EVFILT_READ,
788				    EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep);
789				if (debug)
790					fprintf(stderr, "restored %s, fd %d\n",
791					    sep->se_service, sep->se_fd);
792			}
793	}
794}
795
796static void
797config(void)
798{
799	struct servtab *sep, *cp, **sepp;
800	size_t n;
801
802	if (!setconfig()) {
803		syslog(LOG_ERR, "%s: %m", CONFIG);
804		return;
805	}
806	for (sep = servtab; sep != NULL; sep = sep->se_next)
807		sep->se_checked = 0;
808	while ((cp = getconfigent())) {
809		for (sep = servtab; sep != NULL; sep = sep->se_next)
810			if (strcmp(sep->se_service, cp->se_service) == 0 &&
811			    strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
812			    strcmp(sep->se_proto, cp->se_proto) == 0 &&
813			    ISMUX(sep) == ISMUX(cp))
814				break;
815		if (sep != NULL) {
816			int i;
817
818#define SWAP(type, a, b) {type c = a; a = b; b = c;}
819
820			/*
821			 * sep->se_wait may be holding the pid of a daemon
822			 * that we're waiting for.  If so, don't overwrite
823			 * it unless the config file explicitly says don't
824			 * wait.
825			 */
826			if (cp->se_bi == 0 &&
827			    (sep->se_wait == 1 || cp->se_wait == 0))
828				sep->se_wait = cp->se_wait;
829			SWAP(char *, sep->se_user, cp->se_user);
830			SWAP(char *, sep->se_group, cp->se_group);
831			SWAP(char *, sep->se_server, cp->se_server);
832			for (i = 0; i < MAXARGV; i++)
833				SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
834#ifdef IPSEC
835			SWAP(char *, sep->se_policy, cp->se_policy);
836#endif
837			SWAP(int, cp->se_type, sep->se_type);
838			SWAP(int, cp->se_max, sep->se_max);
839#undef SWAP
840			if (isrpcservice(sep))
841				unregister_rpc(sep);
842			sep->se_rpcversl = cp->se_rpcversl;
843			sep->se_rpcversh = cp->se_rpcversh;
844			freeconfig(cp);
845			if (debug)
846				print_service("REDO", sep);
847		} else {
848			sep = enter(cp);
849			if (debug)
850				print_service("ADD ", sep);
851		}
852		sep->se_checked = 1;
853
854		switch (sep->se_family) {
855		case AF_LOCAL:
856			if (sep->se_fd != -1)
857				break;
858			n = strlen(sep->se_service);
859			if (n > sizeof(sep->se_ctrladdr_un.sun_path)) {
860				syslog(LOG_ERR, "%s: address too long",
861				    sep->se_service);
862				sep->se_checked = 0;
863				continue;
864			}
865			(void)unlink(sep->se_service);
866			strncpy(sep->se_ctrladdr_un.sun_path,
867			    sep->se_service, n);
868			sep->se_ctrladdr_un.sun_family = AF_LOCAL;
869			sep->se_ctrladdr_size = n +
870			    sizeof(sep->se_ctrladdr_un) -
871			    sizeof(sep->se_ctrladdr_un.sun_path);
872			if (!ISMUX(sep))
873				setup(sep);
874			break;
875		case AF_INET:
876#ifdef INET6
877		case AF_INET6:
878#endif
879		    {
880			struct addrinfo hints, *res;
881			char *host, *port;
882			int error;
883			int s;
884
885			/* check if the family is supported */
886			s = socket(sep->se_family, SOCK_DGRAM, 0);
887			if (s < 0) {
888				syslog(LOG_WARNING,
889				    "%s/%s: %s: the address family is not "
890				    "supported by the kernel",
891				    sep->se_service, sep->se_proto,
892				    sep->se_hostaddr);
893				sep->se_checked = 0;
894				continue;
895			}
896			close(s);
897
898			memset(&hints, 0, sizeof(hints));
899			hints.ai_family = sep->se_family;
900			hints.ai_socktype = sep->se_socktype;
901			hints.ai_flags = AI_PASSIVE;
902			if (!strcmp(sep->se_hostaddr, "*"))
903				host = NULL;
904			else
905				host = sep->se_hostaddr;
906			if (isrpcservice(sep) || ISMUX(sep))
907				port = "0";
908			else
909				port = sep->se_service;
910			error = getaddrinfo(host, port, &hints, &res);
911			if (error) {
912				if (error == EAI_SERVICE) {
913					/* gai_strerror not friendly enough */
914					syslog(LOG_WARNING, "%s/%s: "
915					    "unknown service",
916					    sep->se_service, sep->se_proto);
917				} else {
918					syslog(LOG_ERR, "%s/%s: %s: %s",
919					    sep->se_service, sep->se_proto,
920					    sep->se_hostaddr,
921					    gai_strerror(error));
922				}
923				sep->se_checked = 0;
924				continue;
925			}
926			if (res->ai_next) {
927				syslog(LOG_ERR,
928					"%s/%s: %s: resolved to multiple addr",
929				    sep->se_service, sep->se_proto,
930				    sep->se_hostaddr);
931				sep->se_checked = 0;
932				freeaddrinfo(res);
933				continue;
934			}
935			memcpy(&sep->se_ctrladdr, res->ai_addr,
936				res->ai_addrlen);
937			if (ISMUX(sep)) {
938				sep->se_fd = -1;
939				freeaddrinfo(res);
940				continue;
941			}
942			sep->se_ctrladdr_size = res->ai_addrlen;
943			freeaddrinfo(res);
944#ifdef RPC
945			if (isrpcservice(sep)) {
946				struct rpcent *rp;
947
948				sep->se_rpcprog = atoi(sep->se_service);
949				if (sep->se_rpcprog == 0) {
950					rp = getrpcbyname(sep->se_service);
951					if (rp == 0) {
952						syslog(LOG_ERR,
953						    "%s/%s: unknown service",
954						    sep->se_service,
955						    sep->se_proto);
956						sep->se_checked = 0;
957						continue;
958					}
959					sep->se_rpcprog = rp->r_number;
960				}
961				if (sep->se_fd == -1 && !ISMUX(sep))
962					setup(sep);
963				if (sep->se_fd != -1)
964					register_rpc(sep);
965			} else
966#endif
967			{
968				if (sep->se_fd >= 0)
969					close_sep(sep);
970				if (sep->se_fd == -1 && !ISMUX(sep))
971					setup(sep);
972			}
973		    }
974		}
975	}
976	endconfig();
977	/*
978	 * Purge anything not looked at above.
979	 */
980	sepp = &servtab;
981	while ((sep = *sepp)) {
982		if (sep->se_checked) {
983			sepp = &sep->se_next;
984			continue;
985		}
986		*sepp = sep->se_next;
987		if (sep->se_fd >= 0)
988			close_sep(sep);
989		if (isrpcservice(sep))
990			unregister_rpc(sep);
991		if (sep->se_family == AF_LOCAL)
992			(void)unlink(sep->se_service);
993		if (debug)
994			print_service("FREE", sep);
995		freeconfig(sep);
996		free(sep);
997	}
998}
999
1000static void
1001retry(void)
1002{
1003	struct servtab *sep;
1004
1005	timingout = 0;
1006	for (sep = servtab; sep != NULL; sep = sep->se_next) {
1007		if (sep->se_fd == -1 && !ISMUX(sep)) {
1008			switch (sep->se_family) {
1009			case AF_LOCAL:
1010			case AF_INET:
1011#ifdef INET6
1012			case AF_INET6:
1013#endif
1014				setup(sep);
1015				if (sep->se_fd != -1 && isrpcservice(sep))
1016					register_rpc(sep);
1017				break;
1018			}
1019		}
1020	}
1021}
1022
1023static void
1024goaway(void)
1025{
1026	struct servtab *sep;
1027
1028	for (sep = servtab; sep != NULL; sep = sep->se_next) {
1029		if (sep->se_fd == -1)
1030			continue;
1031
1032		switch (sep->se_family) {
1033		case AF_LOCAL:
1034			(void)unlink(sep->se_service);
1035			break;
1036		case AF_INET:
1037#ifdef INET6
1038		case AF_INET6:
1039#endif
1040			if (sep->se_wait == 1 && isrpcservice(sep))
1041				unregister_rpc(sep);
1042			break;
1043		}
1044		(void)close(sep->se_fd);
1045	}
1046	exit(0);
1047}
1048
1049static void
1050setup(struct servtab *sep)
1051{
1052	int		on = 1;
1053#ifdef INET6
1054	int		off = 0;
1055#endif
1056	struct kevent	*ev;
1057
1058	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1059		if (debug)
1060			fprintf(stderr, "socket failed on %s/%s: %s\n",
1061			    sep->se_service, sep->se_proto, strerror(errno));
1062		syslog(LOG_ERR, "%s/%s: socket: %m",
1063		    sep->se_service, sep->se_proto);
1064		return;
1065	}
1066	/* Set all listening sockets to close-on-exec. */
1067	if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
1068		syslog(LOG_ERR, "%s/%s: fcntl(F_SETFD, FD_CLOEXEC): %m",
1069		    sep->se_service, sep->se_proto);
1070		close(sep->se_fd);
1071		return;
1072	}
1073
1074#define	turnon(fd, opt) \
1075setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1076	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1077	    turnon(sep->se_fd, SO_DEBUG) < 0)
1078		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1079	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1080		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1081#undef turnon
1082
1083	/* Set the socket buffer sizes, if specified. */
1084	if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1085	    SO_SNDBUF, (char *)&sep->se_sndbuf, sizeof(sep->se_sndbuf)) < 0)
1086		syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m",
1087		    sep->se_sndbuf);
1088	if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1089	    SO_RCVBUF, (char *)&sep->se_rcvbuf, sizeof(sep->se_rcvbuf)) < 0)
1090		syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m",
1091		    sep->se_rcvbuf);
1092#ifdef INET6
1093	if (sep->se_family == AF_INET6) {
1094		int *v;
1095		v = (sep->se_type == FAITH_TYPE) ? &on : &off;
1096		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH,
1097		    (char *)v, sizeof(*v)) < 0)
1098			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1099	}
1100#endif
1101#ifdef IPSEC
1102	if (ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy) < 0 &&
1103	    sep->se_policy) {
1104		syslog(LOG_ERR, "%s/%s: ipsec setup failed",
1105		    sep->se_service, sep->se_proto);
1106		(void)close(sep->se_fd);
1107		sep->se_fd = -1;
1108		return;
1109	}
1110#endif
1111
1112	if (bind(sep->se_fd, &sep->se_ctrladdr, 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	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 > 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 *)&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(sep->se_rpcprog, n, nconf);
1186		if (!rpcb_set(sep->se_rpcprog, 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(sep->se_rpcprog, 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 = (struct servtab *)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))) {
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#ifdef MULOG
1316		/* Avoid use of `skip' if there is a danger of it looking
1317		 * at continuation lines.
1318		 */
1319		do {
1320			cp++;
1321		} while (*cp == ' ' || *cp == '\t');
1322		if (*cp == '\0')
1323			continue;
1324		if ((arg = skip(&cp)) == NULL)
1325			continue;
1326		if (strcmp(arg, "DOMAIN"))
1327			continue;
1328		if (curdom)
1329			free(curdom);
1330		curdom = NULL;
1331		while (*cp == ' ' || *cp == '\t')
1332			cp++;
1333		if (*cp == '\0')
1334			continue;
1335		arg = cp;
1336		while (*cp && *cp != ' ' && *cp != '\t')
1337			cp++;
1338		if (*cp != '\0')
1339			*cp++ = '\0';
1340		curdom = newstr(arg);
1341#endif
1342		break;
1343	}
1344	if (cp == NULL)
1345		return (NULL);
1346	/*
1347	 * clear the static buffer, since some fields (se_ctrladdr,
1348	 * for example) don't get initialized here.
1349	 */
1350	memset((caddr_t)sep, 0, sizeof *sep);
1351	arg = skip(&cp);
1352	if (cp == NULL) {
1353		/* got an empty line containing just blanks/tabs. */
1354		goto more;
1355	}
1356	/* Check for a host name. */
1357	hostdelim = strrchr(arg, ':');
1358	if (hostdelim) {
1359		*hostdelim = '\0';
1360		if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1361			hostdelim[-1] = '\0';
1362			sep->se_hostaddr = newstr(arg + 1);
1363		} else
1364			sep->se_hostaddr = newstr(arg);
1365		arg = hostdelim + 1;
1366		/*
1367		 * If the line is of the form `host:', then just change the
1368		 * default host for the following lines.
1369		 */
1370		if (*arg == '\0') {
1371			arg = skip(&cp);
1372			if (cp == NULL) {
1373				free(defhost);
1374				defhost = sep->se_hostaddr;
1375				goto more;
1376			}
1377		}
1378	} else
1379		sep->se_hostaddr = newstr(defhost);
1380	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1381		char *c = arg + MUX_LEN;
1382		if (*c == '+') {
1383			sep->se_type = MUXPLUS_TYPE;
1384			c++;
1385		} else
1386			sep->se_type = MUX_TYPE;
1387		sep->se_service = newstr(c);
1388	} else {
1389		sep->se_service = newstr(arg);
1390		sep->se_type = NORM_TYPE;
1391	}
1392
1393	arg = sskip(&cp);
1394	if (strcmp(arg, "stream") == 0)
1395		sep->se_socktype = SOCK_STREAM;
1396	else if (strcmp(arg, "dgram") == 0)
1397		sep->se_socktype = SOCK_DGRAM;
1398	else if (strcmp(arg, "rdm") == 0)
1399		sep->se_socktype = SOCK_RDM;
1400	else if (strcmp(arg, "seqpacket") == 0)
1401		sep->se_socktype = SOCK_SEQPACKET;
1402	else if (strcmp(arg, "raw") == 0)
1403		sep->se_socktype = SOCK_RAW;
1404	else
1405		sep->se_socktype = -1;
1406
1407	arg = sskip(&cp);
1408	if (sep->se_type == NORM_TYPE &&
1409	    strncmp(arg, "faith/", strlen("faith/")) == 0) {
1410		arg += strlen("faith/");
1411		sep->se_type = FAITH_TYPE;
1412	}
1413	sep->se_proto = newstr(arg);
1414
1415#define	MALFORMED(arg) \
1416do { \
1417	syslog(LOG_ERR, "%s: malformed buffer size option `%s'", \
1418	    sep->se_service, (arg)); \
1419	goto more; \
1420} while (0)
1421
1422#define	GETVAL(arg) \
1423do { \
1424	if (!isdigit((unsigned char)*(arg))) \
1425		MALFORMED(arg); \
1426	val = strtol((arg), &cp0, 10); \
1427	if (cp0 != NULL) { \
1428		if (cp0[1] != '\0') \
1429			MALFORMED((arg)); \
1430		if (cp0[0] == 'k') \
1431			val *= 1024; \
1432		if (cp0[0] == 'm') \
1433			val *= 1024 * 1024; \
1434	} \
1435	if (val < 1) { \
1436		syslog(LOG_ERR, "%s: invalid buffer size `%s'", \
1437		    sep->se_service, (arg)); \
1438		goto more; \
1439	} \
1440} while (0)
1441
1442#define	ASSIGN(arg) \
1443do { \
1444	if (strcmp((arg), "sndbuf") == 0) \
1445		sep->se_sndbuf = val; \
1446	else if (strcmp((arg), "rcvbuf") == 0) \
1447		sep->se_rcvbuf = val; \
1448	else \
1449		MALFORMED((arg)); \
1450} while (0)
1451
1452	/*
1453	 * Extract the send and receive buffer sizes before parsing
1454	 * the protocol.
1455	 */
1456	sep->se_sndbuf = sep->se_rcvbuf = 0;
1457	buf0 = buf1 = sz0 = sz1 = NULL;
1458	if ((buf0 = strchr(sep->se_proto, ',')) != NULL) {
1459		/* Not meaningful for Tcpmux services. */
1460		if (ISMUX(sep)) {
1461			syslog(LOG_ERR, "%s: can't specify buffer sizes for "
1462			    "tcpmux services", sep->se_service);
1463			goto more;
1464		}
1465
1466		/* Skip the , */
1467		*buf0++ = '\0';
1468
1469		/* Check to see if another socket buffer size was specified. */
1470		if ((buf1 = strchr(buf0, ',')) != NULL) {
1471			/* Skip the , */
1472			*buf1++ = '\0';
1473
1474			/* Make sure a 3rd one wasn't specified. */
1475			if (strchr(buf1, ',') != NULL) {
1476				syslog(LOG_ERR, "%s: too many buffer sizes",
1477				    sep->se_service);
1478				goto more;
1479			}
1480
1481			/* Locate the size. */
1482			if ((sz1 = strchr(buf1, '=')) == NULL)
1483				MALFORMED(buf1);
1484
1485			/* Skip the = */
1486			*sz1++ = '\0';
1487		}
1488
1489		/* Locate the size. */
1490		if ((sz0 = strchr(buf0, '=')) == NULL)
1491			MALFORMED(buf0);
1492
1493		/* Skip the = */
1494		*sz0++ = '\0';
1495
1496		GETVAL(sz0);
1497		ASSIGN(buf0);
1498
1499		if (buf1 != NULL) {
1500			GETVAL(sz1);
1501			ASSIGN(buf1);
1502		}
1503	}
1504
1505#undef ASSIGN
1506#undef GETVAL
1507#undef MALFORMED
1508
1509	if (strcmp(sep->se_proto, "unix") == 0) {
1510		sep->se_family = AF_LOCAL;
1511	} else {
1512		val = strlen(sep->se_proto);
1513		if (!val) {
1514			syslog(LOG_ERR, "%s: invalid protocol specified",
1515			    sep->se_service);
1516			goto more;
1517		}
1518		val = sep->se_proto[val - 1];
1519		switch (val) {
1520		case '4':	/*tcp4 or udp4*/
1521			sep->se_family = AF_INET;
1522			break;
1523#ifdef INET6
1524		case '6':	/*tcp6 or udp6*/
1525			sep->se_family = AF_INET6;
1526			break;
1527#endif
1528		default:
1529			sep->se_family = AF_INET;	/*will become AF_INET6*/
1530			break;
1531		}
1532		if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1533#ifdef RPC
1534			char *cp, *ccp;
1535			cp = strchr(sep->se_service, '/');
1536			if (cp == 0) {
1537				syslog(LOG_ERR, "%s: no rpc version",
1538				    sep->se_service);
1539				goto more;
1540			}
1541			*cp++ = '\0';
1542			sep->se_rpcversl = sep->se_rpcversh =
1543			    strtol(cp, &ccp, 0);
1544			if (ccp == cp) {
1545		badafterall:
1546				syslog(LOG_ERR, "%s/%s: bad rpc version",
1547				    sep->se_service, cp);
1548				goto more;
1549			}
1550			if (*ccp == '-') {
1551				cp = ccp + 1;
1552				sep->se_rpcversh = strtol(cp, &ccp, 0);
1553				if (ccp == cp)
1554					goto badafterall;
1555			}
1556#else
1557			syslog(LOG_ERR, "%s: rpc services not suported",
1558			    sep->se_service);
1559			goto more;
1560#endif /* RPC */
1561		}
1562	}
1563	arg = sskip(&cp);
1564	{
1565		char *cp;
1566		if ((cp = strchr(arg, ':')) == NULL)
1567			cp = strchr(arg, '.');
1568		if (cp != NULL) {
1569			*cp++ = '\0';
1570			sep->se_max = atoi(cp);
1571		} else
1572			sep->se_max = TOOMANY;
1573	}
1574	sep->se_wait = strcmp(arg, "wait") == 0;
1575	if (ISMUX(sep)) {
1576		/*
1577		 * Silently enforce "nowait" for TCPMUX services since
1578		 * they don't have an assigned port to listen on.
1579		 */
1580		sep->se_wait = 0;
1581
1582		if (strncmp(sep->se_proto, "tcp", 3)) {
1583			syslog(LOG_ERR,
1584			    "%s: bad protocol for tcpmux service %s",
1585			    CONFIG, sep->se_service);
1586			goto more;
1587		}
1588		if (sep->se_socktype != SOCK_STREAM) {
1589			syslog(LOG_ERR,
1590			    "%s: bad socket type for tcpmux service %s",
1591			    CONFIG, sep->se_service);
1592			goto more;
1593		}
1594	}
1595	sep->se_user = newstr(sskip(&cp));
1596	if ((sep->se_group = strchr(sep->se_user, ':')) != NULL)
1597		*sep->se_group++ = '\0';
1598	else if ((sep->se_group = strchr(sep->se_user, '.')) != NULL)
1599		*sep->se_group++ = '\0';
1600
1601	sep->se_server = newstr(sskip(&cp));
1602	if (strcmp(sep->se_server, "internal") == 0) {
1603		struct biltin *bi;
1604
1605		for (bi = biltins; bi->bi_service; bi++)
1606			if (bi->bi_socktype == sep->se_socktype &&
1607			    strcmp(bi->bi_service, sep->se_service) == 0)
1608				break;
1609		if (bi->bi_service == 0) {
1610			syslog(LOG_ERR, "internal service %s unknown",
1611			    sep->se_service);
1612			goto more;
1613		}
1614		sep->se_bi = bi;
1615		sep->se_wait = bi->bi_wait;
1616	} else
1617		sep->se_bi = NULL;
1618	argc = 0;
1619	for (arg = skip(&cp); cp; arg = skip(&cp)) {
1620#if MULOG
1621		char *colon;
1622
1623		if (argc == 0 && (colon = strrchr(arg, ':'))) {
1624			while (arg < colon) {
1625				int	x;
1626				char	*ccp;
1627
1628				switch (*arg++) {
1629				case 'l':
1630					x = 1;
1631					if (isdigit(*arg)) {
1632						x = strtol(arg, &ccp, 0);
1633						if (ccp == arg)
1634							break;
1635						arg = ccp;
1636					}
1637					sep->se_log &= ~MULOG_RFC931;
1638					sep->se_log |= x;
1639					break;
1640				case 'a':
1641					sep->se_log |= MULOG_RFC931;
1642					break;
1643				default:
1644					break;
1645				}
1646			}
1647			arg = colon + 1;
1648		}
1649#endif
1650		if (argc < MAXARGV)
1651			sep->se_argv[argc++] = newstr(arg);
1652	}
1653	while (argc <= MAXARGV)
1654		sep->se_argv[argc++] = NULL;
1655#ifdef IPSEC
1656	sep->se_policy = policy ? newstr(policy) : NULL;
1657#endif
1658	return (sep);
1659}
1660
1661static void
1662freeconfig(struct servtab *cp)
1663{
1664	int i;
1665
1666	if (cp->se_hostaddr)
1667		free(cp->se_hostaddr);
1668	if (cp->se_service)
1669		free(cp->se_service);
1670	if (cp->se_proto)
1671		free(cp->se_proto);
1672	if (cp->se_user)
1673		free(cp->se_user);
1674	/* Note: se_group is part of the newstr'ed se_user */
1675	if (cp->se_server)
1676		free(cp->se_server);
1677	for (i = 0; i < MAXARGV; i++)
1678		if (cp->se_argv[i])
1679			free(cp->se_argv[i]);
1680#ifdef IPSEC
1681	if (cp->se_policy)
1682		free(cp->se_policy);
1683#endif
1684}
1685
1686
1687/*
1688 * Safe skip - if skip returns null, log a syntax error in the
1689 * configuration file and exit.
1690 */
1691static char *
1692sskip(char **cpp)
1693{
1694	char *cp;
1695
1696	cp = skip(cpp);
1697	if (cp == NULL) {
1698		syslog(LOG_ERR, "%s: syntax error", CONFIG);
1699		exit(1);
1700	}
1701	return (cp);
1702}
1703
1704static char *
1705skip(char **cpp)
1706{
1707	char *cp = *cpp;
1708	char *start;
1709	char quote;
1710
1711	if (*cpp == NULL)
1712		return (NULL);
1713
1714again:
1715	while (*cp == ' ' || *cp == '\t')
1716		cp++;
1717	if (*cp == '\0') {
1718		int c;
1719
1720		c = getc(fconfig);
1721		(void) ungetc(c, fconfig);
1722		if (c == ' ' || c == '\t')
1723			if ((cp = nextline(fconfig)))
1724				goto again;
1725		*cpp = NULL;
1726		return (NULL);
1727	}
1728	start = cp;
1729	quote = '\0';
1730	while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) {
1731		if (*cp == '\'' || *cp == '"') {
1732			if (quote && *cp != quote)
1733				cp++;
1734			else {
1735				if (quote)
1736					quote = '\0';
1737				else
1738					quote = *cp;
1739				memmove(cp, cp+1, strlen(cp));
1740			}
1741		} else
1742			cp++;
1743	}
1744	if (*cp != '\0')
1745		*cp++ = '\0';
1746	*cpp = cp;
1747	return (start);
1748}
1749
1750static char *
1751nextline(FILE *fd)
1752{
1753	char *cp;
1754
1755	if (fgets(line, sizeof (line), fd) == NULL)
1756		return (NULL);
1757	cp = strchr(line, '\n');
1758	if (cp)
1759		*cp = '\0';
1760	return (line);
1761}
1762
1763static char *
1764newstr(char *cp)
1765{
1766	if ((cp = strdup((cp != NULL) ? cp : "")) != NULL)
1767		return (cp);
1768	syslog(LOG_ERR, "strdup: %m");
1769	exit(1);
1770}
1771
1772static void
1773inetd_setproctitle(char *a, int s)
1774{
1775	socklen_t size;
1776	struct sockaddr_storage ss;
1777	char hbuf[NI_MAXHOST], *hp;
1778
1779	size = sizeof(ss);
1780	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1781		if (getnameinfo((struct sockaddr *)&ss, size, hp = hbuf,
1782		    sizeof(hbuf), NULL, 0, niflags) != 0)
1783			hp = "?";
1784		setproctitle("-%s [%s]", a, hp);
1785	} else
1786		setproctitle("-%s", a);
1787}
1788
1789static void
1790bump_nofile(void)
1791{
1792#ifdef RLIMIT_NOFILE
1793
1794#define FD_CHUNK	32
1795
1796	struct rlimit rl;
1797
1798	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1799		syslog(LOG_ERR, "getrlimit: %m");
1800		return;
1801	}
1802	rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1803	if (rl.rlim_cur <= rlim_ofile_cur) {
1804		syslog(LOG_ERR,
1805		    "bump_nofile: cannot extend file limit, max = %d",
1806		    (int)rl.rlim_cur);
1807		return;
1808	}
1809
1810	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1811		syslog(LOG_ERR, "setrlimit: %m");
1812		return;
1813	}
1814
1815	rlim_ofile_cur = rl.rlim_cur;
1816	return;
1817
1818#else
1819	syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
1820	return;
1821#endif
1822}
1823
1824/*
1825 * Internet services provided internally by inetd:
1826 */
1827#define	BUFSIZE	4096
1828
1829/* ARGSUSED */
1830static void
1831echo_stream(int s, struct servtab *sep)	/* Echo service -- echo data back */
1832{
1833	char buffer[BUFSIZE];
1834	int i;
1835
1836	inetd_setproctitle(sep->se_service, s);
1837	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1838	    write(s, buffer, i) > 0)
1839		;
1840}
1841
1842/* ARGSUSED */
1843static void
1844echo_dg(int s, struct servtab *sep)	/* Echo service -- echo data back */
1845{
1846	char buffer[BUFSIZE];
1847	int i;
1848	socklen_t size;
1849	struct sockaddr_storage ss;
1850	struct sockaddr *sa;
1851
1852	sa = (struct sockaddr *)&ss;
1853	size = sizeof(ss);
1854	if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1855		return;
1856	if (port_good_dg(sa))
1857		(void) sendto(s, buffer, i, 0, sa, size);
1858}
1859
1860/* ARGSUSED */
1861static void
1862discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1863{
1864	char buffer[BUFSIZE];
1865
1866	inetd_setproctitle(sep->se_service, s);
1867	while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1868			errno == EINTR)
1869		;
1870}
1871
1872/* ARGSUSED */
1873static void
1874discard_dg(int s, struct servtab *sep)	/* Discard service -- ignore data */
1875
1876{
1877	char buffer[BUFSIZE];
1878
1879	(void) read(s, buffer, sizeof(buffer));
1880}
1881
1882#define LINESIZ 72
1883char ring[128];
1884char *endring;
1885
1886static void
1887initring(void)
1888{
1889	int i;
1890
1891	endring = ring;
1892
1893	for (i = 0; i <= 128; ++i)
1894		if (isprint(i))
1895			*endring++ = i;
1896}
1897
1898/* ARGSUSED */
1899static void
1900chargen_stream(int s,struct servtab *sep)	/* Character generator */
1901{
1902	int len;
1903	char *rs, text[LINESIZ+2];
1904
1905	inetd_setproctitle(sep->se_service, s);
1906
1907	if (!endring) {
1908		initring();
1909		rs = ring;
1910	}
1911
1912	text[LINESIZ] = '\r';
1913	text[LINESIZ + 1] = '\n';
1914	for (rs = ring;;) {
1915		if ((len = endring - rs) >= LINESIZ)
1916			memmove(text, rs, LINESIZ);
1917		else {
1918			memmove(text, rs, len);
1919			memmove(text + len, ring, LINESIZ - len);
1920		}
1921		if (++rs == endring)
1922			rs = ring;
1923		if (write(s, text, sizeof(text)) != sizeof(text))
1924			break;
1925	}
1926}
1927
1928/* ARGSUSED */
1929static void
1930chargen_dg(int s, struct servtab *sep)		/* Character generator */
1931{
1932	struct sockaddr_storage ss;
1933	struct sockaddr *sa;
1934	static char *rs;
1935	int len;
1936	socklen_t size;
1937	char text[LINESIZ+2];
1938
1939	if (endring == 0) {
1940		initring();
1941		rs = ring;
1942	}
1943
1944	sa = (struct sockaddr *)&ss;
1945	size = sizeof(ss);
1946	if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
1947		return;
1948
1949	if (!port_good_dg(sa))
1950		return;
1951
1952	if ((len = endring - rs) >= LINESIZ)
1953		memmove(text, rs, LINESIZ);
1954	else {
1955		memmove(text, rs, len);
1956		memmove(text + len, ring, LINESIZ - len);
1957	}
1958	if (++rs == endring)
1959		rs = ring;
1960	text[LINESIZ] = '\r';
1961	text[LINESIZ + 1] = '\n';
1962	(void) sendto(s, text, sizeof(text), 0, sa, size);
1963}
1964
1965/*
1966 * Return a machine readable date and time, in the form of the
1967 * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1968 * returns the number of seconds since midnight, Jan 1, 1970,
1969 * we must add 2208988800 seconds to this figure to make up for
1970 * some seventy years Bell Labs was asleep.
1971 */
1972
1973static uint32_t
1974machtime(void)
1975{
1976	struct timeval tv;
1977
1978	if (gettimeofday(&tv, NULL) < 0) {
1979		if (debug)
1980			fprintf(stderr, "Unable to get time of day\n");
1981		return (0);
1982	}
1983#define	OFFSET ((uint32_t)25567 * 24*60*60)
1984	return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1985#undef OFFSET
1986}
1987
1988/* ARGSUSED */
1989static void
1990machtime_stream(int s, struct servtab *sep)
1991{
1992	uint32_t result;
1993
1994	result = machtime();
1995	(void) write(s, (char *) &result, sizeof(result));
1996}
1997
1998/* ARGSUSED */
1999void
2000machtime_dg(int s, struct servtab *sep)
2001{
2002	uint32_t result;
2003	struct sockaddr_storage ss;
2004	struct sockaddr *sa;
2005	socklen_t size;
2006
2007	sa = (struct sockaddr *)&ss;
2008	size = sizeof(ss);
2009	if (recvfrom(s, (char *)&result, sizeof(result), 0, sa, &size) < 0)
2010		return;
2011	if (!port_good_dg(sa))
2012		return;
2013	result = machtime();
2014	(void) sendto(s, (char *) &result, sizeof(result), 0, sa, size);
2015}
2016
2017/* ARGSUSED */
2018static void
2019daytime_stream(int s,struct servtab *sep)
2020/* Return human-readable time of day */
2021{
2022	char buffer[256];
2023	time_t clock;
2024	int len;
2025
2026	clock = time((time_t *) 0);
2027
2028	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
2029	(void) write(s, buffer, len);
2030}
2031
2032/* ARGSUSED */
2033void
2034daytime_dg(int s, struct servtab *sep)
2035/* Return human-readable time of day */
2036{
2037	char buffer[256];
2038	time_t clock;
2039	struct sockaddr_storage ss;
2040	struct sockaddr *sa;
2041	socklen_t size;
2042	int len;
2043
2044	clock = time((time_t *) 0);
2045
2046	sa = (struct sockaddr *)&ss;
2047	size = sizeof(ss);
2048	if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
2049		return;
2050	if (!port_good_dg(sa))
2051		return;
2052	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
2053	(void) sendto(s, buffer, len, 0, sa, size);
2054}
2055
2056/*
2057 * print_service:
2058 *	Dump relevant information to stderr
2059 */
2060static void
2061print_service(char *action, struct servtab *sep)
2062{
2063
2064	if (isrpcservice(sep))
2065		fprintf(stderr,
2066		    "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2067#ifdef IPSEC
2068		    " policy=\"%s\""
2069#endif
2070		    "\n",
2071		    action, sep->se_service,
2072		    sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
2073		    sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
2074		    (long)sep->se_bi, sep->se_server
2075#ifdef IPSEC
2076		    , (sep->se_policy ? sep->se_policy : "")
2077#endif
2078		    );
2079	else
2080		fprintf(stderr,
2081		    "%s: %s proto=%s%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2082#ifdef IPSEC
2083		    " policy=%s"
2084#endif
2085		    "\n",
2086		    action, sep->se_service,
2087		    sep->se_type == FAITH_TYPE ? "faith/" : "",
2088		    sep->se_proto,
2089		    sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
2090		    (long)sep->se_bi, sep->se_server
2091#ifdef IPSEC
2092		    , (sep->se_policy ? sep->se_policy : "")
2093#endif
2094		    );
2095}
2096
2097static void
2098usage(void)
2099{
2100#ifdef LIBWRAP
2101	(void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2102#else
2103	(void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2104#endif
2105	exit(1);
2106}
2107
2108
2109/*
2110 *  Based on TCPMUX.C by Mark K. Lottor November 1988
2111 *  sri-nic::ps:<mkl>tcpmux.c
2112 */
2113
2114static int		/* # of characters upto \r,\n or \0 */
2115getline(int fd,	char *buf, int len)
2116{
2117	int count = 0, n;
2118
2119	do {
2120		n = read(fd, buf, len-count);
2121		if (n == 0)
2122			return (count);
2123		if (n < 0)
2124			return (-1);
2125		while (--n >= 0) {
2126			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2127				return (count);
2128			count++;
2129			buf++;
2130		}
2131	} while (count < len);
2132	return (count);
2133}
2134
2135#define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
2136
2137#define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
2138
2139static void
2140tcpmux(int ctrl, struct servtab *sep)
2141{
2142	char service[MAX_SERV_LEN+1];
2143	int len;
2144
2145	/* Get requested service name */
2146	if ((len = getline(ctrl, service, MAX_SERV_LEN)) < 0) {
2147		strwrite(ctrl, "-Error reading service name\r\n");
2148		goto reject;
2149	}
2150	service[len] = '\0';
2151
2152	if (debug)
2153		fprintf(stderr, "tcpmux: someone wants %s\n", service);
2154
2155	/*
2156	 * Help is a required command, and lists available services,
2157	 * one per line.
2158	 */
2159	if (!strcasecmp(service, "help")) {
2160		strwrite(ctrl, "+Available services:\r\n");
2161		strwrite(ctrl, "help\r\n");
2162		for (sep = servtab; sep != NULL; sep = sep->se_next) {
2163			if (!ISMUX(sep))
2164				continue;
2165			(void)write(ctrl, sep->se_service,
2166			    strlen(sep->se_service));
2167			strwrite(ctrl, "\r\n");
2168		}
2169		goto reject;
2170	}
2171
2172	/* Try matching a service in inetd.conf with the request */
2173	for (sep = servtab; sep != NULL; sep = sep->se_next) {
2174		if (!ISMUX(sep))
2175			continue;
2176		if (!strcasecmp(service, sep->se_service)) {
2177			if (ISMUXPLUS(sep))
2178				strwrite(ctrl, "+Go\r\n");
2179			run_service(ctrl, sep, 1 /* forked */);
2180			return;
2181		}
2182	}
2183	strwrite(ctrl, "-Service not available\r\n");
2184reject:
2185	_exit(1);
2186}
2187
2188#ifdef MULOG
2189void
2190dolog(struct servtab *sep, int ctrl)
2191{
2192	struct sockaddr_storage	ss;
2193	struct sockaddr		*sa = (struct sockaddr *)&ss;
2194	socklen_t		len = sizeof(ss);
2195	char			*host, *dp, buf[BUFSIZ];
2196	int			connected = 1;
2197
2198	switch (sep->se_family) {
2199	case AF_INET:
2200#ifdef INET6
2201	case AF_INET6:
2202#endif
2203		break;
2204	default:
2205		return;
2206	}
2207
2208	if (getpeername(ctrl, sa, &len) < 0) {
2209		if (errno != ENOTCONN) {
2210			syslog(LOG_ERR, "getpeername: %m");
2211			return;
2212		}
2213		if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, sa, &len) < 0) {
2214			syslog(LOG_ERR, "recvfrom: %m");
2215			return;
2216		}
2217		connected = 0;
2218	}
2219	switch (sa->sa_family) {
2220	case AF_INET:
2221#ifdef INET6
2222	case AF_INET6:
2223#endif
2224		break;
2225	default:
2226		syslog(LOG_ERR, "unexpected address family %u", sa->sa_family);
2227		return;
2228	}
2229
2230	if (getnameinfo(sa, len, buf, sizeof(buf), NULL, 0, 0) != 0)
2231		strlcpy(buf, "?", sizeof(buf));
2232	host = buf;
2233
2234	switch (sep->se_log & ~MULOG_RFC931) {
2235	case 0:
2236		return;
2237	case 1:
2238		if (curdom == NULL || *curdom == '\0')
2239			break;
2240		dp = host + strlen(host) - strlen(curdom);
2241		if (dp < host)
2242			break;
2243		if (debug)
2244			fprintf(stderr, "check \"%s\" against curdom \"%s\"\n",
2245			    host, curdom);
2246		if (strcasecmp(dp, curdom) == 0)
2247			return;
2248		break;
2249	case 2:
2250	default:
2251		break;
2252	}
2253
2254	openlog("", LOG_NOWAIT, MULOG);
2255
2256	if (connected && (sep->se_log & MULOG_RFC931))
2257		syslog(LOG_INFO, "%s@%s wants %s",
2258		    rfc931_name(sa, ctrl), host, sep->se_service);
2259	else
2260		syslog(LOG_INFO, "%s wants %s",
2261		    host, sep->se_service);
2262}
2263
2264/*
2265 * From tcp_log by
2266 *  Wietse Venema, Eindhoven University of Technology, The Netherlands.
2267 */
2268#if 0
2269static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46";
2270#endif
2271
2272#include <setjmp.h>
2273
2274#define	RFC931_PORT	113		/* Semi-well-known port */
2275#define	TIMEOUT		4
2276#define	TIMEOUT2	10
2277
2278static jmp_buf timebuf;
2279
2280/* timeout - handle timeouts */
2281
2282static void
2283timeout(int sig)
2284{
2285	longjmp(timebuf, sig);
2286}
2287
2288/* rfc931_name - return remote user name */
2289
2290char *
2291rfc931_name(struct sockaddr *there,	/* remote link information */
2292    int ctrl)
2293{
2294	struct sockaddr_storage here;	/* local link information */
2295	struct sockaddr_storage sin;	/* for talking to RFC931 daemon */
2296	socklen_t	length;
2297	int		s;
2298	unsigned	remote;
2299	unsigned	local;
2300	static char	user[256];		/* XXX */
2301	char		buf[256];
2302	char		*cp;
2303	char		*result = "USER_UNKNOWN";
2304	int		len;
2305	u_int16_t	myport, hisport;
2306
2307	/* Find out local port number of our stdin. */
2308
2309	length = sizeof(here);
2310	if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) {
2311		syslog(LOG_ERR, "getsockname: %m");
2312		return (result);
2313	}
2314	switch (here.ss_family) {
2315	case AF_INET:
2316		myport = ((struct sockaddr_in *)&here)->sin_port;
2317		break;
2318#ifdef INET6
2319	case AF_INET6:
2320		myport = ((struct sockaddr_in6 *)&here)->sin6_port;
2321		break;
2322#endif
2323	}
2324	switch (there->sa_family) {
2325	case AF_INET:
2326		hisport = ((struct sockaddr_in *)&there)->sin_port;
2327		break;
2328#ifdef INET6
2329	case AF_INET6:
2330		hisport = ((struct sockaddr_in6 *)&there)->sin6_port;
2331		break;
2332#endif
2333	}
2334	/* Set up timer so we won't get stuck. */
2335
2336	if ((s = socket(here.ss_family, SOCK_STREAM, 0)) == -1) {
2337		syslog(LOG_ERR, "socket: %m");
2338		return (result);
2339	}
2340
2341	sin = here;
2342	switch (sin.ss_family) {
2343	case AF_INET:
2344		((struct sockaddr_in *)&sin)->sin_port = htons(0);
2345		break;
2346#ifdef INET6
2347	case AF_INET6:
2348		((struct sockaddr_in6 *)&sin)->sin6_port = htons(0);
2349		break;
2350#endif
2351	}
2352	if (bind(s, (struct sockaddr *) &sin, sin.ss_len) == -1) {
2353		syslog(LOG_ERR, "bind: %m");
2354		return (result);
2355	}
2356
2357	signal(SIGALRM, timeout);
2358	if (setjmp(timebuf)) {
2359		close(s);			/* not: fclose(fp) */
2360		return (result);
2361	}
2362	alarm(TIMEOUT);
2363
2364	/* Connect to the RFC931 daemon. */
2365
2366	memcpy(&sin, there, there->sa_len);
2367	switch (sin.ss_family) {
2368	case AF_INET:
2369		((struct sockaddr_in *)&sin)->sin_port = htons(RFC931_PORT);
2370		break;
2371#ifdef INET6
2372	case AF_INET6:
2373		((struct sockaddr_in6 *)&sin)->sin6_port = htons(RFC931_PORT);
2374		break;
2375#endif
2376	}
2377	if (connect(s, (struct sockaddr *) &sin, sin.ss_len) == -1) {
2378		close(s);
2379		alarm(0);
2380		return (result);
2381	}
2382
2383	/* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
2384	(void)snprintf(buf, sizeof buf, "%u,%u\r\n", ntohs(hisport),
2385	    ntohs(myport));
2386
2387	for (len = 0, cp = buf; len < strlen(buf); ) {
2388		int	n;
2389
2390		if ((n = write(s, cp, strlen(buf) - len)) == -1) {
2391			close(s);
2392			alarm(0);
2393			return (result);
2394		}
2395		cp += n;
2396		len += n;
2397	}
2398
2399	/* Read response */
2400	for (cp = buf; cp < buf + sizeof(buf) - 1; ) {
2401		char	c;
2402		if (read(s, &c, 1) != 1) {
2403			close(s);
2404			alarm(0);
2405			return (result);
2406		}
2407		if (c == '\n')
2408			break;
2409		*cp++ = c;
2410	}
2411	*cp = '\0';
2412
2413	if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local,
2414	    user) == 3 && ntohs(hisport) == remote && ntohs(myport) == local) {
2415		/* Strip trailing carriage return. */
2416		if ((cp = strchr(user, '\r')) != NULL)
2417			*cp = 0;
2418		result = user;
2419	}
2420
2421	alarm(0);
2422	close(s);
2423	return (result);
2424}
2425#endif
2426
2427/*
2428 * check if the address/port where send data to is one of the obvious ports
2429 * that are used for denial of service attacks like two echo ports
2430 * just echoing data between them
2431 */
2432static int
2433port_good_dg(struct sockaddr *sa)
2434{
2435	struct in_addr in;
2436#ifdef INET6
2437	struct in6_addr *in6;
2438#endif
2439	u_int16_t port;
2440	int i, bad;
2441	char hbuf[NI_MAXHOST];
2442
2443	bad = 0;
2444
2445	switch (sa->sa_family) {
2446	case AF_INET:
2447		in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
2448		port = ntohs(((struct sockaddr_in *)sa)->sin_port);
2449#ifdef INET6
2450	v4chk:
2451#endif
2452		if (IN_MULTICAST(in.s_addr))
2453			goto bad;
2454		switch ((in.s_addr & 0xff000000) >> 24) {
2455		case 0: case 127: case 255:
2456			goto bad;
2457		}
2458		if (dg_broadcast(&in))
2459			goto bad;
2460		break;
2461#ifdef INET6
2462	case AF_INET6:
2463		in6 = &((struct sockaddr_in6 *)sa)->sin6_addr;
2464		port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
2465		if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
2466			goto bad;
2467		if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
2468			memcpy(&in, &in6->s6_addr[12], sizeof(in));
2469			in.s_addr = ntohl(in.s_addr);
2470			goto v4chk;
2471		}
2472		break;
2473#endif
2474	default:
2475		/* XXX unsupported af, is it safe to assume it to be safe? */
2476		return (1);
2477	}
2478
2479	for (i = 0; bad_ports[i] != 0; i++) {
2480		if (port == bad_ports[i])
2481			goto bad;
2482	}
2483
2484	return (1);
2485
2486bad:
2487	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
2488	    niflags) != 0)
2489		strlcpy(hbuf, "?", sizeof(hbuf));
2490	syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2491		hbuf, port);
2492	return (0);
2493}
2494
2495/* XXX need optimization */
2496static int
2497dg_broadcast(struct in_addr *in)
2498{
2499	struct ifaddrs *ifa, *ifap;
2500	struct sockaddr_in *sin;
2501
2502	if (getifaddrs(&ifap) < 0)
2503		return (0);
2504	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2505		if (ifa->ifa_addr->sa_family != AF_INET ||
2506		    (ifa->ifa_flags & IFF_BROADCAST) == 0)
2507			continue;
2508		sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
2509		if (sin->sin_addr.s_addr == in->s_addr) {
2510			freeifaddrs(ifap);
2511			return (1);
2512		}
2513	}
2514	freeifaddrs(ifap);
2515	return (0);
2516}
2517
2518static int
2519my_kevent(const struct kevent *changelist, size_t nchanges,
2520    struct kevent *eventlist, size_t nevents)
2521{
2522	int	result;
2523
2524	while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2525	    NULL)) < 0)
2526		if (errno != EINTR) {
2527			syslog(LOG_ERR, "kevent: %m");
2528			exit(EXIT_FAILURE);
2529		}
2530
2531	return (result);
2532}
2533
2534static struct kevent *
2535allocchange(void)
2536{
2537	if (changes == A_CNT(changebuf)) {
2538		(void) my_kevent(changebuf, A_CNT(changebuf), NULL, 0);
2539		changes = 0;
2540	}
2541
2542	return (&changebuf[changes++]);
2543}
2544