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