inetd.c revision 1.136
1/*	$NetBSD: inetd.c,v 1.136 2021/09/03 21:02:04 rillig Exp $	*/
2
3/*-
4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Matthias Scheler.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1983, 1991, 1993, 1994
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 *    may be used to endorse or promote products derived from this software
47 *    without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62#include <sys/cdefs.h>
63#ifndef lint
64__COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\
65 The Regents of the University of California.  All rights reserved.");
66#if 0
67static char sccsid[] = "@(#)inetd.c	8.4 (Berkeley) 4/13/94";
68#else
69__RCSID("$NetBSD: inetd.c,v 1.136 2021/09/03 21:02:04 rillig 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
195
196#ifndef NO_RPC
197#define RPC
198#endif
199
200#include <net/if.h>
201
202#ifdef RPC
203#include <rpc/rpc.h>
204#include <rpc/rpcb_clnt.h>
205#include <netconfig.h>
206#endif
207
208#include <ctype.h>
209#include <err.h>
210#include <errno.h>
211#include <fcntl.h>
212#include <glob.h>
213#include <grp.h>
214#include <libgen.h>
215#include <pwd.h>
216#include <signal.h>
217#include <stdio.h>
218#include <stdlib.h>
219#include <string.h>
220#include <syslog.h>
221#include <unistd.h>
222#include <util.h>
223#include <ifaddrs.h>
224
225#include "inetd.h"
226
227#ifdef LIBWRAP
228# include <tcpd.h>
229#ifndef LIBWRAP_ALLOW_FACILITY
230# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
231#endif
232#ifndef LIBWRAP_ALLOW_SEVERITY
233# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
234#endif
235#ifndef LIBWRAP_DENY_FACILITY
236# define LIBWRAP_DENY_FACILITY LOG_AUTH
237#endif
238#ifndef LIBWRAP_DENY_SEVERITY
239# define LIBWRAP_DENY_SEVERITY LOG_WARNING
240#endif
241int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
242int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
243#endif
244
245#define	CNT_INTVL	((time_t)60)	/* servers in CNT_INTVL sec. */
246#define	RETRYTIME	(60*10)		/* retry after bind or server fail */
247
248int	debug;
249#ifdef LIBWRAP
250int	lflag;
251#endif
252int	maxsock;
253int	kq;
254int	options;
255int	timingout;
256const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
257
258#ifndef OPEN_MAX
259#define OPEN_MAX	64
260#endif
261
262/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
263#define FD_MARGIN	(8)
264rlim_t		rlim_ofile_cur = OPEN_MAX;
265
266struct rlimit	rlim_ofile;
267
268struct kevent	changebuf[64];
269size_t		changes;
270
271struct servtab *servtab;
272
273static void	chargen_dg(int, struct servtab *);
274static void	chargen_stream(int, struct servtab *);
275static void	close_sep(struct servtab *);
276static void	config(void);
277static void	daytime_dg(int, struct servtab *);
278static void	daytime_stream(int, struct servtab *);
279static void	discard_dg(int, struct servtab *);
280static void	discard_stream(int, struct servtab *);
281static void	echo_dg(int, struct servtab *);
282static void	echo_stream(int, struct servtab *);
283static void	endconfig(void);
284static struct servtab	*enter(struct servtab *);
285static struct servtab	*getconfigent(char **);
286__dead static void	goaway(void);
287static void	machtime_dg(int, struct servtab *);
288static void	machtime_stream(int, struct servtab *);
289#ifdef DEBUG_ENABLE
290static void	print_service(const char *, struct servtab *);
291#endif
292static void	reapchild(void);
293static void	retry(void);
294static void	run_service(int, struct servtab *, int);
295static void	setup(struct servtab *);
296static char	*skip(char **);
297static void	tcpmux(int, struct servtab *);
298__dead static void	usage(void);
299static void	register_rpc(struct servtab *);
300static void	unregister_rpc(struct servtab *);
301static void	bump_nofile(void);
302static void	inetd_setproctitle(char *, int);
303static void	initring(void);
304static uint32_t	machtime(void);
305static int	port_good_dg(struct sockaddr *);
306static int	dg_broadcast(struct in_addr *);
307static int	my_kevent(const struct kevent *, size_t, struct kevent *, size_t);
308static struct kevent	*allocchange(void);
309static int	get_line(int, char *, int);
310static void	spawn(struct servtab *, int);
311static struct servtab	init_servtab(void);
312static int	rl_process(struct servtab *, int);
313static struct se_ip_list_node	*rl_add(struct servtab *, char *);
314static void	rl_reset(struct servtab *, time_t);
315static struct se_ip_list_node	*rl_try_get_ip(struct servtab *, char *);
316static void	include_configs(char *);
317static int	glob_error(const char *, int);
318static void	read_glob_configs(char *);
319static void	prepare_next_config(const char*);
320static bool	is_same_service(const struct servtab *, const struct servtab *);
321static char	*gen_file_pattern(const char *, const char *);
322static bool	check_no_reinclude(const char *);
323static void	include_matched_path(char *);
324static void	purge_unchecked(void);
325static void	config_root(void);
326static void	clear_ip_list(struct servtab *);
327static time_t	rl_time(void);
328static void	rl_get_name(struct servtab *, int, char *);
329static void	rl_drop_connection(struct servtab *, int);
330
331struct biltin {
332	const char *bi_service;		/* internally provided service name */
333	int	bi_socktype;		/* type of socket supported */
334	short	bi_fork;		/* 1 if should fork before call */
335	short	bi_wait;		/* 1 if should wait for child */
336	void	(*bi_fn)(int, struct servtab *);
337					/* function which performs it */
338} biltins[] = {
339	/* Echo received data */
340	{ "echo",	SOCK_STREAM,	true, false,	echo_stream },
341	{ "echo",	SOCK_DGRAM,	false, false,	echo_dg },
342
343	/* Internet /dev/null */
344	{ "discard",	SOCK_STREAM,	true, false,	discard_stream },
345	{ "discard",	SOCK_DGRAM,	false, false,	discard_dg },
346
347	/* Return 32 bit time since 1970 */
348	{ "time",	SOCK_STREAM,	false, false,	machtime_stream },
349	{ "time",	SOCK_DGRAM,	false, false,	machtime_dg },
350
351	/* Return human-readable time */
352	{ "daytime",	SOCK_STREAM,	false, false,	daytime_stream },
353	{ "daytime",	SOCK_DGRAM,	false, false,	daytime_dg },
354
355	/* Familiar character generator */
356	{ "chargen",	SOCK_STREAM,	true, false,	chargen_stream },
357	{ "chargen",	SOCK_DGRAM,	false, false,	chargen_dg },
358
359	{ "tcpmux",	SOCK_STREAM,	true, false,	tcpmux },
360
361	{ NULL, 0, false, false, NULL }
362};
363
364/* list of "bad" ports. I.e. ports that are most obviously used for
365 * "cycling packets" denial of service attacks. See /etc/services.
366 * List must end with port number "0".
367 */
368
369u_int16_t bad_ports[] =  { 7, 9, 13, 19, 37, 0 };
370
371
372#define NUMINT	(sizeof(intab) / sizeof(struct inent))
373const char	*CONFIG = _PATH_INETDCONF;
374
375static int my_signals[] =
376    { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE };
377
378int
379main(int argc, char *argv[])
380{
381	int		ch, n, reload = 1;
382
383	while ((ch = getopt(argc, argv,
384#ifdef LIBWRAP
385					"dl"
386#else
387					"d"
388#endif
389					   )) != -1)
390		switch(ch) {
391		case 'd':
392			debug = true;
393			options |= SO_DEBUG;
394			break;
395#ifdef LIBWRAP
396		case 'l':
397			lflag = true;
398			break;
399#endif
400		case '?':
401		default:
402			usage();
403		}
404	argc -= optind;
405	argv += optind;
406
407	if (argc > 0)
408		CONFIG = argv[0];
409
410	if (!debug)
411		daemon(0, 0);
412	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
413	pidfile(NULL);
414
415	kq = kqueue();
416	if (kq < 0) {
417		syslog(LOG_ERR, "kqueue: %m");
418		return (EXIT_FAILURE);
419	}
420
421	if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
422		syslog(LOG_ERR, "getrlimit: %m");
423	} else {
424		rlim_ofile_cur = rlim_ofile.rlim_cur;
425		if (rlim_ofile_cur == RLIM_INFINITY)	/* ! */
426			rlim_ofile_cur = OPEN_MAX;
427	}
428
429	for (n = 0; n < (int)__arraycount(my_signals); n++) {
430		int	signum;
431
432		signum = my_signals[n];
433		if (signum != SIGCHLD)
434			(void) signal(signum, SIG_IGN);
435
436		if (signum != SIGPIPE) {
437			struct kevent	*ev;
438
439			ev = allocchange();
440			EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE,
441			    0, 0, 0);
442		}
443	}
444
445	for (;;) {
446		int		ctrl;
447		struct kevent	eventbuf[64], *ev;
448		struct servtab	*sep;
449
450		if (reload) {
451			reload = false;
452			config_root();
453		}
454
455		n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf));
456		changes = 0;
457
458		for (ev = eventbuf; n > 0; ev++, n--) {
459			if (ev->filter == EVFILT_SIGNAL) {
460				switch (ev->ident) {
461				case SIGALRM:
462					retry();
463					break;
464				case SIGCHLD:
465					reapchild();
466					break;
467				case SIGTERM:
468				case SIGINT:
469					goaway();
470					break;
471				case SIGHUP:
472					reload = true;
473					break;
474				}
475				continue;
476			}
477			if (ev->filter != EVFILT_READ)
478				continue;
479			sep = (struct servtab *)ev->udata;
480			/* Paranoia */
481			if ((int)ev->ident != sep->se_fd)
482				continue;
483			DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep));
484			if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
485				/* XXX here do the libwrap check-before-accept*/
486				ctrl = accept(sep->se_fd, NULL, NULL);
487				DPRINTF(SERV_FMT ": accept, ctrl fd %d",
488				    SERV_PARAMS(sep), ctrl);
489				if (ctrl < 0) {
490					if (errno != EINTR)
491						syslog(LOG_WARNING,
492						    SERV_FMT ": accept: %m",
493						    SERV_PARAMS(sep));
494					continue;
495				}
496			} else
497				ctrl = sep->se_fd;
498			spawn(sep, ctrl);
499		}
500	}
501}
502
503static void
504spawn(struct servtab *sep, int ctrl)
505{
506	int dofork;
507	pid_t pid;
508
509	pid = 0;
510#ifdef LIBWRAP_INTERNAL
511	dofork = true;
512#else
513	dofork = (sep->se_bi == NULL || sep->se_bi->bi_fork);
514#endif
515	if (dofork) {
516		if (rl_process(sep, ctrl)) {
517			return;
518		}
519		pid = fork();
520		if (pid < 0) {
521			syslog(LOG_ERR, "fork: %m");
522			if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM)
523				close(ctrl);
524			sleep(1);
525			return;
526		}
527		if (pid != 0 && sep->se_wait != 0) {
528			struct kevent	*ev;
529
530			sep->se_wait = pid;
531			ev = allocchange();
532			EV_SET(ev, sep->se_fd, EVFILT_READ,
533			    EV_DELETE, 0, 0, 0);
534		}
535		if (pid == 0) {
536			size_t	n;
537
538			for (n = 0; n < __arraycount(my_signals); n++)
539				(void) signal(my_signals[n], SIG_DFL);
540			if (debug)
541				setsid();
542		}
543	}
544	if (pid == 0) {
545		run_service(ctrl, sep, dofork);
546		if (dofork)
547			exit(0);
548	}
549	if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM)
550		close(ctrl);
551}
552
553static void
554run_service(int ctrl, struct servtab *sep, int didfork)
555{
556	struct passwd *pwd;
557	struct group *grp = NULL;	/* XXX gcc */
558	char buf[NI_MAXSERV];
559	struct servtab *s;
560#ifdef LIBWRAP
561	char abuf[BUFSIZ];
562	struct request_info req;
563	int denied;
564	char *service = NULL;	/* XXX gcc */
565#endif
566
567#ifdef LIBWRAP
568#ifndef LIBWRAP_INTERNAL
569	if (sep->se_bi == 0)
570#endif
571	if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
572		request_init(&req, RQ_DAEMON, sep->se_argv[0] != NULL ?
573		    sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
574		fromhost(&req);
575		denied = hosts_access(&req) == 0;
576		if (denied || lflag) {
577			if (getnameinfo(&sep->se_ctrladdr,
578			    (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0,
579			    buf, sizeof(buf), 0) != 0) {
580				/* shouldn't happen */
581				(void)snprintf(buf, sizeof buf, "%d",
582				    ntohs(sep->se_ctrladdr_in.sin_port));
583			}
584			service = buf;
585			if (req.client->sin != NULL) {
586				sockaddr_snprintf(abuf, sizeof(abuf), "%a",
587				    req.client->sin);
588			} else {
589				strcpy(abuf, "(null)");
590			}
591		}
592		if (denied) {
593			syslog(deny_severity,
594			    "refused connection from %.500s(%s), service %s (%s)",
595			    eval_client(&req), abuf, service, sep->se_proto);
596			goto reject;
597		}
598		if (lflag) {
599			syslog(allow_severity,
600			    "connection from %.500s(%s), service %s (%s)",
601			    eval_client(&req), abuf, service, sep->se_proto);
602		}
603	}
604#endif /* LIBWRAP */
605
606	if (sep->se_bi != NULL) {
607		if (didfork) {
608			for (s = servtab; s != NULL; s = s->se_next)
609				if (s->se_fd != -1 && s->se_fd != ctrl) {
610					close(s->se_fd);
611					s->se_fd = -1;
612				}
613		}
614		(*sep->se_bi->bi_fn)(ctrl, sep);
615	} else {
616		if ((pwd = getpwnam(sep->se_user)) == NULL) {
617			syslog(LOG_ERR, "%s/%s: %s: No such user",
618			    sep->se_service, sep->se_proto, sep->se_user);
619			goto reject;
620		}
621		if (sep->se_group != NULL &&
622		    (grp = getgrnam(sep->se_group)) == NULL) {
623			syslog(LOG_ERR, "%s/%s: %s: No such group",
624			    sep->se_service, sep->se_proto, sep->se_group);
625			goto reject;
626		}
627		if (pwd->pw_uid != 0) {
628			if (sep->se_group != NULL)
629				pwd->pw_gid = grp->gr_gid;
630			if (setgid(pwd->pw_gid) < 0) {
631				syslog(LOG_ERR,
632				 "%s/%s: can't set gid %d: %m", sep->se_service,
633				    sep->se_proto, pwd->pw_gid);
634				goto reject;
635			}
636			(void) initgroups(pwd->pw_name,
637			    pwd->pw_gid);
638			if (setuid(pwd->pw_uid) < 0) {
639				syslog(LOG_ERR,
640				 "%s/%s: can't set uid %d: %m", sep->se_service,
641				    sep->se_proto, pwd->pw_uid);
642				goto reject;
643			}
644		} else if (sep->se_group != NULL) {
645			(void) setgid((gid_t)grp->gr_gid);
646		}
647		DPRINTF("%d execl %s",
648		    getpid(), sep->se_server);
649		/* Set our control descriptor to not close-on-exec... */
650		if (fcntl(ctrl, F_SETFD, 0) < 0)
651			syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl);
652		/* ...and dup it to stdin, stdout, and stderr. */
653		if (ctrl != 0) {
654			dup2(ctrl, 0);
655			close(ctrl);
656			ctrl = 0;
657		}
658		dup2(0, 1);
659		dup2(0, 2);
660		if (rlim_ofile.rlim_cur != rlim_ofile_cur &&
661		    setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
662			syslog(LOG_ERR, "setrlimit: %m");
663		execv(sep->se_server, sep->se_argv);
664		syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server);
665	reject:
666		if (sep->se_socktype != SOCK_STREAM)
667			recv(ctrl, buf, sizeof (buf), 0);
668		_exit(EXIT_FAILURE);
669	}
670}
671
672static void
673reapchild(void)
674{
675	int status;
676	pid_t pid;
677	struct servtab *sep;
678
679	for (;;) {
680		pid = wait3(&status, WNOHANG, NULL);
681		if (pid <= 0)
682			break;
683		DPRINTF("%d reaped, status %#x", pid, status);
684		for (sep = servtab; sep != NULL; sep = sep->se_next)
685			if (sep->se_wait == pid) {
686				struct kevent	*ev;
687
688				if (WIFEXITED(status) && WEXITSTATUS(status))
689					syslog(LOG_WARNING,
690					    "%s: exit status %u",
691					    sep->se_server, WEXITSTATUS(status));
692				else if (WIFSIGNALED(status))
693					syslog(LOG_WARNING,
694					    "%s: exit signal %u",
695					    sep->se_server, WTERMSIG(status));
696				sep->se_wait = 1;
697				ev = allocchange();
698				EV_SET(ev, sep->se_fd, EVFILT_READ,
699				    EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep);
700				DPRINTF("restored %s, fd %d",
701				    sep->se_service, sep->se_fd);
702			}
703	}
704}
705
706size_t	line_number;
707
708/*
709 * Recursively merge loaded service definitions with any defined
710 * in the current or included config files.
711 */
712static void
713config(void)
714{
715	struct servtab *sep, *cp;
716	/*
717	 * Current position in line, used with key-values notation,
718	 * saves cp across getconfigent calls.
719	 */
720	char *current_pos;
721	size_t n;
722
723	/* open config file from beginning */
724	fconfig = fopen(CONFIG, "r");
725	if(fconfig == NULL) {
726		syslog(LOG_ERR, "%s: %m", CONFIG);
727		return;
728	}
729
730	/* First call to nextline will advance line_number to 1 */
731	line_number = 0;
732
733	/* Start parsing at the beginning of the first line */
734	current_pos = nextline(fconfig);
735
736	while ((cp = getconfigent(&current_pos)) != NULL) {
737		/* Find an already existing service definition */
738		for (sep = servtab; sep != NULL; sep = sep->se_next)
739			if (is_same_service(sep, cp))
740				break;
741		if (sep != NULL) {
742			int i;
743
744#define SWAP(type, a, b) {type c = a; a = b; b = c;}
745
746			/*
747			 * sep->se_wait may be holding the pid of a daemon
748			 * that we're waiting for.  If so, don't overwrite
749			 * it unless the config file explicitly says don't
750			 * wait.
751			 */
752			if (cp->se_bi == 0 &&
753			    (sep->se_wait == 1 || cp->se_wait == 0))
754				sep->se_wait = cp->se_wait;
755			SWAP(char *, sep->se_user, cp->se_user);
756			SWAP(char *, sep->se_group, cp->se_group);
757			SWAP(char *, sep->se_server, cp->se_server);
758			for (i = 0; i < MAXARGV; i++)
759				SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
760#ifdef IPSEC
761			SWAP(char *, sep->se_policy, cp->se_policy);
762#endif
763			SWAP(service_type, cp->se_type, sep->se_type);
764			SWAP(size_t, cp->se_service_max, sep->se_service_max);
765			SWAP(size_t, cp->se_ip_max, sep->se_ip_max);
766#undef SWAP
767			if (isrpcservice(sep))
768				unregister_rpc(sep);
769			sep->se_rpcversl = cp->se_rpcversl;
770			sep->se_rpcversh = cp->se_rpcversh;
771			freeconfig(cp);
772#ifdef DEBUG_ENABLE
773			if (debug)
774				print_service("REDO", sep);
775#endif
776		} else {
777			sep = enter(cp);
778#ifdef DEBUG_ENABLE
779			if (debug)
780				print_service("ADD ", sep);
781#endif
782		}
783		sep->se_checked = 1;
784
785		/*
786		 * Remainder of config(void) checks validity of servtab options
787		 * and sets up the service by setting up sockets (in setup(servtab)).
788		 */
789		switch (sep->se_family) {
790		case AF_LOCAL:
791			if (sep->se_fd != -1)
792				break;
793			n = strlen(sep->se_service);
794			if (n >= sizeof(sep->se_ctrladdr_un.sun_path)) {
795				syslog(LOG_ERR, "%s/%s: address too long",
796				    sep->se_service, sep->se_proto);
797				sep->se_checked = 0;
798				continue;
799			}
800			(void)unlink(sep->se_service);
801			strlcpy(sep->se_ctrladdr_un.sun_path,
802			    sep->se_service, n + 1);
803			sep->se_ctrladdr_un.sun_family = AF_LOCAL;
804			sep->se_ctrladdr_size = (socklen_t)(n +
805			    sizeof(sep->se_ctrladdr_un) -
806			    sizeof(sep->se_ctrladdr_un.sun_path));
807			if (!ISMUX(sep))
808				setup(sep);
809			break;
810		case AF_INET:
811#ifdef INET6
812		case AF_INET6:
813#endif
814		    {
815			struct addrinfo hints, *res;
816			char *host;
817			const char *port;
818			int error;
819			int s;
820
821			/* check if the family is supported */
822			s = socket(sep->se_family, SOCK_DGRAM, 0);
823			if (s < 0) {
824				syslog(LOG_WARNING,
825				    "%s/%s: %s: the address family is not "
826				    "supported by the kernel",
827				    sep->se_service, sep->se_proto,
828				    sep->se_hostaddr);
829				sep->se_checked = false;
830				continue;
831			}
832			close(s);
833
834			memset(&hints, 0, sizeof(hints));
835			hints.ai_family = sep->se_family;
836			hints.ai_socktype = sep->se_socktype;
837			hints.ai_flags = AI_PASSIVE;
838			if (strcmp(sep->se_hostaddr, "*") == 0)
839				host = NULL;
840			else
841				host = sep->se_hostaddr;
842			if (isrpcservice(sep) || ISMUX(sep))
843				port = "0";
844			else
845				port = sep->se_service;
846			error = getaddrinfo(host, port, &hints, &res);
847			if (error != 0) {
848				if (error == EAI_SERVICE) {
849					/* gai_strerror not friendly enough */
850					syslog(LOG_WARNING, SERV_FMT ": "
851					    "unknown service",
852					    SERV_PARAMS(sep));
853				} else {
854					syslog(LOG_ERR, SERV_FMT ": %s: %s",
855					    SERV_PARAMS(sep),
856					    sep->se_hostaddr,
857					    gai_strerror(error));
858				}
859				sep->se_checked = false;
860				continue;
861			}
862			if (res->ai_next != NULL) {
863				syslog(LOG_ERR,
864					SERV_FMT ": %s: resolved to multiple addr",
865				    SERV_PARAMS(sep),
866				    sep->se_hostaddr);
867				sep->se_checked = false;
868				freeaddrinfo(res);
869				continue;
870			}
871			memcpy(&sep->se_ctrladdr, res->ai_addr,
872				res->ai_addrlen);
873			if (ISMUX(sep)) {
874				sep->se_fd = -1;
875				freeaddrinfo(res);
876				continue;
877			}
878			sep->se_ctrladdr_size = res->ai_addrlen;
879			freeaddrinfo(res);
880#ifdef RPC
881			if (isrpcservice(sep)) {
882				struct rpcent *rp;
883
884				sep->se_rpcprog = atoi(sep->se_service);
885				if (sep->se_rpcprog == 0) {
886					rp = getrpcbyname(sep->se_service);
887					if (rp == 0) {
888						syslog(LOG_ERR,
889						    SERV_FMT
890						    ": unknown service",
891						    SERV_PARAMS(sep));
892						sep->se_checked = false;
893						continue;
894					}
895					sep->se_rpcprog = rp->r_number;
896				}
897				if (sep->se_fd == -1 && !ISMUX(sep))
898					setup(sep);
899				if (sep->se_fd != -1)
900					register_rpc(sep);
901			} else
902#endif
903			{
904				if (sep->se_fd >= 0)
905					close_sep(sep);
906				if (sep->se_fd == -1 && !ISMUX(sep))
907					setup(sep);
908			}
909		    }
910		}
911	}
912	endconfig();
913}
914
915static void
916retry(void)
917{
918	struct servtab *sep;
919
920	timingout = false;
921	for (sep = servtab; sep != NULL; sep = sep->se_next) {
922		if (sep->se_fd == -1 && !ISMUX(sep)) {
923			switch (sep->se_family) {
924			case AF_LOCAL:
925			case AF_INET:
926#ifdef INET6
927			case AF_INET6:
928#endif
929				setup(sep);
930				if (sep->se_fd >= 0 && isrpcservice(sep))
931					register_rpc(sep);
932				break;
933			}
934		}
935	}
936}
937
938static void
939goaway(void)
940{
941	struct servtab *sep;
942
943	for (sep = servtab; sep != NULL; sep = sep->se_next) {
944		if (sep->se_fd == -1)
945			continue;
946
947		switch (sep->se_family) {
948		case AF_LOCAL:
949			(void)unlink(sep->se_service);
950			break;
951		case AF_INET:
952#ifdef INET6
953		case AF_INET6:
954#endif
955			if (sep->se_wait == 1 && isrpcservice(sep))
956				unregister_rpc(sep);
957			break;
958		}
959		(void)close(sep->se_fd);
960		sep->se_fd = -1;
961	}
962	exit(0);
963}
964
965static void
966setup(struct servtab *sep)
967{
968	int		on = 1;
969#ifdef INET6
970	int		off = 0;
971#endif
972	struct kevent	*ev;
973
974	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
975		DPRINTF("socket failed on " SERV_FMT ": %s",
976		    SERV_PARAMS(sep), strerror(errno));
977		syslog(LOG_ERR, "%s/%s: socket: %m",
978		    sep->se_service, sep->se_proto);
979		return;
980	}
981	/* Set all listening sockets to close-on-exec. */
982	if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
983		syslog(LOG_ERR, SERV_FMT ": fcntl(F_SETFD, FD_CLOEXEC): %m",
984		    SERV_PARAMS(sep));
985		close(sep->se_fd);
986		sep->se_fd = -1;
987		return;
988	}
989
990#define	turnon(fd, opt) \
991setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on))
992	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
993	    turnon(sep->se_fd, SO_DEBUG) < 0)
994		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
995	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
996		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
997#undef turnon
998
999	/* Set the socket buffer sizes, if specified. */
1000	if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1001	    SO_SNDBUF, &sep->se_sndbuf, (socklen_t)sizeof(sep->se_sndbuf)) < 0)
1002		syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m",
1003		    sep->se_sndbuf);
1004	if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1005	    SO_RCVBUF, &sep->se_rcvbuf, (socklen_t)sizeof(sep->se_rcvbuf)) < 0)
1006		syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m",
1007		    sep->se_rcvbuf);
1008#ifdef INET6
1009	if (sep->se_family == AF_INET6) {
1010		int *v;
1011		v = (sep->se_type == FAITH_TYPE) ? &on : &off;
1012		if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH,
1013		    v, (socklen_t)sizeof(*v)) < 0)
1014			syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1015	}
1016#endif
1017#ifdef IPSEC
1018	/* Avoid setting a policy if a policy specifier doesn't exist. */
1019	if (sep->se_policy != NULL) {
1020		int e = ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy);
1021		if (e < 0) {
1022			syslog(LOG_ERR, SERV_FMT ": ipsec setup failed",
1023			    SERV_PARAMS(sep));
1024			(void)close(sep->se_fd);
1025			sep->se_fd = -1;
1026			return;
1027		}
1028	}
1029#endif
1030
1031	if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
1032		DPRINTF(SERV_FMT ": bind failed: %s",
1033			SERV_PARAMS(sep), strerror(errno));
1034		syslog(LOG_ERR, SERV_FMT ": bind: %m",
1035		    SERV_PARAMS(sep));
1036		(void) close(sep->se_fd);
1037		sep->se_fd = -1;
1038		if (!timingout) {
1039			timingout = true;
1040			alarm(RETRYTIME);
1041		}
1042		return;
1043	}
1044	if (sep->se_socktype == SOCK_STREAM)
1045		listen(sep->se_fd, 10);
1046
1047	/* Set the accept filter, if specified. To be done after listen.*/
1048	if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1049	    SO_ACCEPTFILTER, &sep->se_accf,
1050	    (socklen_t)sizeof(sep->se_accf)) < 0)
1051		syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m",
1052		    sep->se_accf.af_name);
1053
1054	ev = allocchange();
1055	EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
1056	    (intptr_t)sep);
1057	if (sep->se_fd > maxsock) {
1058		maxsock = sep->se_fd;
1059		if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
1060			bump_nofile();
1061	}
1062	DPRINTF(SERV_FMT ": registered on fd %d", SERV_PARAMS(sep), sep->se_fd);
1063}
1064
1065/*
1066 * Finish with a service and its socket.
1067 */
1068static void
1069close_sep(struct servtab *sep)
1070{
1071
1072	if (sep->se_fd >= 0) {
1073		(void) close(sep->se_fd);
1074		sep->se_fd = -1;
1075	}
1076	sep->se_count = 0;
1077	if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
1078		clear_ip_list(sep);
1079	}
1080}
1081
1082static void
1083register_rpc(struct servtab *sep)
1084{
1085#ifdef RPC
1086	struct netbuf nbuf;
1087	struct sockaddr_storage ss;
1088	struct netconfig *nconf;
1089	socklen_t socklen;
1090	int n;
1091
1092	if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1093		syslog(LOG_ERR, "%s: getnetconfigent failed",
1094		    sep->se_proto);
1095		return;
1096	}
1097	socklen = sizeof ss;
1098	if (getsockname(sep->se_fd, (struct sockaddr *)(void *)&ss, &socklen) < 0) {
1099		syslog(LOG_ERR, SERV_FMT ": getsockname: %m",
1100		    SERV_PARAMS(sep));
1101		return;
1102	}
1103
1104	nbuf.buf = &ss;
1105	nbuf.len = ss.ss_len;
1106	nbuf.maxlen = sizeof (struct sockaddr_storage);
1107	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1108		DPRINTF("rpcb_set: %u %d %s %s",
1109		    sep->se_rpcprog, n, nconf->nc_netid,
1110		    taddr2uaddr(nconf, &nbuf));
1111		(void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf);
1112		if (rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf) == 0)
1113			syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s",
1114			    sep->se_rpcprog, n, nconf->nc_netid,
1115			    taddr2uaddr(nconf, &nbuf), clnt_spcreateerror(""));
1116	}
1117#endif /* RPC */
1118}
1119
1120static void
1121unregister_rpc(struct servtab *sep)
1122{
1123#ifdef RPC
1124	int n;
1125	struct netconfig *nconf;
1126
1127	if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1128		syslog(LOG_ERR, "%s: getnetconfigent failed",
1129		    sep->se_proto);
1130		return;
1131	}
1132
1133	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1134		DPRINTF("rpcb_unset(%u, %d, %s)",
1135		    sep->se_rpcprog, n, nconf->nc_netid);
1136		if (rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf) == 0)
1137			syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n",
1138			    sep->se_rpcprog, n, nconf->nc_netid);
1139	}
1140#endif /* RPC */
1141}
1142
1143
1144static struct servtab *
1145enter(struct servtab *cp)
1146{
1147	struct servtab *sep;
1148
1149	sep = malloc(sizeof (*sep));
1150	if (sep == NULL) {
1151		syslog(LOG_ERR, "Out of memory.");
1152		exit(EXIT_FAILURE);
1153	}
1154	*sep = *cp;
1155	sep->se_fd = -1;
1156	sep->se_rpcprog = -1;
1157	sep->se_next = servtab;
1158	servtab = sep;
1159	return (sep);
1160}
1161
1162FILE	*fconfig;
1163/* Temporary storage for new servtab */
1164static struct	servtab serv;
1165/* Current line from current config file */
1166static char	line[LINE_MAX];
1167char    *defhost;
1168#ifdef IPSEC
1169char *policy;
1170#endif
1171
1172static void
1173endconfig(void)
1174{
1175	if (fconfig != NULL) {
1176		(void) fclose(fconfig);
1177		fconfig = NULL;
1178	}
1179	if (defhost != NULL) {
1180		free(defhost);
1181		defhost = NULL;
1182	}
1183
1184#ifdef IPSEC
1185	if (policy != NULL) {
1186		free(policy);
1187		policy = NULL;
1188	}
1189#endif
1190
1191}
1192
1193#define LOG_EARLY_ENDCONF() \
1194	ERR("Exiting %s early. Some services will be unavailable", CONFIG)
1195
1196#define LOG_TOO_FEW_ARGS() \
1197	ERR("Expected more arguments")
1198
1199/* Parse the next service and apply any directives, and returns it as servtab */
1200static struct servtab *
1201getconfigent(char **current_pos)
1202{
1203	struct servtab *sep = &serv;
1204	int argc, val;
1205	char *cp, *cp0, *arg, *buf0, *buf1, *sz0, *sz1;
1206	static char TCPMUX_TOKEN[] = "tcpmux/";
1207#define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1208	char *hostdelim;
1209
1210	/*
1211	 * Pre-condition: current_pos points into line,
1212	 * line contains config line. Continue where the last getconfigent left off.
1213	 * Allows for multiple service definitions per line.
1214	 */
1215	cp = *current_pos;
1216
1217	if (false) {
1218		/*
1219		 * Go to the next line, but only after attemting to read the current
1220		 * one! Keep reading until we find a valid definition or EOF.
1221		 */
1222more:
1223		cp = nextline(fconfig);
1224	}
1225
1226	if (cp == NULL) {
1227		/* EOF or I/O error, let config() know to exit the file */
1228		return NULL;
1229	}
1230
1231	/* Comments and IPsec policies */
1232	if (cp[0] == '#') {
1233#ifdef IPSEC
1234		/* lines starting with #@ is not a comment, but the policy */
1235		if (cp[1] == '@') {
1236			char *p;
1237			for (p = cp + 2; isspace((unsigned char)*p); p++)
1238				;
1239			if (*p == '\0') {
1240				if (policy)
1241					free(policy);
1242				policy = NULL;
1243			} else {
1244				if (ipsecsetup_test(p) < 0) {
1245					ERR("Invalid IPsec policy \"%s\"", p);
1246					LOG_EARLY_ENDCONF();
1247					/*
1248					* Stop reading the current config to prevent services
1249					* from being run without IPsec.
1250					*/
1251					return NULL;
1252				} else {
1253					if (policy)
1254						free(policy);
1255					policy = newstr(p);
1256				}
1257			}
1258		}
1259#endif
1260
1261		goto more;
1262	}
1263
1264	/* Parse next token: listen-addr/hostname, service-spec, .include */
1265	arg = skip(&cp);
1266
1267	if (cp == NULL) {
1268		goto more;
1269	}
1270
1271	if(arg[0] == '.') {
1272		if (strcmp(&arg[1], "include") == 0) {
1273			/* include directive */
1274			arg = skip(&cp);
1275			if(arg == NULL) {
1276				LOG_TOO_FEW_ARGS();
1277				return NULL;
1278			}
1279			include_configs(arg);
1280			goto more;
1281		} else {
1282			ERR("Unknown directive '%s'", &arg[1]);
1283			goto more;
1284		}
1285	}
1286
1287	/* After this point, we might need to store data in a servtab */
1288	*sep = init_servtab();
1289
1290	/* Check for a host name. */
1291	hostdelim = strrchr(arg, ':');
1292	if (hostdelim != NULL) {
1293		*hostdelim = '\0';
1294		if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1295			hostdelim[-1] = '\0';
1296			sep->se_hostaddr = newstr(arg + 1);
1297		} else
1298			sep->se_hostaddr = newstr(arg);
1299		arg = hostdelim + 1;
1300		/*
1301		 * If the line is of the form `host:', then just change the
1302		 * default host for the following lines.
1303		 */
1304		if (*arg == '\0') {
1305			arg = skip(&cp);
1306			if (cp == NULL) {
1307				free(defhost);
1308				defhost = sep->se_hostaddr;
1309				goto more;
1310			}
1311		}
1312	} else {
1313		/* No host address found, set it to NULL to indicate absence */
1314		sep->se_hostaddr = NULL;
1315	}
1316	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1317		char *c = arg + MUX_LEN;
1318		if (*c == '+') {
1319			sep->se_type = MUXPLUS_TYPE;
1320			c++;
1321		} else
1322			sep->se_type = MUX_TYPE;
1323		sep->se_service = newstr(c);
1324	} else {
1325		sep->se_service = newstr(arg);
1326		sep->se_type = NORM_TYPE;
1327	}
1328
1329	DPRINTCONF("Found service definition '%s'", sep->se_service);
1330
1331	/* on/off/socktype */
1332	arg = skip(&cp);
1333	if (arg == NULL) {
1334		LOG_TOO_FEW_ARGS();
1335		freeconfig(sep);
1336		goto more;
1337	}
1338
1339	/* Check for new v2 syntax */
1340	if (strcmp(arg, "on") == 0 || strncmp(arg, "on#", 3) == 0) {
1341
1342		if (arg[2] == '#') {
1343			cp = nextline(fconfig);
1344		}
1345
1346		switch(parse_syntax_v2(sep, &cp)) {
1347		case V2_SUCCESS:
1348			*current_pos = cp;
1349			return sep;
1350		case V2_SKIP:
1351			/* Skip invalid definitions, freeconfig is called in parse_v2.c */
1352			*current_pos = cp;
1353			freeconfig(sep);
1354			goto more;
1355		case V2_ERROR:
1356			/*
1357			 * Unrecoverable error, stop reading. freeconfig is called
1358			 * in parse_v2.c
1359			 */
1360			LOG_EARLY_ENDCONF();
1361			freeconfig(sep);
1362			return NULL;
1363		}
1364	} else if (strcmp(arg, "off") == 0 || strncmp(arg, "off#", 4) == 0) {
1365
1366		if (arg[3] == '#') {
1367			cp = nextline(fconfig);
1368		}
1369
1370		/* Parse syntax the same as with 'on', but ignore the result */
1371		switch(parse_syntax_v2(sep, &cp)) {
1372		case V2_SUCCESS:
1373		case V2_SKIP:
1374			*current_pos = cp;
1375			freeconfig(sep);
1376			goto more;
1377		case V2_ERROR:
1378			/* Unrecoverable error, stop reading */
1379			LOG_EARLY_ENDCONF();
1380			freeconfig(sep);
1381			return NULL;
1382		}
1383	} else {
1384		/* continue parsing v1 */
1385		parse_socktype(arg, sep);
1386		if (sep->se_socktype == SOCK_STREAM) {
1387			parse_accept_filter(arg, sep);
1388		}
1389		if (sep->se_hostaddr == NULL) {
1390			/* Set host to current default */
1391			sep->se_hostaddr = newstr(defhost);
1392		}
1393	}
1394
1395	/* protocol */
1396	arg = skip(&cp);
1397	if (arg == NULL) {
1398		LOG_TOO_FEW_ARGS();
1399		freeconfig(sep);
1400		goto more;
1401	}
1402	if (sep->se_type == NORM_TYPE &&
1403	    strncmp(arg, "faith/", strlen("faith/")) == 0) {
1404		arg += strlen("faith/");
1405		sep->se_type = FAITH_TYPE;
1406	}
1407	sep->se_proto = newstr(arg);
1408
1409#define	MALFORMED(arg) \
1410do { \
1411	ERR("%s: malformed buffer size option `%s'", \
1412	    sep->se_service, (arg)); \
1413	freeconfig(sep); \
1414	goto more; \
1415} while (false)
1416
1417#define	GETVAL(arg) \
1418do { \
1419	if (!isdigit((unsigned char)*(arg))) \
1420		MALFORMED(arg); \
1421	val = (int)strtol((arg), &cp0, 10); \
1422	if (cp0 != NULL) { \
1423		if (cp0[1] != '\0') \
1424			MALFORMED((arg)); \
1425		if (cp0[0] == 'k') \
1426			val *= 1024; \
1427		if (cp0[0] == 'm') \
1428			val *= 1024 * 1024; \
1429	} \
1430	if (val < 1) { \
1431		ERR("%s: invalid buffer size `%s'", \
1432		    sep->se_service, (arg)); \
1433		freeconfig(sep); \
1434		goto more; \
1435	} \
1436} while (false)
1437
1438#define	ASSIGN(arg) \
1439do { \
1440	if (strcmp((arg), "sndbuf") == 0) \
1441		sep->se_sndbuf = val; \
1442	else if (strcmp((arg), "rcvbuf") == 0) \
1443		sep->se_rcvbuf = val; \
1444	else \
1445		MALFORMED((arg)); \
1446} while (false)
1447
1448	/*
1449	 * Extract the send and receive buffer sizes before parsing
1450	 * the protocol.
1451	 */
1452	sep->se_sndbuf = sep->se_rcvbuf = 0;
1453	buf0 = buf1 = sz0 = sz1 = NULL;
1454	if ((buf0 = strchr(sep->se_proto, ',')) != NULL) {
1455		/* Not meaningful for Tcpmux services. */
1456		if (ISMUX(sep)) {
1457			ERR("%s: can't specify buffer sizes for "
1458			    "tcpmux services", sep->se_service);
1459			goto more;
1460		}
1461
1462		/* Skip the , */
1463		*buf0++ = '\0';
1464
1465		/* Check to see if another socket buffer size was specified. */
1466		if ((buf1 = strchr(buf0, ',')) != NULL) {
1467			/* Skip the , */
1468			*buf1++ = '\0';
1469
1470			/* Make sure a 3rd one wasn't specified. */
1471			if (strchr(buf1, ',') != NULL) {
1472				ERR("%s: too many buffer sizes", sep->se_service);
1473				goto more;
1474			}
1475
1476			/* Locate the size. */
1477			if ((sz1 = strchr(buf1, '=')) == NULL)
1478				MALFORMED(buf1);
1479
1480			/* Skip the = */
1481			*sz1++ = '\0';
1482		}
1483
1484		/* Locate the size. */
1485		if ((sz0 = strchr(buf0, '=')) == NULL)
1486			MALFORMED(buf0);
1487
1488		/* Skip the = */
1489		*sz0++ = '\0';
1490
1491		GETVAL(sz0);
1492		ASSIGN(buf0);
1493
1494		if (buf1 != NULL) {
1495			GETVAL(sz1);
1496			ASSIGN(buf1);
1497		}
1498	}
1499
1500#undef ASSIGN
1501#undef GETVAL
1502#undef MALFORMED
1503
1504	if (parse_protocol(sep)) {
1505		freeconfig(sep);
1506		goto more;
1507	}
1508
1509	/* wait/nowait:max */
1510	arg = skip(&cp);
1511	if (arg == NULL) {
1512		LOG_TOO_FEW_ARGS();
1513		freeconfig(sep);
1514		goto more;
1515	}
1516
1517	/* Rate limiting parsing */ {
1518		char *cp1;
1519		if ((cp1 = strchr(arg, ':')) == NULL)
1520			cp1 = strchr(arg, '.');
1521		if (cp1 != NULL) {
1522			int rstatus;
1523			*cp1++ = '\0';
1524			sep->se_service_max = (size_t)strtou(cp1, NULL, 10, 0,
1525			    SERVTAB_COUNT_MAX, &rstatus);
1526
1527			if (rstatus != 0) {
1528				if (rstatus != ERANGE) {
1529					/* For compatibility with atoi parsing */
1530					sep->se_service_max = 0;
1531				}
1532
1533				WRN("Improper \"max\" value '%s', "
1534				    "using '%zu' instead: %s",
1535				    cp1,
1536				    sep->se_service_max,
1537				    strerror(rstatus));
1538			}
1539
1540		} else
1541			sep->se_service_max = TOOMANY;
1542	}
1543	if (parse_wait(sep, strcmp(arg, "wait") == 0)) {
1544		freeconfig(sep);
1545		goto more;
1546	}
1547
1548	/* Parse user:group token */
1549	arg = skip(&cp);
1550	if(arg == NULL) {
1551		LOG_TOO_FEW_ARGS();
1552		freeconfig(sep);
1553		goto more;
1554	}
1555	char* separator = strchr(arg, ':');
1556	if (separator == NULL) {
1557		/* Backwards compatibility, allow dot instead of colon */
1558		separator = strchr(arg, '.');
1559	}
1560
1561	if (separator == NULL) {
1562		/* Only user was specified */
1563		sep->se_group = NULL;
1564	} else {
1565		*separator = '\0';
1566		sep->se_group = newstr(separator + 1);
1567	}
1568
1569	sep->se_user = newstr(arg);
1570
1571	/* Parser server-program (path to binary or "internal") */
1572	arg = skip(&cp);
1573	if (arg == NULL) {
1574		LOG_TOO_FEW_ARGS();
1575		freeconfig(sep);
1576		goto more;
1577	}
1578	if (parse_server(sep, arg)) {
1579		freeconfig(sep);
1580		goto more;
1581	}
1582
1583	argc = 0;
1584	for (arg = skip(&cp); cp != NULL; arg = skip(&cp)) {
1585		if (argc < MAXARGV)
1586			sep->se_argv[argc++] = newstr(arg);
1587	}
1588	while (argc <= MAXARGV)
1589		sep->se_argv[argc++] = NULL;
1590#ifdef IPSEC
1591	sep->se_policy = policy != NULL ? newstr(policy) : NULL;
1592#endif
1593	/* getconfigent read a positional service def, move to next line */
1594	*current_pos = nextline(fconfig);
1595	return (sep);
1596}
1597
1598void
1599freeconfig(struct servtab *cp)
1600{
1601	int i;
1602
1603	free(cp->se_hostaddr);
1604	free(cp->se_service);
1605	free(cp->se_proto);
1606	free(cp->se_user);
1607	free(cp->se_group);
1608	free(cp->se_server);
1609	for (i = 0; i < MAXARGV; i++)
1610		free(cp->se_argv[i]);
1611#ifdef IPSEC
1612	free(cp->se_policy);
1613#endif
1614}
1615
1616/*
1617 * Get next token *in the current service definition* from config file.
1618 * Allows multi-line parse if single space or single tab-indented.
1619 * Things in quotes are considered single token.
1620 * Advances cp to next token.
1621 */
1622static char *
1623skip(char **cpp)
1624{
1625	char *cp = *cpp;
1626	char *start;
1627	char quote;
1628
1629	if (*cpp == NULL)
1630		return (NULL);
1631
1632again:
1633	while (*cp == ' ' || *cp == '\t')
1634		cp++;
1635	if (*cp == '\0') {
1636		int c;
1637
1638		c = getc(fconfig);
1639		(void) ungetc(c, fconfig);
1640		if (c == ' ' || c == '\t')
1641			if ((cp = nextline(fconfig)) != NULL)
1642				goto again;
1643		*cpp = NULL;
1644		return (NULL);
1645	}
1646	start = cp;
1647	/* Parse shell-style quotes */
1648	quote = '\0';
1649	while (*cp != '\0' && (quote != '\0' || (*cp != ' ' && *cp != '\t'))) {
1650		if (*cp == '\'' || *cp == '"') {
1651			if (quote != '\0' && *cp != quote)
1652				cp++;
1653			else {
1654				if (quote != '\0')
1655					quote = '\0';
1656				else
1657					quote = *cp;
1658				memmove(cp, cp+1, strlen(cp));
1659			}
1660		} else
1661			cp++;
1662	}
1663	if (*cp != '\0')
1664		*cp++ = '\0';
1665	*cpp = cp;
1666	return (start);
1667}
1668
1669char *
1670nextline(FILE *fd)
1671{
1672	char *cp;
1673
1674	if (fgets(line, (int)sizeof(line), fd) == NULL) {
1675		if (ferror(fd) != 0) {
1676			ERR("Error when reading next line: %s", strerror(errno));
1677		}
1678		return NULL;
1679	}
1680	cp = strchr(line, '\n');
1681	if (cp != NULL)
1682		*cp = '\0';
1683	line_number++;
1684	return line;
1685}
1686
1687char *
1688newstr(const char *cp)
1689{
1690	char *dp;
1691	if ((dp = strdup((cp != NULL) ? cp : "")) != NULL)
1692		return (dp);
1693	syslog(LOG_ERR, "strdup: %m");
1694	exit(EXIT_FAILURE);
1695	/*NOTREACHED*/
1696}
1697
1698static void
1699inetd_setproctitle(char *a, int s)
1700{
1701	socklen_t size;
1702	struct sockaddr_storage ss;
1703	char hbuf[NI_MAXHOST];
1704	const char *hp;
1705	struct sockaddr *sa;
1706
1707	size = sizeof(ss);
1708	sa = (struct sockaddr *)(void *)&ss;
1709	if (getpeername(s, sa, &size) == 0) {
1710		if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
1711		    0, niflags) != 0)
1712			hp = "?";
1713		else
1714			hp = hbuf;
1715		setproctitle("-%s [%s]", a, hp);
1716	} else
1717		setproctitle("-%s", a);
1718}
1719
1720static void
1721bump_nofile(void)
1722{
1723#define FD_CHUNK	32
1724	struct rlimit rl;
1725
1726	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1727		syslog(LOG_ERR, "getrlimit: %m");
1728		return;
1729	}
1730	rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1731	if (rl.rlim_cur <= rlim_ofile_cur) {
1732		syslog(LOG_ERR,
1733		    "bump_nofile: cannot extend file limit, max = %d",
1734		    (int)rl.rlim_cur);
1735		return;
1736	}
1737
1738	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1739		syslog(LOG_ERR, "setrlimit: %m");
1740		return;
1741	}
1742
1743	rlim_ofile_cur = rl.rlim_cur;
1744	return;
1745}
1746
1747/*
1748 * Internet services provided internally by inetd:
1749 */
1750#define	BUFSIZE	4096
1751
1752/* ARGSUSED */
1753static void
1754echo_stream(int s, struct servtab *sep)	/* Echo service -- echo data back */
1755{
1756	char buffer[BUFSIZE];
1757	ssize_t i;
1758
1759	inetd_setproctitle(sep->se_service, s);
1760	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1761	    write(s, buffer, (size_t)i) > 0)
1762		;
1763}
1764
1765/* ARGSUSED */
1766static void
1767echo_dg(int s, struct servtab *sep)	/* Echo service -- echo data back */
1768{
1769	char buffer[BUFSIZE];
1770	ssize_t i;
1771	socklen_t size;
1772	struct sockaddr_storage ss;
1773	struct sockaddr *sa;
1774
1775	sa = (struct sockaddr *)(void *)&ss;
1776	size = sizeof(ss);
1777	if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1778		return;
1779	if (port_good_dg(sa))
1780		(void) sendto(s, buffer, (size_t)i, 0, sa, size);
1781}
1782
1783/* ARGSUSED */
1784static void
1785discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1786{
1787	char buffer[BUFSIZE];
1788
1789	inetd_setproctitle(sep->se_service, s);
1790	while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1791			errno == EINTR)
1792		;
1793}
1794
1795/* ARGSUSED */
1796static void
1797discard_dg(int s, struct servtab *sep)	/* Discard service -- ignore data */
1798
1799{
1800	char buffer[BUFSIZE];
1801
1802	(void) read(s, buffer, sizeof(buffer));
1803}
1804
1805#define LINESIZ 72
1806char ring[128];
1807char *endring;
1808
1809static void
1810initring(void)
1811{
1812	int i;
1813
1814	endring = ring;
1815
1816	for (i = 0; i <= 128; ++i)
1817		if (isprint(i))
1818			*endring++ = (char)i;
1819}
1820
1821/* ARGSUSED */
1822static void
1823chargen_stream(int s, struct servtab *sep)	/* Character generator */
1824{
1825	size_t len;
1826	char *rs, text[LINESIZ+2];
1827
1828	inetd_setproctitle(sep->se_service, s);
1829
1830	if (endring == NULL) {
1831		initring();
1832		rs = ring;
1833	}
1834
1835	text[LINESIZ] = '\r';
1836	text[LINESIZ + 1] = '\n';
1837	for (rs = ring;;) {
1838		if ((len = (size_t)(endring - rs)) >= LINESIZ)
1839			memmove(text, rs, LINESIZ);
1840		else {
1841			memmove(text, rs, len);
1842			memmove(text + len, ring, LINESIZ - len);
1843		}
1844		if (++rs == endring)
1845			rs = ring;
1846		if (write(s, text, sizeof(text)) != sizeof(text))
1847			break;
1848	}
1849}
1850
1851/* ARGSUSED */
1852static void
1853chargen_dg(int s, struct servtab *sep)		/* Character generator */
1854{
1855	struct sockaddr_storage ss;
1856	struct sockaddr *sa;
1857	static char *rs;
1858	size_t len;
1859	socklen_t size;
1860	char text[LINESIZ+2];
1861
1862	if (endring == 0) {
1863		initring();
1864		rs = ring;
1865	}
1866
1867	sa = (struct sockaddr *)(void *)&ss;
1868	size = sizeof(ss);
1869	if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
1870		return;
1871
1872	if (!port_good_dg(sa))
1873		return;
1874
1875	if ((len = (size_t)(endring - rs)) >= LINESIZ)
1876		memmove(text, rs, LINESIZ);
1877	else {
1878		memmove(text, rs, len);
1879		memmove(text + len, ring, LINESIZ - len);
1880	}
1881	if (++rs == endring)
1882		rs = ring;
1883	text[LINESIZ] = '\r';
1884	text[LINESIZ + 1] = '\n';
1885	(void) sendto(s, text, sizeof(text), 0, sa, size);
1886}
1887
1888/*
1889 * Return a machine readable date and time, in the form of the
1890 * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1891 * returns the number of seconds since midnight, Jan 1, 1970,
1892 * we must add 2208988800 seconds to this figure to make up for
1893 * some seventy years Bell Labs was asleep.
1894 */
1895
1896static uint32_t
1897machtime(void)
1898{
1899	struct timeval tv;
1900
1901	if (gettimeofday(&tv, NULL) < 0) {
1902		DPRINTF("Unable to get time of day");
1903		return (0);
1904	}
1905#define	OFFSET ((uint32_t)25567 * 24*60*60)
1906	return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1907#undef OFFSET
1908}
1909
1910/* ARGSUSED */
1911static void
1912machtime_stream(int s, struct servtab *sep)
1913{
1914	uint32_t result;
1915
1916	result = machtime();
1917	(void) write(s, &result, sizeof(result));
1918}
1919
1920/* ARGSUSED */
1921void
1922machtime_dg(int s, struct servtab *sep)
1923{
1924	uint32_t result;
1925	struct sockaddr_storage ss;
1926	struct sockaddr *sa;
1927	socklen_t size;
1928
1929	sa = (struct sockaddr *)(void *)&ss;
1930	size = sizeof(ss);
1931	if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0)
1932		return;
1933	if (!port_good_dg(sa))
1934		return;
1935	result = machtime();
1936	(void)sendto(s, &result, sizeof(result), 0, sa, size);
1937}
1938
1939/* ARGSUSED */
1940static void
1941daytime_stream(int s,struct servtab *sep)
1942/* Return human-readable time of day */
1943{
1944	char buffer[256];
1945	time_t clk;
1946	int len;
1947
1948	clk = time((time_t *) 0);
1949
1950	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1951	(void) write(s, buffer, (size_t)len);
1952}
1953
1954/* ARGSUSED */
1955void
1956daytime_dg(int s, struct servtab *sep)
1957/* Return human-readable time of day */
1958{
1959	char buffer[256];
1960	time_t clk;
1961	struct sockaddr_storage ss;
1962	struct sockaddr *sa;
1963	socklen_t size;
1964	int len;
1965
1966	clk = time((time_t *) 0);
1967
1968	sa = (struct sockaddr *)(void *)&ss;
1969	size = sizeof(ss);
1970	if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
1971		return;
1972	if (!port_good_dg(sa))
1973		return;
1974	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1975	(void) sendto(s, buffer, (size_t)len, 0, sa, size);
1976}
1977
1978#ifdef DEBUG_ENABLE
1979/*
1980 * print_service:
1981 *	Dump relevant information to stderr
1982 */
1983static void
1984print_service(const char *action, struct servtab *sep)
1985{
1986
1987	if (isrpcservice(sep))
1988		fprintf(stderr,
1989		    "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
1990#ifdef IPSEC
1991		    " policy=\"%s\""
1992#endif
1993		    "\n",
1994		    action, sep->se_service,
1995		    sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
1996		    sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
1997		    (long)sep->se_bi, sep->se_server
1998#ifdef IPSEC
1999		    , (sep->se_policy != NULL ? sep->se_policy : "")
2000#endif
2001		    );
2002	else
2003		fprintf(stderr,
2004		    "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
2005#ifdef IPSEC
2006		    " policy=%s"
2007#endif
2008		    "\n",
2009		    action, sep->se_hostaddr, sep->se_service,
2010		    sep->se_type == FAITH_TYPE ? "faith/" : "",
2011		    sep->se_proto,
2012		    sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2013		    (long)sep->se_bi, sep->se_server
2014#ifdef IPSEC
2015		    , (sep->se_policy != NULL ? sep->se_policy : "")
2016#endif
2017		    );
2018}
2019#endif
2020
2021static void
2022usage(void)
2023{
2024#ifdef LIBWRAP
2025	(void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2026#else
2027	(void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2028#endif
2029	exit(EXIT_FAILURE);
2030}
2031
2032
2033/*
2034 *  Based on TCPMUX.C by Mark K. Lottor November 1988
2035 *  sri-nic::ps:<mkl>tcpmux.c
2036 */
2037
2038static int		/* # of characters upto \r,\n or \0 */
2039get_line(int fd,	char *buf, int len)
2040{
2041	int count = 0;
2042	ssize_t n;
2043
2044	do {
2045		n = read(fd, buf, (size_t)(len - count));
2046		if (n == 0)
2047			return (count);
2048		if (n < 0)
2049			return (-1);
2050		while (--n >= 0) {
2051			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2052				return (count);
2053			count++;
2054			buf++;
2055		}
2056	} while (count < len);
2057	return (count);
2058}
2059
2060#define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
2061
2062#define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
2063
2064static void
2065tcpmux(int ctrl, struct servtab *sep)
2066{
2067	char service[MAX_SERV_LEN+1];
2068	int len;
2069
2070	/* Get requested service name */
2071	if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) {
2072		strwrite(ctrl, "-Error reading service name\r\n");
2073		goto reject;
2074	}
2075	service[len] = '\0';
2076
2077	DPRINTF("tcpmux: %s: service requested", service);
2078
2079	/*
2080	 * Help is a required command, and lists available services,
2081	 * one per line.
2082	 */
2083	if (strcasecmp(service, "help") == 0) {
2084		strwrite(ctrl, "+Available services:\r\n");
2085		strwrite(ctrl, "help\r\n");
2086		for (sep = servtab; sep != NULL; sep = sep->se_next) {
2087			if (!ISMUX(sep))
2088				continue;
2089			(void)write(ctrl, sep->se_service,
2090			    strlen(sep->se_service));
2091			strwrite(ctrl, "\r\n");
2092		}
2093		goto reject;
2094	}
2095
2096	/* Try matching a service in inetd.conf with the request */
2097	for (sep = servtab; sep != NULL; sep = sep->se_next) {
2098		if (!ISMUX(sep))
2099			continue;
2100		if (strcasecmp(service, sep->se_service) == 0) {
2101			if (ISMUXPLUS(sep))
2102				strwrite(ctrl, "+Go\r\n");
2103			run_service(ctrl, sep, true /* forked */);
2104			return;
2105		}
2106	}
2107	strwrite(ctrl, "-Service not available\r\n");
2108reject:
2109	_exit(EXIT_FAILURE);
2110}
2111
2112/*
2113 * check if the address/port where send data to is one of the obvious ports
2114 * that are used for denial of service attacks like two echo ports
2115 * just echoing data between them
2116 */
2117static int
2118port_good_dg(struct sockaddr *sa)
2119{
2120	struct in_addr in;
2121	struct sockaddr_in *sin;
2122#ifdef INET6
2123	struct in6_addr *in6;
2124	struct sockaddr_in6 *sin6;
2125#endif
2126	u_int16_t port;
2127	int i;
2128	char hbuf[NI_MAXHOST];
2129
2130	switch (sa->sa_family) {
2131	case AF_INET:
2132		sin = (struct sockaddr_in *)(void *)sa;
2133		in.s_addr = ntohl(sin->sin_addr.s_addr);
2134		port = ntohs(sin->sin_port);
2135#ifdef INET6
2136	v4chk:
2137#endif
2138		if (IN_MULTICAST(in.s_addr))
2139			goto bad;
2140		switch ((in.s_addr & 0xff000000) >> 24) {
2141		case 0: case 127: case 255:
2142			goto bad;
2143		}
2144		if (dg_broadcast(&in))
2145			goto bad;
2146		break;
2147#ifdef INET6
2148	case AF_INET6:
2149		sin6 = (struct sockaddr_in6 *)(void *)sa;
2150		in6 = &sin6->sin6_addr;
2151		port = ntohs(sin6->sin6_port);
2152		if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
2153			goto bad;
2154		if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
2155			memcpy(&in, &in6->s6_addr[12], sizeof(in));
2156			in.s_addr = ntohl(in.s_addr);
2157			goto v4chk;
2158		}
2159		break;
2160#endif
2161	default:
2162		/* XXX unsupported af, is it safe to assume it to be safe? */
2163		return true;
2164	}
2165
2166	for (i = 0; bad_ports[i] != 0; i++) {
2167		if (port == bad_ports[i])
2168			goto bad;
2169	}
2170
2171	return true;
2172
2173bad:
2174	if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
2175	    niflags) != 0)
2176		strlcpy(hbuf, "?", sizeof(hbuf));
2177	syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2178		hbuf, port);
2179	return false;
2180}
2181
2182/* XXX need optimization */
2183static int
2184dg_broadcast(struct in_addr *in)
2185{
2186	struct ifaddrs *ifa, *ifap;
2187	struct sockaddr_in *sin;
2188
2189	if (getifaddrs(&ifap) < 0)
2190		return false;
2191	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
2192		if (ifa->ifa_addr->sa_family != AF_INET ||
2193		    (ifa->ifa_flags & IFF_BROADCAST) == 0)
2194			continue;
2195		sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
2196		if (sin->sin_addr.s_addr == in->s_addr) {
2197			freeifaddrs(ifap);
2198			return true;
2199		}
2200	}
2201	freeifaddrs(ifap);
2202	return false;
2203}
2204
2205static int
2206my_kevent(const struct kevent *changelist, size_t nchanges,
2207    struct kevent *eventlist, size_t nevents)
2208{
2209	int	result;
2210
2211	while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2212	    NULL)) < 0)
2213		if (errno != EINTR) {
2214			syslog(LOG_ERR, "kevent: %m");
2215			exit(EXIT_FAILURE);
2216		}
2217
2218	return (result);
2219}
2220
2221static struct kevent *
2222allocchange(void)
2223{
2224	if (changes == __arraycount(changebuf)) {
2225		(void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0);
2226		changes = 0;
2227	}
2228
2229	return (&changebuf[changes++]);
2230}
2231
2232static void
2233config_root(void)
2234{
2235	struct servtab *sep;
2236	/* Uncheck services */
2237	for (sep = servtab; sep != NULL; sep = sep->se_next) {
2238		sep->se_checked = false;
2239	}
2240	defhost = newstr("*");
2241#ifdef IPSEC
2242	policy = NULL;
2243#endif
2244	fconfig = NULL;
2245	config();
2246	purge_unchecked();
2247}
2248
2249static void
2250purge_unchecked(void)
2251{
2252	struct servtab *sep, **sepp = &servtab;
2253	int servtab_count = 0;
2254	while ((sep = *sepp) != NULL) {
2255		if (sep->se_checked) {
2256			sepp = &sep->se_next;
2257			servtab_count++;
2258			continue;
2259		}
2260		*sepp = sep->se_next;
2261		if (sep->se_fd >= 0)
2262			close_sep(sep);
2263		if (isrpcservice(sep))
2264			unregister_rpc(sep);
2265		if (sep->se_family == AF_LOCAL)
2266			(void)unlink(sep->se_service);
2267#ifdef DEBUG_ENABLE
2268		if (debug)
2269			print_service("FREE", sep);
2270#endif
2271		freeconfig(sep);
2272		free(sep);
2273	}
2274	DPRINTF("%d service(s) loaded.", servtab_count);
2275}
2276
2277static bool
2278is_same_service(const struct servtab *sep, const struct servtab *cp)
2279{
2280	return
2281	    strcmp(sep->se_service, cp->se_service) == 0 &&
2282	    strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
2283	    strcmp(sep->se_proto, cp->se_proto) == 0 &&
2284	    sep->se_family == cp->se_family &&
2285	    ISMUX(sep) == ISMUX(cp);
2286}
2287
2288int
2289parse_protocol(struct servtab *sep)
2290{
2291	int val;
2292
2293	if (strcmp(sep->se_proto, "unix") == 0) {
2294		sep->se_family = AF_LOCAL;
2295	} else {
2296		val = (int)strlen(sep->se_proto);
2297		if (val == 0) {
2298			ERR("%s: invalid protocol specified",
2299			    sep->se_service);
2300			return -1;
2301		}
2302		val = sep->se_proto[val - 1];
2303		switch (val) {
2304		case '4':	/*tcp4 or udp4*/
2305			sep->se_family = AF_INET;
2306			break;
2307#ifdef INET6
2308		case '6':	/*tcp6 or udp6*/
2309			sep->se_family = AF_INET6;
2310			break;
2311#endif
2312		default:
2313			/* Use 'default' IP version which is IPv4, may eventually be
2314			 * changed to AF_INET6 */
2315			sep->se_family = AF_INET;
2316			break;
2317		}
2318		if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
2319#ifdef RPC
2320			char *cp1, *ccp;
2321			cp1 = strchr(sep->se_service, '/');
2322			if (cp1 == 0) {
2323				ERR("%s: no rpc version",
2324				    sep->se_service);
2325				return -1;
2326			}
2327			*cp1++ = '\0';
2328			sep->se_rpcversl = sep->se_rpcversh =
2329			    (int)strtol(cp1, &ccp, 0);
2330			if (ccp == cp1) {
2331		badafterall:
2332				ERR("%s/%s: bad rpc version",
2333				    sep->se_service, cp1);
2334				return -1;
2335			}
2336			if (*ccp == '-') {
2337				cp1 = ccp + 1;
2338				sep->se_rpcversh = (int)strtol(cp1, &ccp, 0);
2339				if (ccp == cp1)
2340					goto badafterall;
2341			}
2342#else
2343			ERR("%s: rpc services not supported",
2344			    sep->se_service);
2345			return -1;
2346#endif /* RPC */
2347		}
2348	}
2349	return 0;
2350}
2351
2352int
2353parse_wait(struct servtab *sep, int wait)
2354{
2355	if (!ISMUX(sep)) {
2356		sep->se_wait = wait;
2357		return 0;
2358	}
2359	/*
2360	 * Silently enforce "nowait" for TCPMUX services since
2361	 * they don't have an assigned port to listen on.
2362	 */
2363	sep->se_wait = 0;
2364
2365	if (strncmp(sep->se_proto, "tcp", 3)) {
2366		ERR("bad protocol for tcpmux service %s",
2367			sep->se_service);
2368		return -1;
2369	}
2370	if (sep->se_socktype != SOCK_STREAM) {
2371		ERR("bad socket type for tcpmux service %s",
2372		    sep->se_service);
2373		return -1;
2374	}
2375	return 0;
2376}
2377
2378int
2379parse_server(struct servtab *sep, const char *arg){
2380	sep->se_server = newstr(arg);
2381	if (strcmp(sep->se_server, "internal") != 0) {
2382		sep->se_bi = NULL;
2383		return 0;
2384	}
2385	struct biltin *bi;
2386
2387	for (bi = biltins; bi->bi_service; bi++)
2388		if (bi->bi_socktype == sep->se_socktype &&
2389		    strcmp(bi->bi_service, sep->se_service) == 0)
2390			break;
2391	if (bi->bi_service == NULL) {
2392		ERR("Internal service %s unknown",
2393		    sep->se_service);
2394		return -1;
2395	}
2396	sep->se_bi = bi;
2397	sep->se_wait = bi->bi_wait;
2398	return 0;
2399}
2400
2401/* TODO test to make sure accept filter still works */
2402void
2403parse_accept_filter(char *arg, struct servtab *sep) {
2404	char *accf, *accf_arg;
2405	/* one and only one accept filter */
2406	accf = strchr(arg, ':');
2407	if (accf == NULL)
2408		return;
2409	if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') {
2410		/* more than one ||  nothing beyond */
2411		sep->se_socktype = -1;
2412		return;
2413	}
2414
2415	accf++;			/* skip delimiter */
2416	strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name));
2417	accf_arg = strchr(accf, ',');
2418	if (accf_arg == NULL)	/* zero or one arg, no more */
2419		return;
2420
2421	if (strrchr(accf, ',') != accf_arg) {
2422		sep->se_socktype = -1;
2423	} else {
2424		accf_arg++;
2425		strlcpy(sep->se_accf.af_arg, accf_arg,
2426		    sizeof(sep->se_accf.af_arg));
2427	}
2428}
2429
2430void
2431parse_socktype(char* arg, struct servtab* sep)
2432{
2433	/* stream socket may have an accept filter, only check first chars */
2434	if (strncmp(arg, "stream", sizeof("stream") - 1) == 0)
2435		sep->se_socktype = SOCK_STREAM;
2436	else if (strcmp(arg, "dgram") == 0)
2437		sep->se_socktype = SOCK_DGRAM;
2438	else if (strcmp(arg, "rdm") == 0)
2439		sep->se_socktype = SOCK_RDM;
2440	else if (strcmp(arg, "seqpacket") == 0)
2441		sep->se_socktype = SOCK_SEQPACKET;
2442	else if (strcmp(arg, "raw") == 0)
2443		sep->se_socktype = SOCK_RAW;
2444	else
2445		sep->se_socktype = -1;
2446}
2447
2448static struct servtab
2449init_servtab(void)
2450{
2451	/* This does not set every field to default. See enter() as well */
2452	return (struct servtab) {
2453		/*
2454		 * Set se_max to non-zero so uninitialized value is not
2455	 	 * a valid value. Useful in v2 syntax parsing.
2456		 */
2457		.se_service_max = SERVTAB_UNSPEC_SIZE_T,
2458		.se_ip_max = SERVTAB_UNSPEC_SIZE_T,
2459		.se_wait = SERVTAB_UNSPEC_VAL,
2460		.se_socktype = SERVTAB_UNSPEC_VAL
2461		/* All other fields initialized to 0 or null */
2462	};
2463}
2464
2465/* Include directives bookkeeping structure */
2466struct file_list {
2467	/* Absolute path used for checking for circular references */
2468	char *abs;
2469	/* Pointer to the absolute path of the parent config file,
2470	 * on the stack */
2471	struct file_list *next;
2472} *file_list_head;
2473
2474static void
2475include_configs(char *pattern)
2476{
2477	/* Allocate global per-config state on the thread stack */
2478	const char* save_CONFIG;
2479	FILE	*save_fconfig;
2480	size_t	save_line_number;
2481	char    *save_defhost;
2482	struct	file_list new_file;
2483#ifdef IPSEC
2484	char *save_policy;
2485#endif
2486
2487	/* Store current globals on the stack */
2488	save_CONFIG = CONFIG;
2489	save_fconfig = fconfig;
2490	save_line_number = line_number;
2491	save_defhost = defhost;
2492	new_file.abs = realpath(CONFIG, NULL);
2493	new_file.next = file_list_head;
2494#ifdef IPSEC
2495	save_policy = policy;
2496#endif
2497	/* Put new_file at the top of the config stack */
2498	file_list_head = &new_file;
2499	read_glob_configs(pattern);
2500	free(new_file.abs);
2501	/* Pop new_file off the stack */
2502	file_list_head = new_file.next;
2503
2504	/* Restore global per-config state */
2505	CONFIG = save_CONFIG;
2506	fconfig = save_fconfig;
2507	line_number = save_line_number;
2508	defhost = save_defhost;
2509#ifdef IPSEC
2510	policy = save_policy;
2511#endif
2512}
2513
2514static void
2515prepare_next_config(const char *file_name)
2516{
2517	/* Setup new state that is normally only done in main */
2518	CONFIG = file_name;
2519
2520	/* Inherit default host and IPsec policy */
2521	defhost = newstr(defhost);
2522
2523#ifdef IPSEC
2524	policy = (policy == NULL) ? NULL : newstr(policy);
2525#endif
2526}
2527
2528static void
2529read_glob_configs(char *pattern) {
2530	glob_t results;
2531	char *full_pattern;
2532	int glob_result;
2533	full_pattern = gen_file_pattern(CONFIG, pattern);
2534
2535	DPRINTCONF("Found include directive '%s'", full_pattern);
2536
2537	glob_result = glob(full_pattern, GLOB_NOSORT, glob_error, &results);
2538	switch(glob_result) {
2539	case 0:
2540		/* No glob errors */
2541		break;
2542	case GLOB_ABORTED:
2543		ERR("Error while searching for include files");
2544		break;
2545	case GLOB_NOMATCH:
2546		/* It's fine if no files were matched. */
2547		DPRINTCONF("No files matched pattern '%s'", full_pattern);
2548		break;
2549	case GLOB_NOSPACE:
2550		ERR("Error when searching for include files: %s",
2551		    strerror(errno));
2552		break;
2553	default:
2554		ERR("Unknown glob(3) error %d", errno);
2555		break;
2556	}
2557	free(full_pattern);
2558
2559	for (size_t i = 0; i < results.gl_pathc; i++) {
2560		include_matched_path(results.gl_pathv[i]);
2561	}
2562
2563	globfree(&results);
2564}
2565
2566static void
2567include_matched_path(char *glob_path)
2568{
2569	struct stat sb;
2570	char *tmp;
2571
2572	if (lstat(glob_path, &sb) != 0) {
2573		ERR("Error calling stat on path '%s': %s", glob_path,
2574		    strerror(errno));
2575		return;
2576	}
2577
2578	if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
2579		DPRINTCONF("'%s' is not a file.", glob_path);
2580		ERR("The matched path '%s' is not a regular file", glob_path);
2581		return;
2582	}
2583
2584	DPRINTCONF("Include '%s'", glob_path);
2585
2586	if (S_ISLNK(sb.st_mode)) {
2587		tmp = glob_path;
2588		glob_path = realpath(tmp, NULL);
2589	}
2590
2591	/* Ensure the file is not being reincluded .*/
2592	if (check_no_reinclude(glob_path)) {
2593		prepare_next_config(glob_path);
2594		config();
2595	} else {
2596		DPRINTCONF("File '%s' already included in current include "
2597		    "chain", glob_path);
2598		WRN("Including file '%s' would cause a circular "
2599		    "dependency", glob_path);
2600	}
2601
2602	if (S_ISLNK(sb.st_mode)) {
2603		free(glob_path);
2604		glob_path = tmp;
2605	}
2606}
2607
2608static bool
2609check_no_reinclude(const char *glob_path)
2610{
2611	struct file_list *cur = file_list_head;
2612	char *abs_path = realpath(glob_path, NULL);
2613
2614	if (abs_path == NULL) {
2615		ERR("Error checking real path for '%s': %s",
2616			glob_path, strerror(errno));
2617		return false;
2618	}
2619
2620	DPRINTCONF("Absolute path '%s'", abs_path);
2621
2622	for (cur = file_list_head; cur != NULL; cur = cur->next) {
2623		if (strcmp(cur->abs, abs_path) == 0) {
2624			/* file included more than once */
2625			/* TODO relative or abs path for logging error? */
2626			free(abs_path);
2627			return false;
2628		}
2629	}
2630	free(abs_path);
2631	return true;
2632}
2633
2634/* Resolve the pattern relative to the config file the pattern is from  */
2635static char *
2636gen_file_pattern(const char *cur_config, const char *pattern)
2637{
2638	if (pattern[0] == '/') {
2639		/* Absolute paths don't need any normalization */
2640		return newstr(pattern);
2641	}
2642
2643	/* pattern is relative */
2644	/* Find the end of the file's directory */
2645	size_t i, last = 0;
2646	for (i = 0; cur_config[i] != '\0'; i++) {
2647		if (cur_config[i] == '/') {
2648			last = i;
2649		}
2650	}
2651
2652	if (last == 0) {
2653		/* cur_config is just a filename, pattern already correct */
2654		return newstr(pattern);
2655	}
2656
2657	/* Relativize pattern to cur_config file's directory */
2658	char *full_pattern = malloc(last + 1 + strlen(pattern) + 1);
2659	if (full_pattern == NULL) {
2660		syslog(LOG_ERR, "Out of memory.");
2661		exit(EXIT_FAILURE);
2662	}
2663	memcpy(full_pattern, cur_config, last);
2664	full_pattern[last] = '/';
2665	strcpy(&full_pattern[last + 1], pattern);
2666	return full_pattern;
2667}
2668
2669static int
2670glob_error(const char *path, int error)
2671{
2672	WRN("Error while resolving path '%s': %s", path, strerror(error));
2673	return 0;
2674}
2675
2676/* Return 0 on allow, -1 if connection should be blocked */
2677static int
2678rl_process(struct servtab *sep, int ctrl)
2679{
2680	struct se_ip_list_node *node;
2681	time_t now = 0; /* 0 prevents GCC from complaining */
2682	bool istimevalid = false;
2683	char hbuf[NI_MAXHOST];
2684
2685	DPRINTF(SERV_FMT ": processing rate-limiting",
2686	    SERV_PARAMS(sep));
2687	DPRINTF(SERV_FMT ": se_service_max "
2688	    "%zu and se_count %zu", SERV_PARAMS(sep),
2689	    sep->se_service_max, sep->se_count);
2690
2691	/* se_count is incremented if rl_process will return 0 */
2692	if (sep->se_count == 0) {
2693		now = rl_time();
2694		sep->se_time = now;
2695		istimevalid = true;
2696	}
2697
2698	if (sep->se_count >= sep->se_service_max) {
2699		if(!istimevalid) {
2700			now = rl_time();
2701			istimevalid = true;
2702		}
2703
2704		if (now - sep->se_time > CNT_INTVL) {
2705			rl_reset(sep, now);
2706		} else {
2707			syslog(LOG_ERR,
2708			    SERV_FMT ": max spawn rate (%zu in %ji seconds) "
2709			    "already met, closing until end of timeout in "
2710			    "%ju seconds",
2711			    SERV_PARAMS(sep),
2712			    sep->se_service_max,
2713			    (intmax_t)CNT_INTVL,
2714			    (uintmax_t)RETRYTIME);
2715
2716			DPRINTF(SERV_FMT ": service not started",
2717			    SERV_PARAMS(sep));
2718
2719			rl_drop_connection(sep, ctrl);
2720
2721			/* Close the server for 10 minutes */
2722			close_sep(sep);
2723			if (!timingout) {
2724				timingout = true;
2725				alarm(RETRYTIME);
2726			}
2727
2728			return -1;
2729		}
2730	}
2731
2732	if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2733		rl_get_name(sep, ctrl, hbuf);
2734		node = rl_try_get_ip(sep, hbuf);
2735		if(node == NULL) {
2736			node = rl_add(sep, hbuf);
2737		}
2738
2739		DPRINTF(
2740		    SERV_FMT ": se_ip_max %zu and ip_count %zu",
2741		    SERV_PARAMS(sep), sep->se_ip_max, node->count);
2742
2743		if (node->count >= sep->se_ip_max) {
2744			if (!istimevalid) {
2745				/*
2746				 * Only get the clock time if we didn't
2747				 * already
2748				 */
2749				now = rl_time();
2750				istimevalid = true;
2751			}
2752
2753			if (now - sep->se_time > CNT_INTVL) {
2754				rl_reset(sep, now);
2755				node = rl_add(sep, hbuf);
2756			} else {
2757				if (debug && node->count == sep->se_ip_max) {
2758					/*
2759					 * Only log first failed request to
2760					 * prevent DoS attack writing to system
2761					 * log
2762					 */
2763					syslog(LOG_ERR, SERV_FMT
2764					    ": max ip spawn rate (%zu in "
2765					    "%ji seconds) for "
2766					    "%." TOSTRING(NI_MAXHOST) "s "
2767					    "already met; service not started",
2768					    SERV_PARAMS(sep),
2769					    sep->se_ip_max,
2770					    (intmax_t)CNT_INTVL,
2771					    node->address);
2772				}
2773
2774				DPRINTF(SERV_FMT ": service not started",
2775   				    SERV_PARAMS(sep));
2776
2777				rl_drop_connection(sep, ctrl);
2778				/*
2779				 * Increment so debug-syslog message will
2780				 * trigger only once
2781				 */
2782				node->count++;
2783				return -1;
2784			}
2785		}
2786		node->count++;
2787	}
2788
2789	DPRINTF(SERV_FMT ": running service ", SERV_PARAMS(sep));
2790
2791	sep->se_count++;
2792	return 0;
2793}
2794
2795/* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */
2796static void
2797rl_get_name(struct servtab *sep, int ctrl, char *hbuf)
2798{
2799	struct sockaddr_storage addr;
2800	socklen_t len = sizeof(struct sockaddr_storage);
2801	switch (sep->se_socktype) {
2802	case SOCK_STREAM:
2803		if (getpeername(ctrl, (struct sockaddr *)&addr, &len) != 0) {
2804			/* error, log it and skip ip rate limiting */
2805			syslog(LOG_ERR,
2806				SERV_FMT " failed to get peer name of the "
2807				"connection", SERV_PARAMS(sep));
2808			exit(EXIT_FAILURE);
2809		}
2810		break;
2811	case SOCK_DGRAM: {
2812		struct msghdr header = {
2813			.msg_name = &addr,
2814			.msg_namelen = sizeof(struct sockaddr_storage),
2815			/* scatter/gather and control info is null */
2816		};
2817		ssize_t count;
2818
2819		/* Peek so service can still get the packet */
2820		count = recvmsg(ctrl, &header, MSG_PEEK);
2821		if (count == -1) {
2822			syslog(LOG_ERR,
2823			    "failed to get dgram source address: %s; exiting",
2824			    strerror(errno));
2825			exit(EXIT_FAILURE);
2826		}
2827		break;
2828	}
2829	default:
2830		DPRINTF(SERV_FMT ": ip_max rate limiting not supported for "
2831		    "socktype", SERV_PARAMS(sep));
2832		syslog(LOG_ERR, SERV_FMT
2833		    ": ip_max rate limiting not supported for socktype",
2834		    SERV_PARAMS(sep));
2835		exit(EXIT_FAILURE);
2836	}
2837
2838	if (getnameinfo((struct sockaddr *)&addr,
2839		addr.ss_len, hbuf,
2840		NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) {
2841		/* error, log it and skip ip rate limiting */
2842		syslog(LOG_ERR,
2843		    SERV_FMT ": failed to get name info of the incoming "
2844		    "connection; exiting",
2845		    SERV_PARAMS(sep));
2846		exit(EXIT_FAILURE);
2847	}
2848}
2849
2850static void
2851rl_drop_connection(struct servtab *sep, int ctrl)
2852{
2853
2854	if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
2855		/*
2856		 * If the fd isn't a listen socket,
2857		 * close the individual connection too.
2858		 */
2859		close(ctrl);
2860		return;
2861	}
2862	if (sep->se_socktype != SOCK_DGRAM) {
2863		return;
2864	}
2865	/*
2866	 * Drop the single datagram the service would have
2867	 * consumed if nowait. If this is a wait service, this
2868	 * will consume 1 datagram, and further received packets
2869	 * will be removed in the same way.
2870	 */
2871	struct msghdr header = {
2872		/* All fields null, just consume one message */
2873	};
2874	ssize_t count;
2875
2876	count = recvmsg(ctrl, &header, 0);
2877	if (count == -1) {
2878		syslog(LOG_ERR,
2879		    SERV_FMT ": failed to consume nowait dgram: %s",
2880		    SERV_PARAMS(sep), strerror(errno));
2881		exit(EXIT_FAILURE);
2882	}
2883	DPRINTF(SERV_FMT ": dropped dgram message",
2884	    SERV_PARAMS(sep));
2885}
2886
2887static time_t
2888rl_time(void)
2889{
2890	struct timespec time;
2891	if(clock_gettime(CLOCK_MONOTONIC, &time) == -1) {
2892		syslog(LOG_ERR, "clock_gettime for rate limiting failed: %s; "
2893		    "exiting", strerror(errno));
2894		/* Exit inetd if rate limiting fails */
2895		exit(EXIT_FAILURE);
2896	}
2897	return time.tv_sec;
2898}
2899
2900static struct se_ip_list_node*
2901rl_add(struct servtab *sep, char* ip)
2902{
2903	DPRINTF(
2904	    SERV_FMT ": add ip %s to rate limiting tracking",
2905	    SERV_PARAMS(sep), ip);
2906
2907	/*
2908	 * TODO memory could be saved by using a variable length malloc
2909	 * with only the length of ip instead of the existing address field
2910	 * NI_MAXHOST in length.
2911	 */
2912	struct se_ip_list_node* temp = malloc(sizeof(*temp));
2913	if (temp == NULL) {
2914		syslog(LOG_ERR, "Out of memory.");
2915		exit(EXIT_FAILURE);
2916	}
2917	temp->count = 0;
2918	temp->next = NULL;
2919	strlcpy(temp->address, ip, sizeof(temp->address));
2920
2921	if (sep->se_ip_list_head == NULL) {
2922		/* List empty, insert as head */
2923		sep->se_ip_list_head = temp;
2924	} else {
2925		/* List not empty, insert as head, point next to prev head */
2926		temp->next = sep->se_ip_list_head;
2927		sep->se_ip_list_head = temp;
2928	}
2929
2930	return temp;
2931}
2932
2933static void
2934rl_reset(struct servtab *sep, time_t now)
2935{
2936	DPRINTF(SERV_FMT ": %ji seconds passed; resetting rate limiting ",
2937	    SERV_PARAMS(sep), (intmax_t)(now - sep->se_time));
2938
2939	sep->se_count = 0;
2940	sep->se_time = now;
2941	if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2942		clear_ip_list(sep);
2943	}
2944}
2945
2946static void
2947clear_ip_list(struct servtab *sep) {
2948	struct se_ip_list_node *curr, *next;
2949	curr = sep->se_ip_list_head;
2950
2951	while (curr != NULL) {
2952		next = curr->next;
2953		free(curr);
2954		curr = next;
2955	}
2956	sep->se_ip_list_head = NULL;
2957}
2958
2959static struct se_ip_list_node *
2960rl_try_get_ip(struct servtab *sep, char *ip)
2961{
2962	struct se_ip_list_node *curr;
2963
2964	DPRINTF(
2965	    SERV_FMT ": look up ip %s for ip_max rate limiting",
2966	    SERV_PARAMS(sep), ip);
2967
2968	for (curr = sep->se_ip_list_head; curr != NULL; curr = curr->next) {
2969		if (!strncmp(curr->address, ip, NI_MAXHOST)) {
2970			/* IP addr match */
2971			return curr;
2972		}
2973	}
2974	return NULL;
2975}
2976