xref: /netbsd-src/usr.sbin/inetd/inetd.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /*	$NetBSD: inetd.c,v 1.139 2021/10/17 04:14:49 ryo 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.139 2021/10/17 04:14:49 ryo 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 MAXARGV (64)
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 MAXARGV (64)
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/wait.h>
191 #include <sys/resource.h>
192 #include <sys/event.h>
193 #include <sys/socket.h>
194 #include <sys/queue.h>
195 
196 
197 #ifndef NO_RPC
198 #define RPC
199 #endif
200 
201 #include <net/if.h>
202 
203 #ifdef RPC
204 #include <rpc/rpc.h>
205 #include <rpc/rpcb_clnt.h>
206 #include <netconfig.h>
207 #endif
208 
209 #include <ctype.h>
210 #include <err.h>
211 #include <errno.h>
212 #include <fcntl.h>
213 #include <glob.h>
214 #include <grp.h>
215 #include <libgen.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 "inetd.h"
227 
228 #ifdef LIBWRAP
229 # include <tcpd.h>
230 #ifndef LIBWRAP_ALLOW_FACILITY
231 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
232 #endif
233 #ifndef LIBWRAP_ALLOW_SEVERITY
234 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
235 #endif
236 #ifndef LIBWRAP_DENY_FACILITY
237 # define LIBWRAP_DENY_FACILITY LOG_AUTH
238 #endif
239 #ifndef LIBWRAP_DENY_SEVERITY
240 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
241 #endif
242 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
243 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
244 #endif
245 
246 static bool foreground;
247 int	debug;
248 #ifdef LIBWRAP
249 int	lflag;
250 #endif
251 int	maxsock;
252 int	kq;
253 int	options;
254 int	timingout;
255 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
256 
257 #ifndef OPEN_MAX
258 #define OPEN_MAX	64
259 #endif
260 
261 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
262 #define FD_MARGIN	(8)
263 rlim_t		rlim_ofile_cur = OPEN_MAX;
264 
265 struct rlimit	rlim_ofile;
266 
267 struct kevent	changebuf[64];
268 size_t		changes;
269 
270 struct servtab *servtab;
271 
272 static ssize_t	recvfromto(int, void * restrict, size_t, int,
273     struct sockaddr * restrict, socklen_t * restrict,
274     struct sockaddr * restrict, socklen_t * restrict);
275 static ssize_t	sendfromto(int, const void *, size_t, int,
276     const struct sockaddr *, socklen_t, const struct sockaddr *, socklen_t);
277 static void	chargen_dg(int, struct servtab *);
278 static void	chargen_stream(int, struct servtab *);
279 static void	daytime_dg(int, struct servtab *);
280 static void	daytime_stream(int, struct servtab *);
281 static void	discard_dg(int, struct servtab *);
282 static void	discard_stream(int, struct servtab *);
283 static void	echo_dg(int, struct servtab *);
284 static void	echo_stream(int, struct servtab *);
285 __dead static void	goaway(void);
286 static void	machtime_dg(int, struct servtab *);
287 static void	machtime_stream(int, struct servtab *);
288 static void	reapchild(void);
289 static void	retry(void);
290 static void	run_service(int, struct servtab *, int);
291 static void	tcpmux(int, struct servtab *);
292 __dead static void	usage(void);
293 static void	bump_nofile(void);
294 static void	inetd_setproctitle(char *, int);
295 static void	initring(void);
296 static uint32_t	machtime(void);
297 static int	port_good_dg(struct sockaddr *);
298 static int	dg_broadcast(struct in_addr *);
299 static int	my_kevent(const struct kevent *, size_t, struct kevent *, size_t);
300 static struct kevent	*allocchange(void);
301 static int	get_line(int, char *, int);
302 static void	spawn(struct servtab *, int);
303 
304 struct biltin {
305 	const char *bi_service;		/* internally provided service name */
306 	int	bi_socktype;		/* type of socket supported */
307 	short	bi_fork;		/* 1 if should fork before call */
308 	short	bi_wait;		/* 1 if should wait for child */
309 	void	(*bi_fn)(int, struct servtab *);
310 					/* function which performs it */
311 } biltins[] = {
312 	/* Echo received data */
313 	{ "echo",	SOCK_STREAM,	true, false,	echo_stream },
314 	{ "echo",	SOCK_DGRAM,	false, false,	echo_dg },
315 
316 	/* Internet /dev/null */
317 	{ "discard",	SOCK_STREAM,	true, false,	discard_stream },
318 	{ "discard",	SOCK_DGRAM,	false, false,	discard_dg },
319 
320 	/* Return 32 bit time since 1970 */
321 	{ "time",	SOCK_STREAM,	false, false,	machtime_stream },
322 	{ "time",	SOCK_DGRAM,	false, false,	machtime_dg },
323 
324 	/* Return human-readable time */
325 	{ "daytime",	SOCK_STREAM,	false, false,	daytime_stream },
326 	{ "daytime",	SOCK_DGRAM,	false, false,	daytime_dg },
327 
328 	/* Familiar character generator */
329 	{ "chargen",	SOCK_STREAM,	true, false,	chargen_stream },
330 	{ "chargen",	SOCK_DGRAM,	false, false,	chargen_dg },
331 
332 	{ "tcpmux",	SOCK_STREAM,	true, false,	tcpmux }
333 };
334 
335 /* list of "bad" ports. I.e. ports that are most obviously used for
336  * "cycling packets" denial of service attacks. See /etc/services.
337  * List must end with port number "0".
338  */
339 
340 u_int16_t bad_ports[] =  { 7, 9, 13, 19, 37, 0 };
341 
342 
343 #define NUMINT	(sizeof(intab) / sizeof(struct inent))
344 const char	*CONFIG = _PATH_INETDCONF;
345 
346 static int my_signals[] =
347     { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE };
348 
349 int
350 main(int argc, char *argv[])
351 {
352 	int		ch, n, reload = 1;
353 
354 	while ((ch = getopt(argc, argv,
355 #ifdef LIBWRAP
356 					"dfl"
357 #else
358 					"df"
359 #endif
360 					   )) != -1)
361 		switch(ch) {
362 		case 'd':
363 			foreground = true;
364 			debug = true;
365 			options |= SO_DEBUG;
366 			break;
367 		case 'f':
368 			foreground = true;
369 			break;
370 #ifdef LIBWRAP
371 		case 'l':
372 			lflag = true;
373 			break;
374 #endif
375 		case '?':
376 		default:
377 			usage();
378 		}
379 	argc -= optind;
380 	argv += optind;
381 
382 	if (argc > 0)
383 		CONFIG = argv[0];
384 
385 	if (!foreground)
386 		daemon(0, 0);
387 	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
388 	pidfile(NULL);
389 
390 	kq = kqueue();
391 	if (kq < 0) {
392 		syslog(LOG_ERR, "kqueue: %m");
393 		return (EXIT_FAILURE);
394 	}
395 
396 	if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
397 		syslog(LOG_ERR, "getrlimit: %m");
398 	} else {
399 		rlim_ofile_cur = rlim_ofile.rlim_cur;
400 		if (rlim_ofile_cur == RLIM_INFINITY)	/* ! */
401 			rlim_ofile_cur = OPEN_MAX;
402 	}
403 
404 	for (n = 0; n < (int)__arraycount(my_signals); n++) {
405 		int	signum;
406 
407 		signum = my_signals[n];
408 		if (signum != SIGCHLD)
409 			(void) signal(signum, SIG_IGN);
410 
411 		if (signum != SIGPIPE) {
412 			struct kevent	*ev;
413 
414 			ev = allocchange();
415 			EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE,
416 			    0, 0, 0);
417 		}
418 	}
419 
420 	for (;;) {
421 		int		ctrl;
422 		struct kevent	eventbuf[64], *ev;
423 		struct servtab	*sep;
424 
425 		if (reload) {
426 			reload = false;
427 			config_root();
428 		}
429 
430 		n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf));
431 		changes = 0;
432 
433 		for (ev = eventbuf; n > 0; ev++, n--) {
434 			if (ev->filter == EVFILT_SIGNAL) {
435 				switch (ev->ident) {
436 				case SIGALRM:
437 					retry();
438 					break;
439 				case SIGCHLD:
440 					reapchild();
441 					break;
442 				case SIGTERM:
443 				case SIGINT:
444 					goaway();
445 					break;
446 				case SIGHUP:
447 					reload = true;
448 					break;
449 				}
450 				continue;
451 			}
452 			if (ev->filter != EVFILT_READ)
453 				continue;
454 			sep = (struct servtab *)ev->udata;
455 			/* Paranoia */
456 			if ((int)ev->ident != sep->se_fd)
457 				continue;
458 			DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep));
459 			if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
460 				/* XXX here do the libwrap check-before-accept*/
461 				ctrl = accept(sep->se_fd, NULL, NULL);
462 				DPRINTF(SERV_FMT ": accept, ctrl fd %d",
463 				    SERV_PARAMS(sep), ctrl);
464 				if (ctrl < 0) {
465 					if (errno != EINTR)
466 						syslog(LOG_WARNING,
467 						    SERV_FMT ": accept: %m",
468 						    SERV_PARAMS(sep));
469 					continue;
470 				}
471 			} else
472 				ctrl = sep->se_fd;
473 			spawn(sep, ctrl);
474 		}
475 	}
476 }
477 
478 static void
479 spawn(struct servtab *sep, int ctrl)
480 {
481 	int dofork;
482 	pid_t pid;
483 
484 	pid = 0;
485 #ifdef LIBWRAP_INTERNAL
486 	dofork = true;
487 #else
488 	dofork = (sep->se_bi == NULL || sep->se_bi->bi_fork);
489 #endif
490 	if (dofork) {
491 		if (rl_process(sep, ctrl)) {
492 			return;
493 		}
494 		pid = fork();
495 		if (pid < 0) {
496 			syslog(LOG_ERR, "fork: %m");
497 			if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM)
498 				close(ctrl);
499 			sleep(1);
500 			return;
501 		}
502 		if (pid != 0 && sep->se_wait != 0) {
503 			struct kevent	*ev;
504 
505 			sep->se_wait = pid;
506 			ev = allocchange();
507 			EV_SET(ev, sep->se_fd, EVFILT_READ,
508 			    EV_DELETE, 0, 0, 0);
509 		}
510 		if (pid == 0) {
511 			size_t	n;
512 
513 			for (n = 0; n < __arraycount(my_signals); n++)
514 				(void) signal(my_signals[n], SIG_DFL);
515 			/* Don't put services in terminal session */
516 			if (foreground)
517 				setsid();
518 		}
519 	}
520 	if (pid == 0) {
521 		run_service(ctrl, sep, dofork);
522 		if (dofork)
523 			exit(EXIT_SUCCESS);
524 	}
525 	if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM)
526 		close(ctrl);
527 }
528 
529 static void
530 run_service(int ctrl, struct servtab *sep, int didfork)
531 {
532 	struct passwd *pwd;
533 	struct group *grp = NULL;	/* XXX gcc */
534 	char buf[NI_MAXSERV];
535 	struct servtab *s;
536 #ifdef LIBWRAP
537 	char abuf[BUFSIZ];
538 	struct request_info req;
539 	int denied;
540 	char *service = NULL;	/* XXX gcc */
541 #endif
542 
543 #ifdef LIBWRAP
544 #ifndef LIBWRAP_INTERNAL
545 	if (sep->se_bi == 0)
546 #endif
547 	if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
548 		request_init(&req, RQ_DAEMON, sep->se_argv[0] != NULL ?
549 		    sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
550 		fromhost(&req);
551 		denied = hosts_access(&req) == 0;
552 		if (denied || lflag) {
553 			if (getnameinfo(&sep->se_ctrladdr,
554 			    (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0,
555 			    buf, sizeof(buf), 0) != 0) {
556 				/* shouldn't happen */
557 				(void)snprintf(buf, sizeof buf, "%d",
558 				    ntohs(sep->se_ctrladdr_in.sin_port));
559 			}
560 			service = buf;
561 			if (req.client->sin != NULL) {
562 				sockaddr_snprintf(abuf, sizeof(abuf), "%a",
563 				    req.client->sin);
564 			} else {
565 				strcpy(abuf, "(null)");
566 			}
567 		}
568 		if (denied) {
569 			syslog(deny_severity,
570 			    "refused connection from %.500s(%s), service %s (%s)",
571 			    eval_client(&req), abuf, service, sep->se_proto);
572 			goto reject;
573 		}
574 		if (lflag) {
575 			syslog(allow_severity,
576 			    "connection from %.500s(%s), service %s (%s)",
577 			    eval_client(&req), abuf, service, sep->se_proto);
578 		}
579 	}
580 #endif /* LIBWRAP */
581 
582 	if (sep->se_bi != NULL) {
583 		if (didfork) {
584 			for (s = servtab; s != NULL; s = s->se_next)
585 				if (s->se_fd != -1 && s->se_fd != ctrl) {
586 					close(s->se_fd);
587 					s->se_fd = -1;
588 				}
589 		}
590 		(*sep->se_bi->bi_fn)(ctrl, sep);
591 	} else {
592 		if ((pwd = getpwnam(sep->se_user)) == NULL) {
593 			syslog(LOG_ERR, "%s/%s: %s: No such user",
594 			    sep->se_service, sep->se_proto, sep->se_user);
595 			goto reject;
596 		}
597 		if (sep->se_group != NULL &&
598 		    (grp = getgrnam(sep->se_group)) == NULL) {
599 			syslog(LOG_ERR, "%s/%s: %s: No such group",
600 			    sep->se_service, sep->se_proto, sep->se_group);
601 			goto reject;
602 		}
603 		if (pwd->pw_uid != 0) {
604 			if (sep->se_group != NULL)
605 				pwd->pw_gid = grp->gr_gid;
606 			if (setgid(pwd->pw_gid) < 0) {
607 				syslog(LOG_ERR,
608 				 "%s/%s: can't set gid %d: %m", sep->se_service,
609 				    sep->se_proto, pwd->pw_gid);
610 				goto reject;
611 			}
612 			(void) initgroups(pwd->pw_name,
613 			    pwd->pw_gid);
614 			if (setuid(pwd->pw_uid) < 0) {
615 				syslog(LOG_ERR,
616 				 "%s/%s: can't set uid %d: %m", sep->se_service,
617 				    sep->se_proto, pwd->pw_uid);
618 				goto reject;
619 			}
620 		} else if (sep->se_group != NULL) {
621 			(void) setgid((gid_t)grp->gr_gid);
622 		}
623 		DPRINTF("%d execl %s",
624 		    getpid(), sep->se_server);
625 		/* Set our control descriptor to not close-on-exec... */
626 		if (fcntl(ctrl, F_SETFD, 0) < 0)
627 			syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl);
628 		/* ...and dup it to stdin, stdout, and stderr. */
629 		if (ctrl != 0) {
630 			dup2(ctrl, 0);
631 			close(ctrl);
632 			ctrl = 0;
633 		}
634 		dup2(0, 1);
635 		dup2(0, 2);
636 		if (rlim_ofile.rlim_cur != rlim_ofile_cur &&
637 		    setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
638 			syslog(LOG_ERR, "setrlimit: %m");
639 		execv(sep->se_server, sep->se_argv);
640 		syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server);
641 	reject:
642 		if (sep->se_socktype != SOCK_STREAM)
643 			recv(ctrl, buf, sizeof (buf), 0);
644 		_exit(EXIT_FAILURE);
645 	}
646 }
647 
648 static void
649 reapchild(void)
650 {
651 	int status;
652 	pid_t pid;
653 	struct servtab *sep;
654 
655 	for (;;) {
656 		pid = wait3(&status, WNOHANG, NULL);
657 		if (pid <= 0)
658 			break;
659 		DPRINTF("%d reaped, status %#x", pid, status);
660 		for (sep = servtab; sep != NULL; sep = sep->se_next)
661 			if (sep->se_wait == pid) {
662 				struct kevent	*ev;
663 
664 				if (WIFEXITED(status) && WEXITSTATUS(status))
665 					syslog(LOG_WARNING,
666 					    "%s: exit status %u",
667 					    sep->se_server, WEXITSTATUS(status));
668 				else if (WIFSIGNALED(status))
669 					syslog(LOG_WARNING,
670 					    "%s: exit signal %u",
671 					    sep->se_server, WTERMSIG(status));
672 				sep->se_wait = 1;
673 				ev = allocchange();
674 				EV_SET(ev, sep->se_fd, EVFILT_READ,
675 				    EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep);
676 				DPRINTF("restored %s, fd %d",
677 				    sep->se_service, sep->se_fd);
678 			}
679 	}
680 }
681 
682 static void
683 retry(void)
684 {
685 	struct servtab *sep;
686 
687 	timingout = false;
688 	for (sep = servtab; sep != NULL; sep = sep->se_next) {
689 		if (sep->se_fd == -1 && !ISMUX(sep)) {
690 			switch (sep->se_family) {
691 			case AF_LOCAL:
692 			case AF_INET:
693 #ifdef INET6
694 			case AF_INET6:
695 #endif
696 				setup(sep);
697 				if (sep->se_fd >= 0 && isrpcservice(sep))
698 					register_rpc(sep);
699 				break;
700 			}
701 		}
702 	}
703 }
704 
705 static void
706 goaway(void)
707 {
708 	struct servtab *sep;
709 
710 	for (sep = servtab; sep != NULL; sep = sep->se_next) {
711 		if (sep->se_fd == -1)
712 			continue;
713 
714 		switch (sep->se_family) {
715 		case AF_LOCAL:
716 			(void)unlink(sep->se_service);
717 			break;
718 		case AF_INET:
719 #ifdef INET6
720 		case AF_INET6:
721 #endif
722 			if (sep->se_wait == 1 && isrpcservice(sep))
723 				unregister_rpc(sep);
724 			break;
725 		}
726 		(void)close(sep->se_fd);
727 		sep->se_fd = -1;
728 	}
729 
730 	DPRINTF("Going away.");
731 
732 	exit(EXIT_SUCCESS);
733 }
734 
735 void
736 setup(struct servtab *sep)
737 {
738 	int		on = 1;
739 #ifdef INET6
740 	int		off = 0;
741 #endif
742 	struct kevent	*ev;
743 
744 	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
745 		DPRINTF("socket failed on " SERV_FMT ": %s",
746 		    SERV_PARAMS(sep), strerror(errno));
747 		syslog(LOG_ERR, "%s/%s: socket: %m",
748 		    sep->se_service, sep->se_proto);
749 		return;
750 	}
751 	/* Set all listening sockets to close-on-exec. */
752 	if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
753 		syslog(LOG_ERR, SERV_FMT ": fcntl(F_SETFD, FD_CLOEXEC): %m",
754 		    SERV_PARAMS(sep));
755 		close(sep->se_fd);
756 		sep->se_fd = -1;
757 		return;
758 	}
759 
760 #define	turnon(fd, opt) \
761 setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on))
762 	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
763 	    turnon(sep->se_fd, SO_DEBUG) < 0)
764 		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
765 	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
766 		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
767 #undef turnon
768 
769 	/* Set the socket buffer sizes, if specified. */
770 	if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
771 	    SO_SNDBUF, &sep->se_sndbuf, (socklen_t)sizeof(sep->se_sndbuf)) < 0)
772 		syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m",
773 		    sep->se_sndbuf);
774 	if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
775 	    SO_RCVBUF, &sep->se_rcvbuf, (socklen_t)sizeof(sep->se_rcvbuf)) < 0)
776 		syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m",
777 		    sep->se_rcvbuf);
778 #ifdef INET6
779 	if (sep->se_family == AF_INET6) {
780 		int *v;
781 		v = (sep->se_type == FAITH_TYPE) ? &on : &off;
782 		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH,
783 		    v, (socklen_t)sizeof(*v)) < 0)
784 			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
785 	}
786 #endif
787 #ifdef IPSEC
788 	/* Avoid setting a policy if a policy specifier doesn't exist. */
789 	if (sep->se_policy != NULL) {
790 		int e = ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy);
791 		if (e < 0) {
792 			syslog(LOG_ERR, SERV_FMT ": ipsec setup failed",
793 			    SERV_PARAMS(sep));
794 			(void)close(sep->se_fd);
795 			sep->se_fd = -1;
796 			return;
797 		}
798 	}
799 #endif
800 
801 	if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
802 		DPRINTF(SERV_FMT ": bind failed: %s",
803 			SERV_PARAMS(sep), strerror(errno));
804 		syslog(LOG_ERR, SERV_FMT ": bind: %m",
805 		    SERV_PARAMS(sep));
806 		(void) close(sep->se_fd);
807 		sep->se_fd = -1;
808 		if (!timingout) {
809 			timingout = true;
810 			alarm(RETRYTIME);
811 		}
812 		return;
813 	}
814 	if (sep->se_socktype == SOCK_STREAM)
815 		listen(sep->se_fd, 10);
816 
817 	/* for internal dgram, setsockopt() is required for recvfromto() */
818 	if (sep->se_socktype == SOCK_DGRAM && sep->se_bi != NULL) {
819 		switch (sep->se_family) {
820 		case AF_INET:
821 			if (setsockopt(sep->se_fd, IPPROTO_IP,
822 			    IP_RECVDSTADDR, &on, sizeof(on)) < 0)
823 				syslog(LOG_ERR,
824 				    "setsockopt (IP_RECVDSTADDR): %m");
825 			break;
826 #ifdef INET6
827 		case AF_INET6:
828 			if (setsockopt(sep->se_fd, IPPROTO_IPV6,
829 			    IPV6_RECVPKTINFO, &on, sizeof(on)) < 0)
830 				syslog(LOG_ERR,
831 				    "setsockopt (IPV6_RECVPKTINFO): %m");
832 			break;
833 #endif
834 		}
835 	}
836 
837 	/* Set the accept filter, if specified. To be done after listen.*/
838 	if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
839 	    SO_ACCEPTFILTER, &sep->se_accf,
840 	    (socklen_t)sizeof(sep->se_accf)) < 0)
841 		syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m",
842 		    sep->se_accf.af_name);
843 
844 	ev = allocchange();
845 	EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
846 	    (intptr_t)sep);
847 	if (sep->se_fd > maxsock) {
848 		maxsock = sep->se_fd;
849 		if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
850 			bump_nofile();
851 	}
852 	DPRINTF(SERV_FMT ": registered on fd %d", SERV_PARAMS(sep), sep->se_fd);
853 }
854 
855 /*
856  * Finish with a service and its socket.
857  */
858 void
859 close_sep(struct servtab *sep)
860 {
861 
862 	if (sep->se_fd >= 0) {
863 		(void) close(sep->se_fd);
864 		sep->se_fd = -1;
865 	}
866 	sep->se_count = 0;
867 	if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
868 		rl_clear_ip_list(sep);
869 	}
870 }
871 
872 void
873 register_rpc(struct servtab *sep)
874 {
875 #ifdef RPC
876 	struct netbuf nbuf;
877 	struct sockaddr_storage ss;
878 	struct netconfig *nconf;
879 	socklen_t socklen;
880 	int n;
881 
882 	if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
883 		syslog(LOG_ERR, "%s: getnetconfigent failed",
884 		    sep->se_proto);
885 		return;
886 	}
887 	socklen = sizeof ss;
888 	if (getsockname(sep->se_fd, (struct sockaddr *)(void *)&ss, &socklen) < 0) {
889 		syslog(LOG_ERR, SERV_FMT ": getsockname: %m",
890 		    SERV_PARAMS(sep));
891 		return;
892 	}
893 
894 	nbuf.buf = &ss;
895 	nbuf.len = ss.ss_len;
896 	nbuf.maxlen = sizeof (struct sockaddr_storage);
897 	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
898 		DPRINTF("rpcb_set: %u %d %s %s",
899 		    sep->se_rpcprog, n, nconf->nc_netid,
900 		    taddr2uaddr(nconf, &nbuf));
901 		(void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf);
902 		if (rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf) == 0)
903 			syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s",
904 			    sep->se_rpcprog, n, nconf->nc_netid,
905 			    taddr2uaddr(nconf, &nbuf), clnt_spcreateerror(""));
906 	}
907 #endif /* RPC */
908 }
909 
910 void
911 unregister_rpc(struct servtab *sep)
912 {
913 #ifdef RPC
914 	int n;
915 	struct netconfig *nconf;
916 
917 	if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
918 		syslog(LOG_ERR, "%s: getnetconfigent failed",
919 		    sep->se_proto);
920 		return;
921 	}
922 
923 	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
924 		DPRINTF("rpcb_unset(%u, %d, %s)",
925 		    sep->se_rpcprog, n, nconf->nc_netid);
926 		if (rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf) == 0)
927 			syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n",
928 			    sep->se_rpcprog, n, nconf->nc_netid);
929 	}
930 #endif /* RPC */
931 }
932 
933 static void
934 inetd_setproctitle(char *a, int s)
935 {
936 	socklen_t size;
937 	struct sockaddr_storage ss;
938 	char hbuf[NI_MAXHOST];
939 	const char *hp;
940 	struct sockaddr *sa;
941 
942 	size = sizeof(ss);
943 	sa = (struct sockaddr *)(void *)&ss;
944 	if (getpeername(s, sa, &size) == 0) {
945 		if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
946 		    0, niflags) != 0)
947 			hp = "?";
948 		else
949 			hp = hbuf;
950 		setproctitle("-%s [%s]", a, hp);
951 	} else
952 		setproctitle("-%s", a);
953 }
954 
955 static void
956 bump_nofile(void)
957 {
958 #define FD_CHUNK	32
959 	struct rlimit rl;
960 
961 	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
962 		syslog(LOG_ERR, "getrlimit: %m");
963 		return;
964 	}
965 	rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
966 	if (rl.rlim_cur <= rlim_ofile_cur) {
967 		syslog(LOG_ERR,
968 		    "bump_nofile: cannot extend file limit, max = %d",
969 		    (int)rl.rlim_cur);
970 		return;
971 	}
972 
973 	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
974 		syslog(LOG_ERR, "setrlimit: %m");
975 		return;
976 	}
977 
978 	rlim_ofile_cur = rl.rlim_cur;
979 	return;
980 }
981 
982 /*
983  * In order to get the destination address (`to') with recvfromto(),
984  * IP_RECVDSTADDR or IP_RECVPKTINFO for AF_INET, or IPV6_RECVPKTINFO
985  * for AF_INET6, must be enabled with setsockopt(2).
986  *
987  * .sin_port and .sin6_port in 'to' are always stored as zero.
988  * If necessary, extract them using getsockname(2).
989  */
990 static ssize_t
991 recvfromto(int s, void * restrict buf, size_t len, int flags,
992     struct sockaddr * restrict from, socklen_t * restrict fromlen,
993     struct sockaddr * restrict to, socklen_t * restrict tolen)
994 {
995 	struct msghdr msg;
996 	struct iovec vec;
997 	struct cmsghdr *cmsg;
998 	struct sockaddr_storage ss;
999 	char cmsgbuf[1024];
1000 	ssize_t rc;
1001 
1002 	if (to == NULL)
1003 		return recvfrom(s, buf, len, flags, from, fromlen);
1004 
1005 	if (tolen == NULL || fromlen == NULL) {
1006 		errno = EFAULT;
1007 		return -1;
1008 	}
1009 
1010 	vec.iov_base = buf;
1011 	vec.iov_len = len;
1012 	msg.msg_name = from;
1013 	msg.msg_namelen = *fromlen;
1014 	msg.msg_iov = &vec;
1015 	msg.msg_iovlen = 1;
1016 	msg.msg_control = cmsgbuf;
1017 	msg.msg_controllen = sizeof(cmsgbuf);
1018 
1019 	rc = recvmsg(s, &msg, flags);
1020 	if (rc < 0)
1021 		return rc;
1022 	*fromlen = msg.msg_namelen;
1023 
1024 	memset(&ss, 0, sizeof(ss));
1025 	for (cmsg = (struct cmsghdr *)CMSG_FIRSTHDR(&msg); cmsg != NULL;
1026 	    cmsg = (struct cmsghdr *)CMSG_NXTHDR(&msg, cmsg)) {
1027 		if (cmsg->cmsg_level == IPPROTO_IP &&
1028 		    cmsg->cmsg_type == IP_RECVDSTADDR) {
1029 			struct in_addr *dst = (struct in_addr *)CMSG_DATA(cmsg);
1030 			struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
1031 
1032 			sin->sin_len = sizeof(*sin);
1033 			sin->sin_family = AF_INET;
1034 			sin->sin_addr = *dst;
1035 			break;
1036 		}
1037 		if (cmsg->cmsg_level == IPPROTO_IP &&
1038 		    cmsg->cmsg_type == IP_PKTINFO) {
1039 			struct in_pktinfo *pi =
1040 			    (struct in_pktinfo *)CMSG_DATA(cmsg);
1041 			struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
1042 
1043 			sin->sin_len = sizeof(*sin);
1044 			sin->sin_family = AF_INET;
1045 			sin->sin_addr = pi->ipi_addr;
1046 			break;
1047 		}
1048 #ifdef INET6
1049 		if (cmsg->cmsg_level == IPPROTO_IPV6 &&
1050 		    cmsg->cmsg_type == IPV6_PKTINFO) {
1051 			struct in6_pktinfo *pi6 =
1052 			    (struct in6_pktinfo *)CMSG_DATA(cmsg);
1053 			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
1054 
1055 			sin6->sin6_len = sizeof(*sin6);
1056 			sin6->sin6_family = AF_INET6;
1057 			sin6->sin6_addr = pi6->ipi6_addr;
1058 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
1059 			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
1060 				sin6->sin6_scope_id = pi6->ipi6_ifindex;
1061 			else
1062 				sin6->sin6_scope_id = 0;
1063 			break;
1064 		}
1065 #endif /* INET6 */
1066 	}
1067 
1068 	socklen_t sslen = (*tolen < ss.ss_len) ? *tolen : ss.ss_len;
1069 	if (sslen > 0)
1070 		memcpy(to, &ss, sslen);
1071 	*tolen = sslen;
1072 
1073 	return rc;
1074 }
1075 
1076 /*
1077  * When sending, the source port is selected as the one bind(2)'ed
1078  * to the socket.
1079  * .sin_port and .sin6_port in `from' are always ignored.
1080  */
1081 static ssize_t
1082 sendfromto(int s, const void *buf, size_t len, int flags,
1083     const struct sockaddr *from, socklen_t fromlen,
1084     const struct sockaddr *to, socklen_t tolen)
1085 {
1086 	struct msghdr msg;
1087 	struct iovec vec;
1088 	struct cmsghdr *cmsg;
1089 	char cmsgbuf[256];
1090 	__CTASSERT(sizeof(cmsgbuf) > CMSG_SPACE(sizeof(struct in_pktinfo)));
1091 #ifdef INET6
1092 	__CTASSERT(sizeof(cmsgbuf) > CMSG_SPACE(sizeof(struct in6_pktinfo)));
1093 #endif
1094 
1095 	if (from == NULL || fromlen == 0)
1096 		return sendto(s, buf, len, flags, to, tolen);
1097 
1098 	vec.iov_base = __UNCONST(buf);
1099 	vec.iov_len = len;
1100 	msg.msg_name = __UNCONST(to);
1101 	msg.msg_namelen = tolen;
1102 	msg.msg_iov = &vec;
1103 	msg.msg_iovlen = 1;
1104 	msg.msg_control = cmsgbuf;
1105 	msg.msg_controllen = 0;
1106 
1107 	if (fromlen < 2) {	/* sa_len + sa_family */
1108 		errno = EINVAL;
1109 		return -1;
1110 	}
1111 
1112 	cmsg = (struct cmsghdr *)cmsgbuf;
1113 	if (from->sa_family == AF_INET) {
1114 		const struct sockaddr_in *from4 =
1115 		    (const struct sockaddr_in *)from;
1116 		struct in_pktinfo *pi;
1117 
1118 		if (fromlen != sizeof(struct sockaddr_in) ||
1119 		    from4->sin_family != AF_INET) {
1120 			errno = EINVAL;
1121 			return -1;
1122 		}
1123 
1124 		msg.msg_controllen += CMSG_SPACE(sizeof(struct in_pktinfo));
1125 		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1126 		cmsg->cmsg_level = IPPROTO_IP;
1127 		cmsg->cmsg_type = IP_PKTINFO;
1128 
1129 		pi = (struct in_pktinfo *)CMSG_DATA(cmsg);
1130 		pi->ipi_addr = from4->sin_addr;
1131 		pi->ipi_ifindex = 0;
1132 #ifdef INET6
1133 	} else if (from->sa_family == AF_INET6) {
1134 		const struct sockaddr_in6 *from6 =
1135 		    (const struct sockaddr_in6 *)from;
1136 		struct in6_pktinfo *pi6;
1137 
1138 		if (fromlen != sizeof(struct sockaddr_in6) ||
1139 		    from6->sin6_family != AF_INET6) {
1140 			errno = EINVAL;
1141 			return -1;
1142 		}
1143 
1144 		msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_pktinfo));
1145 		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1146 		cmsg->cmsg_level = IPPROTO_IPV6;
1147 		cmsg->cmsg_type = IPV6_PKTINFO;
1148 
1149 		pi6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1150 		pi6->ipi6_addr = from6->sin6_addr;
1151 		if (IN6_IS_ADDR_LINKLOCAL(&from6->sin6_addr) ||
1152 		    IN6_IS_ADDR_MC_LINKLOCAL(&from6->sin6_addr)) {
1153 			pi6->ipi6_ifindex = from6->sin6_scope_id;
1154 		} else {
1155 			pi6->ipi6_ifindex = 0;
1156 		}
1157 #endif /* INET6 */
1158 	} else {
1159 		return sendto(s, buf, len, flags, to, tolen);
1160 	}
1161 
1162 	return sendmsg(s, &msg, flags);
1163 }
1164 
1165 /*
1166  * Internet services provided internally by inetd:
1167  */
1168 #define	BUFSIZE	4096
1169 
1170 /* ARGSUSED */
1171 static void
1172 echo_stream(int s, struct servtab *sep)	/* Echo service -- echo data back */
1173 {
1174 	char buffer[BUFSIZE];
1175 	ssize_t i;
1176 
1177 	inetd_setproctitle(sep->se_service, s);
1178 	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1179 	    write(s, buffer, (size_t)i) > 0)
1180 		continue;
1181 }
1182 
1183 /* ARGSUSED */
1184 static void
1185 echo_dg(int s, struct servtab *sep)	/* Echo service -- echo data back */
1186 {
1187 	char buffer[BUFSIZE];
1188 	ssize_t i;
1189 	socklen_t rsize, lsize;
1190 	struct sockaddr_storage remote, local;
1191 	struct sockaddr *lsa, *rsa;
1192 
1193 	rsa = (struct sockaddr *)(void *)&remote;
1194 	lsa = (struct sockaddr *)(void *)&local;
1195 	rsize = sizeof(remote);
1196 	lsize = sizeof(local);
1197 	if ((i = recvfromto(s, buffer, sizeof(buffer), 0,
1198 	    rsa, &rsize, lsa, &lsize)) < 0)
1199 		return;
1200 	if (port_good_dg(rsa))
1201 		(void) sendfromto(s, buffer, (size_t)i, 0,
1202 		    lsa, lsize, rsa, rsize);
1203 }
1204 
1205 /* ARGSUSED */
1206 static void
1207 discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1208 {
1209 	char buffer[BUFSIZE];
1210 
1211 	inetd_setproctitle(sep->se_service, s);
1212 	while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1213 			errno == EINTR)
1214 		;
1215 }
1216 
1217 /* ARGSUSED */
1218 static void
1219 discard_dg(int s, struct servtab *sep)	/* Discard service -- ignore data */
1220 
1221 {
1222 	char buffer[BUFSIZE];
1223 
1224 	(void) read(s, buffer, sizeof(buffer));
1225 }
1226 
1227 #define LINESIZ 72
1228 char ring[128];
1229 char *endring;
1230 
1231 static void
1232 initring(void)
1233 {
1234 	int i;
1235 
1236 	endring = ring;
1237 
1238 	for (i = 0; i <= 128; ++i)
1239 		if (isprint(i))
1240 			*endring++ = (char)i;
1241 }
1242 
1243 /* ARGSUSED */
1244 static void
1245 chargen_stream(int s, struct servtab *sep)	/* Character generator */
1246 {
1247 	size_t len;
1248 	char *rs, text[LINESIZ+2];
1249 
1250 	inetd_setproctitle(sep->se_service, s);
1251 
1252 	if (endring == NULL) {
1253 		initring();
1254 		rs = ring;
1255 	}
1256 
1257 	text[LINESIZ] = '\r';
1258 	text[LINESIZ + 1] = '\n';
1259 	for (rs = ring;;) {
1260 		if ((len = (size_t)(endring - rs)) >= LINESIZ)
1261 			memmove(text, rs, LINESIZ);
1262 		else {
1263 			memmove(text, rs, len);
1264 			memmove(text + len, ring, LINESIZ - len);
1265 		}
1266 		if (++rs == endring)
1267 			rs = ring;
1268 		if (write(s, text, sizeof(text)) != sizeof(text))
1269 			break;
1270 	}
1271 }
1272 
1273 /* ARGSUSED */
1274 static void
1275 chargen_dg(int s, struct servtab *sep)		/* Character generator */
1276 {
1277 	struct sockaddr_storage remote, local;
1278 	struct sockaddr *rsa, *lsa;
1279 	static char *rs;
1280 	size_t len;
1281 	socklen_t rsize, lsize;
1282 	char text[LINESIZ+2];
1283 
1284 	if (endring == 0) {
1285 		initring();
1286 		rs = ring;
1287 	}
1288 
1289 	rsa = (struct sockaddr *)(void *)&remote;
1290 	lsa = (struct sockaddr *)(void *)&local;
1291 	rsize = sizeof(remote);
1292 	lsize = sizeof(local);
1293 	if (recvfromto(s, text, sizeof(text), 0,
1294 	    rsa, &rsize, lsa, &lsize) < 0)
1295 		return;
1296 
1297 	if (!port_good_dg(rsa))
1298 		return;
1299 
1300 	if ((len = (size_t)(endring - rs)) >= LINESIZ)
1301 		memmove(text, rs, LINESIZ);
1302 	else {
1303 		memmove(text, rs, len);
1304 		memmove(text + len, ring, LINESIZ - len);
1305 	}
1306 	if (++rs == endring)
1307 		rs = ring;
1308 	text[LINESIZ] = '\r';
1309 	text[LINESIZ + 1] = '\n';
1310 	(void) sendfromto(s, text, sizeof(text), 0, lsa, lsize, rsa, rsize);
1311 }
1312 
1313 /*
1314  * Return a machine readable date and time, in the form of the
1315  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1316  * returns the number of seconds since midnight, Jan 1, 1970,
1317  * we must add 2208988800 seconds to this figure to make up for
1318  * some seventy years Bell Labs was asleep.
1319  */
1320 
1321 static uint32_t
1322 machtime(void)
1323 {
1324 	struct timeval tv;
1325 
1326 	if (gettimeofday(&tv, NULL) < 0) {
1327 		DPRINTF("Unable to get time of day");
1328 		return (0);
1329 	}
1330 #define	OFFSET ((uint32_t)25567 * 24*60*60)
1331 	return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1332 #undef OFFSET
1333 }
1334 
1335 /* ARGSUSED */
1336 static void
1337 machtime_stream(int s, struct servtab *sep)
1338 {
1339 	uint32_t result;
1340 
1341 	result = machtime();
1342 	(void) write(s, &result, sizeof(result));
1343 }
1344 
1345 /* ARGSUSED */
1346 void
1347 machtime_dg(int s, struct servtab *sep)
1348 {
1349 	uint32_t result;
1350 	struct sockaddr_storage remote, local;
1351 	struct sockaddr *rsa, *lsa;
1352 	socklen_t rsize, lsize;
1353 
1354 	rsa = (struct sockaddr *)(void *)&remote;
1355 	lsa = (struct sockaddr *)(void *)&local;
1356 	rsize = sizeof(remote);
1357 	lsize = sizeof(local);
1358 	if (recvfromto(s, &result, sizeof(result), 0,
1359 	    rsa, &rsize, lsa, &lsize) < 0)
1360 		return;
1361 	if (!port_good_dg(rsa))
1362 		return;
1363 	result = machtime();
1364 	(void)sendfromto(s, &result, sizeof(result), 0, lsa, lsize, rsa, rsize);
1365 }
1366 
1367 /* ARGSUSED */
1368 static void
1369 daytime_stream(int s,struct servtab *sep)
1370 /* Return human-readable time of day */
1371 {
1372 	char buffer[256];
1373 	time_t clk;
1374 	int len;
1375 
1376 	clk = time((time_t *) 0);
1377 
1378 	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1379 	(void) write(s, buffer, (size_t)len);
1380 }
1381 
1382 /* ARGSUSED */
1383 void
1384 daytime_dg(int s, struct servtab *sep)
1385 /* Return human-readable time of day */
1386 {
1387 	char buffer[256];
1388 	time_t clk;
1389 	struct sockaddr_storage remote, local;
1390 	struct sockaddr *rsa, *lsa;
1391 	socklen_t rsize, lsize;
1392 	int len;
1393 
1394 	clk = time((time_t *) 0);
1395 
1396 	rsa = (struct sockaddr *)(void *)&remote;
1397 	lsa = (struct sockaddr *)(void *)&local;
1398 	rsize = sizeof(remote);
1399 	lsize = sizeof(local);
1400 	if (recvfromto(s, buffer, sizeof(buffer), 0,
1401 	    rsa, &rsize, lsa, &lsize) < 0)
1402 		return;
1403 	if (!port_good_dg(rsa))
1404 		return;
1405 	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1406 	(void) sendfromto(s, buffer, (size_t)len, 0, lsa, lsize, rsa, rsize);
1407 }
1408 
1409 static void
1410 usage(void)
1411 {
1412 #ifdef LIBWRAP
1413 	(void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
1414 #else
1415 	(void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
1416 #endif
1417 	exit(EXIT_FAILURE);
1418 }
1419 
1420 
1421 /*
1422  *  Based on TCPMUX.C by Mark K. Lottor November 1988
1423  *  sri-nic::ps:<mkl>tcpmux.c
1424  */
1425 
1426 static int		/* # of characters upto \r,\n or \0 */
1427 get_line(int fd,	char *buf, int len)
1428 {
1429 	int count = 0;
1430 	ssize_t n;
1431 
1432 	do {
1433 		n = read(fd, buf, (size_t)(len - count));
1434 		if (n == 0)
1435 			return (count);
1436 		if (n < 0)
1437 			return (-1);
1438 		while (--n >= 0) {
1439 			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
1440 				return (count);
1441 			count++;
1442 			buf++;
1443 		}
1444 	} while (count < len);
1445 	return (count);
1446 }
1447 
1448 #define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
1449 
1450 #define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
1451 
1452 static void
1453 tcpmux(int ctrl, struct servtab *sep)
1454 {
1455 	char service[MAX_SERV_LEN+1];
1456 	int len;
1457 
1458 	/* Get requested service name */
1459 	if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) {
1460 		strwrite(ctrl, "-Error reading service name\r\n");
1461 		goto reject;
1462 	}
1463 	service[len] = '\0';
1464 
1465 	DPRINTF("tcpmux: %s: service requested", service);
1466 
1467 	/*
1468 	 * Help is a required command, and lists available services,
1469 	 * one per line.
1470 	 */
1471 	if (strcasecmp(service, "help") == 0) {
1472 		strwrite(ctrl, "+Available services:\r\n");
1473 		strwrite(ctrl, "help\r\n");
1474 		for (sep = servtab; sep != NULL; sep = sep->se_next) {
1475 			if (!ISMUX(sep))
1476 				continue;
1477 			(void)write(ctrl, sep->se_service,
1478 			    strlen(sep->se_service));
1479 			strwrite(ctrl, "\r\n");
1480 		}
1481 		goto reject;
1482 	}
1483 
1484 	/* Try matching a service in inetd.conf with the request */
1485 	for (sep = servtab; sep != NULL; sep = sep->se_next) {
1486 		if (!ISMUX(sep))
1487 			continue;
1488 		if (strcasecmp(service, sep->se_service) == 0) {
1489 			if (ISMUXPLUS(sep))
1490 				strwrite(ctrl, "+Go\r\n");
1491 			run_service(ctrl, sep, true /* forked */);
1492 			return;
1493 		}
1494 	}
1495 	strwrite(ctrl, "-Service not available\r\n");
1496 reject:
1497 	_exit(EXIT_FAILURE);
1498 }
1499 
1500 /*
1501  * check if the address/port where send data to is one of the obvious ports
1502  * that are used for denial of service attacks like two echo ports
1503  * just echoing data between them
1504  */
1505 static int
1506 port_good_dg(struct sockaddr *sa)
1507 {
1508 	struct in_addr in;
1509 	struct sockaddr_in *sin;
1510 #ifdef INET6
1511 	struct in6_addr *in6;
1512 	struct sockaddr_in6 *sin6;
1513 #endif
1514 	u_int16_t port;
1515 	int i;
1516 	char hbuf[NI_MAXHOST];
1517 
1518 	switch (sa->sa_family) {
1519 	case AF_INET:
1520 		sin = (struct sockaddr_in *)(void *)sa;
1521 		in.s_addr = ntohl(sin->sin_addr.s_addr);
1522 		port = ntohs(sin->sin_port);
1523 #ifdef INET6
1524 	v4chk:
1525 #endif
1526 		if (IN_MULTICAST(in.s_addr))
1527 			goto bad;
1528 		switch ((in.s_addr & 0xff000000) >> 24) {
1529 		case 0: case 127: case 255:
1530 			goto bad;
1531 		}
1532 		if (dg_broadcast(&in))
1533 			goto bad;
1534 		break;
1535 #ifdef INET6
1536 	case AF_INET6:
1537 		sin6 = (struct sockaddr_in6 *)(void *)sa;
1538 		in6 = &sin6->sin6_addr;
1539 		port = ntohs(sin6->sin6_port);
1540 		if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
1541 			goto bad;
1542 		if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
1543 			memcpy(&in, &in6->s6_addr[12], sizeof(in));
1544 			in.s_addr = ntohl(in.s_addr);
1545 			goto v4chk;
1546 		}
1547 		break;
1548 #endif
1549 	default:
1550 		/* XXX unsupported af, is it safe to assume it to be safe? */
1551 		return true;
1552 	}
1553 
1554 	for (i = 0; bad_ports[i] != 0; i++) {
1555 		if (port == bad_ports[i])
1556 			goto bad;
1557 	}
1558 
1559 	return true;
1560 
1561 bad:
1562 	if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
1563 	    niflags) != 0)
1564 		strlcpy(hbuf, "?", sizeof(hbuf));
1565 	syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
1566 		hbuf, port);
1567 	return false;
1568 }
1569 
1570 /* XXX need optimization */
1571 static int
1572 dg_broadcast(struct in_addr *in)
1573 {
1574 	struct ifaddrs *ifa, *ifap;
1575 	struct sockaddr_in *sin;
1576 
1577 	if (getifaddrs(&ifap) < 0)
1578 		return false;
1579 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
1580 		if (ifa->ifa_addr->sa_family != AF_INET ||
1581 		    (ifa->ifa_flags & IFF_BROADCAST) == 0)
1582 			continue;
1583 		sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
1584 		if (sin->sin_addr.s_addr == in->s_addr) {
1585 			freeifaddrs(ifap);
1586 			return true;
1587 		}
1588 	}
1589 	freeifaddrs(ifap);
1590 	return false;
1591 }
1592 
1593 static int
1594 my_kevent(const struct kevent *changelist, size_t nchanges,
1595     struct kevent *eventlist, size_t nevents)
1596 {
1597 	int	result;
1598 
1599 	while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
1600 	    NULL)) < 0)
1601 		if (errno != EINTR) {
1602 			syslog(LOG_ERR, "kevent: %m");
1603 			exit(EXIT_FAILURE);
1604 		}
1605 
1606 	return (result);
1607 }
1608 
1609 static struct kevent *
1610 allocchange(void)
1611 {
1612 	if (changes == __arraycount(changebuf)) {
1613 		(void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0);
1614 		changes = 0;
1615 	}
1616 
1617 	return (&changebuf[changes++]);
1618 }
1619 
1620 bool
1621 try_biltin(struct servtab *sep)
1622 {
1623 	for (size_t i = 0; i < __arraycount(biltins); i++) {
1624 		if (biltins[i].bi_socktype == sep->se_socktype &&
1625 		    strcmp(biltins[i].bi_service, sep->se_service) == 0) {
1626 			sep->se_bi = &biltins[i];
1627 			sep->se_wait = biltins[i].bi_wait;
1628 			return true;
1629 		}
1630 	}
1631 	return false;
1632 }
1633