inetd.c revision 1.133
1/*	$NetBSD: inetd.c,v 1.133 2021/09/03 19:33:51 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.133 2021/09/03 19:33:51 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,	1, 0,	echo_stream },
341	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg },
342
343	/* Internet /dev/null */
344	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream },
345	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg },
346
347	/* Return 32 bit time since 1970 */
348	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream },
349	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg },
350
351	/* Return human-readable time */
352	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream },
353	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg },
354
355	/* Familiar character generator */
356	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream },
357	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg },
358
359	{ "tcpmux",	SOCK_STREAM,	1, 0,	tcpmux },
360
361	{ NULL, 0, 0, 0, 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 = 1;
393			options |= SO_DEBUG;
394			break;
395#ifdef LIBWRAP
396		case 'l':
397			lflag = 1;
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 = 0;
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 = 1;
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 && 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 = 1;
512#else
513	dofork = (sep->se_bi == 0 || 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 && sep->se_socktype == SOCK_STREAM)
523				close(ctrl);
524			sleep(1);
525			return;
526		}
527		if (pid != 0 && sep->se_wait) {
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 && 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 && sep->se_socktype == SOCK_STREAM) {
572		request_init(&req, RQ_DAEMON, sep->se_argv[0] ?
573		    sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
574		fromhost(&req);
575		denied = !hosts_access(&req);
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) {
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) {
607		if (didfork) {
608			for (s = servtab; s; 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 &&
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) {
628			if (sep->se_group)
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) {
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 = 0;
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, "*"))
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) {
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 = 0;
860				continue;
861			}
862			if (res->ai_next) {
863				syslog(LOG_ERR,
864					SERV_FMT ": %s: resolved to multiple addr",
865				    SERV_PARAMS(sep),
866				    sep->se_hostaddr);
867				sep->se_checked = 0;
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 = 0;
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 = 0;
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 = 1;
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))
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))
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; p && *p && 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) {
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	/*NOTREACHED*/ \
1416} while (/*CONSTCOND*/0)
1417
1418#define	GETVAL(arg) \
1419do { \
1420	if (!isdigit((unsigned char)*(arg))) \
1421		MALFORMED(arg); \
1422	val = (int)strtol((arg), &cp0, 10); \
1423	if (cp0 != NULL) { \
1424		if (cp0[1] != '\0') \
1425			MALFORMED((arg)); \
1426		if (cp0[0] == 'k') \
1427			val *= 1024; \
1428		if (cp0[0] == 'm') \
1429			val *= 1024 * 1024; \
1430	} \
1431	if (val < 1) { \
1432		ERR("%s: invalid buffer size `%s'", \
1433		    sep->se_service, (arg)); \
1434		freeconfig(sep); \
1435		goto more; \
1436	} \
1437	/*NOTREACHED*/ \
1438} while (/*CONSTCOND*/0)
1439
1440#define	ASSIGN(arg) \
1441do { \
1442	if (strcmp((arg), "sndbuf") == 0) \
1443		sep->se_sndbuf = val; \
1444	else if (strcmp((arg), "rcvbuf") == 0) \
1445		sep->se_rcvbuf = val; \
1446	else \
1447		MALFORMED((arg)); \
1448} while (/*CONSTCOND*/0)
1449
1450	/*
1451	 * Extract the send and receive buffer sizes before parsing
1452	 * the protocol.
1453	 */
1454	sep->se_sndbuf = sep->se_rcvbuf = 0;
1455	buf0 = buf1 = sz0 = sz1 = NULL;
1456	if ((buf0 = strchr(sep->se_proto, ',')) != NULL) {
1457		/* Not meaningful for Tcpmux services. */
1458		if (ISMUX(sep)) {
1459			ERR("%s: can't specify buffer sizes for "
1460			    "tcpmux services", sep->se_service);
1461			goto more;
1462		}
1463
1464		/* Skip the , */
1465		*buf0++ = '\0';
1466
1467		/* Check to see if another socket buffer size was specified. */
1468		if ((buf1 = strchr(buf0, ',')) != NULL) {
1469			/* Skip the , */
1470			*buf1++ = '\0';
1471
1472			/* Make sure a 3rd one wasn't specified. */
1473			if (strchr(buf1, ',') != NULL) {
1474				ERR("%s: too many buffer sizes", sep->se_service);
1475				goto more;
1476			}
1477
1478			/* Locate the size. */
1479			if ((sz1 = strchr(buf1, '=')) == NULL)
1480				MALFORMED(buf1);
1481
1482			/* Skip the = */
1483			*sz1++ = '\0';
1484		}
1485
1486		/* Locate the size. */
1487		if ((sz0 = strchr(buf0, '=')) == NULL)
1488			MALFORMED(buf0);
1489
1490		/* Skip the = */
1491		*sz0++ = '\0';
1492
1493		GETVAL(sz0);
1494		ASSIGN(buf0);
1495
1496		if (buf1 != NULL) {
1497			GETVAL(sz1);
1498			ASSIGN(buf1);
1499		}
1500	}
1501
1502#undef ASSIGN
1503#undef GETVAL
1504#undef MALFORMED
1505
1506	if (parse_protocol(sep)) {
1507		freeconfig(sep);
1508		goto more;
1509	}
1510
1511	/* wait/nowait:max */
1512	arg = skip(&cp);
1513	if (arg == NULL) {
1514		LOG_TOO_FEW_ARGS();
1515		freeconfig(sep);
1516		goto more;
1517	}
1518
1519	/* Rate limiting parsing */ {
1520		char *cp1;
1521		if ((cp1 = strchr(arg, ':')) == NULL)
1522			cp1 = strchr(arg, '.');
1523		if (cp1 != NULL) {
1524			int rstatus;
1525			*cp1++ = '\0';
1526			sep->se_service_max = (size_t)strtou(cp1, NULL, 10, 0,
1527			    SERVTAB_COUNT_MAX, &rstatus);
1528
1529			if (rstatus != 0) {
1530				if (rstatus != ERANGE) {
1531					/* For compatibility with atoi parsing */
1532					sep->se_service_max = 0;
1533				}
1534
1535				WRN("Improper \"max\" value '%s', "
1536				    "using '%zu' instead: %s",
1537				    cp1,
1538				    sep->se_service_max,
1539				    strerror(rstatus));
1540			}
1541
1542		} else
1543			sep->se_service_max = TOOMANY;
1544	}
1545	if (parse_wait(sep, strcmp(arg, "wait") == 0)) {
1546		freeconfig(sep);
1547		goto more;
1548	}
1549
1550	/* Parse user:group token */
1551	arg = skip(&cp);
1552	if(arg == NULL) {
1553		LOG_TOO_FEW_ARGS();
1554		freeconfig(sep);
1555		goto more;
1556	}
1557	char* separator = strchr(arg, ':');
1558	if (separator == NULL) {
1559		/* Backwards compatibility, allow dot instead of colon */
1560		separator = strchr(arg, '.');
1561	}
1562
1563	if (separator == NULL) {
1564		/* Only user was specified */
1565		sep->se_group = NULL;
1566	} else {
1567		*separator = '\0';
1568		sep->se_group = newstr(separator + 1);
1569	}
1570
1571	sep->se_user = newstr(arg);
1572
1573	/* Parser server-program (path to binary or "internal") */
1574	arg = skip(&cp);
1575	if (arg == NULL) {
1576		LOG_TOO_FEW_ARGS();
1577		freeconfig(sep);
1578		goto more;
1579	}
1580	if (parse_server(sep, arg)) {
1581		freeconfig(sep);
1582		goto more;
1583	}
1584
1585	argc = 0;
1586	for (arg = skip(&cp); cp; arg = skip(&cp)) {
1587		if (argc < MAXARGV)
1588			sep->se_argv[argc++] = newstr(arg);
1589	}
1590	while (argc <= MAXARGV)
1591		sep->se_argv[argc++] = NULL;
1592#ifdef IPSEC
1593	sep->se_policy = policy ? newstr(policy) : NULL;
1594#endif
1595	/* getconfigent read a positional service def, move to next line */
1596	*current_pos = nextline(fconfig);
1597	return (sep);
1598}
1599
1600void
1601freeconfig(struct servtab *cp)
1602{
1603	int i;
1604
1605	if (cp->se_hostaddr)
1606		free(cp->se_hostaddr);
1607	if (cp->se_service)
1608		free(cp->se_service);
1609	if (cp->se_proto)
1610		free(cp->se_proto);
1611	if (cp->se_user)
1612		free(cp->se_user);
1613	if(cp->se_group)
1614		free(cp->se_group);
1615	if (cp->se_server)
1616		free(cp->se_server);
1617	for (i = 0; i < MAXARGV; i++)
1618		if (cp->se_argv[i])
1619			free(cp->se_argv[i]);
1620#ifdef IPSEC
1621	if (cp->se_policy)
1622		free(cp->se_policy);
1623#endif
1624}
1625
1626/*
1627 * Get next token *in the current service definition* from config file.
1628 * Allows multi-line parse if single space or single tab-indented.
1629 * Things in quotes are considered single token.
1630 * Advances cp to next token.
1631 */
1632static char *
1633skip(char **cpp)
1634{
1635	char *cp = *cpp;
1636	char *start;
1637	char quote;
1638
1639	if (*cpp == NULL)
1640		return (NULL);
1641
1642again:
1643	while (*cp == ' ' || *cp == '\t')
1644		cp++;
1645	if (*cp == '\0') {
1646		int c;
1647
1648		c = getc(fconfig);
1649		(void) ungetc(c, fconfig);
1650		if (c == ' ' || c == '\t')
1651			if ((cp = nextline(fconfig)) != NULL)
1652				goto again;
1653		*cpp = NULL;
1654		return (NULL);
1655	}
1656	start = cp;
1657	/* Parse shell-style quotes */
1658	quote = '\0';
1659	while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) {
1660		if (*cp == '\'' || *cp == '"') {
1661			if (quote && *cp != quote)
1662				cp++;
1663			else {
1664				if (quote)
1665					quote = '\0';
1666				else
1667					quote = *cp;
1668				memmove(cp, cp+1, strlen(cp));
1669			}
1670		} else
1671			cp++;
1672	}
1673	if (*cp != '\0')
1674		*cp++ = '\0';
1675	*cpp = cp;
1676	return (start);
1677}
1678
1679char *
1680nextline(FILE *fd)
1681{
1682	char *cp;
1683
1684	if (fgets(line, (int)sizeof(line), fd) == NULL) {
1685		if (ferror(fd)) {
1686			ERR("Error when reading next line: %s", strerror(errno));
1687		}
1688		return NULL;
1689	}
1690	cp = strchr(line, '\n');
1691	if (cp)
1692		*cp = '\0';
1693	line_number++;
1694	return line;
1695}
1696
1697char *
1698newstr(const char *cp)
1699{
1700	char *dp;
1701	if ((dp = strdup((cp != NULL) ? cp : "")) != NULL)
1702		return (dp);
1703	syslog(LOG_ERR, "strdup: %m");
1704	exit(EXIT_FAILURE);
1705	/*NOTREACHED*/
1706}
1707
1708static void
1709inetd_setproctitle(char *a, int s)
1710{
1711	socklen_t size;
1712	struct sockaddr_storage ss;
1713	char hbuf[NI_MAXHOST];
1714	const char *hp;
1715	struct sockaddr *sa;
1716
1717	size = sizeof(ss);
1718	sa = (struct sockaddr *)(void *)&ss;
1719	if (getpeername(s, sa, &size) == 0) {
1720		if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
1721		    0, niflags) != 0)
1722			hp = "?";
1723		else
1724			hp = hbuf;
1725		setproctitle("-%s [%s]", a, hp);
1726	} else
1727		setproctitle("-%s", a);
1728}
1729
1730static void
1731bump_nofile(void)
1732{
1733#define FD_CHUNK	32
1734	struct rlimit rl;
1735
1736	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1737		syslog(LOG_ERR, "getrlimit: %m");
1738		return;
1739	}
1740	rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1741	if (rl.rlim_cur <= rlim_ofile_cur) {
1742		syslog(LOG_ERR,
1743		    "bump_nofile: cannot extend file limit, max = %d",
1744		    (int)rl.rlim_cur);
1745		return;
1746	}
1747
1748	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1749		syslog(LOG_ERR, "setrlimit: %m");
1750		return;
1751	}
1752
1753	rlim_ofile_cur = rl.rlim_cur;
1754	return;
1755}
1756
1757/*
1758 * Internet services provided internally by inetd:
1759 */
1760#define	BUFSIZE	4096
1761
1762/* ARGSUSED */
1763static void
1764echo_stream(int s, struct servtab *sep)	/* Echo service -- echo data back */
1765{
1766	char buffer[BUFSIZE];
1767	ssize_t i;
1768
1769	inetd_setproctitle(sep->se_service, s);
1770	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1771	    write(s, buffer, (size_t)i) > 0)
1772		;
1773}
1774
1775/* ARGSUSED */
1776static void
1777echo_dg(int s, struct servtab *sep)	/* Echo service -- echo data back */
1778{
1779	char buffer[BUFSIZE];
1780	ssize_t i;
1781	socklen_t size;
1782	struct sockaddr_storage ss;
1783	struct sockaddr *sa;
1784
1785	sa = (struct sockaddr *)(void *)&ss;
1786	size = sizeof(ss);
1787	if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1788		return;
1789	if (port_good_dg(sa))
1790		(void) sendto(s, buffer, (size_t)i, 0, sa, size);
1791}
1792
1793/* ARGSUSED */
1794static void
1795discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1796{
1797	char buffer[BUFSIZE];
1798
1799	inetd_setproctitle(sep->se_service, s);
1800	while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1801			errno == EINTR)
1802		;
1803}
1804
1805/* ARGSUSED */
1806static void
1807discard_dg(int s, struct servtab *sep)	/* Discard service -- ignore data */
1808
1809{
1810	char buffer[BUFSIZE];
1811
1812	(void) read(s, buffer, sizeof(buffer));
1813}
1814
1815#define LINESIZ 72
1816char ring[128];
1817char *endring;
1818
1819static void
1820initring(void)
1821{
1822	int i;
1823
1824	endring = ring;
1825
1826	for (i = 0; i <= 128; ++i)
1827		if (isprint(i))
1828			*endring++ = (char)i;
1829}
1830
1831/* ARGSUSED */
1832static void
1833chargen_stream(int s, struct servtab *sep)	/* Character generator */
1834{
1835	size_t len;
1836	char *rs, text[LINESIZ+2];
1837
1838	inetd_setproctitle(sep->se_service, s);
1839
1840	if (!endring) {
1841		initring();
1842		rs = ring;
1843	}
1844
1845	text[LINESIZ] = '\r';
1846	text[LINESIZ + 1] = '\n';
1847	for (rs = ring;;) {
1848		if ((len = (size_t)(endring - rs)) >= LINESIZ)
1849			memmove(text, rs, LINESIZ);
1850		else {
1851			memmove(text, rs, len);
1852			memmove(text + len, ring, LINESIZ - len);
1853		}
1854		if (++rs == endring)
1855			rs = ring;
1856		if (write(s, text, sizeof(text)) != sizeof(text))
1857			break;
1858	}
1859}
1860
1861/* ARGSUSED */
1862static void
1863chargen_dg(int s, struct servtab *sep)		/* Character generator */
1864{
1865	struct sockaddr_storage ss;
1866	struct sockaddr *sa;
1867	static char *rs;
1868	size_t len;
1869	socklen_t size;
1870	char text[LINESIZ+2];
1871
1872	if (endring == 0) {
1873		initring();
1874		rs = ring;
1875	}
1876
1877	sa = (struct sockaddr *)(void *)&ss;
1878	size = sizeof(ss);
1879	if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
1880		return;
1881
1882	if (!port_good_dg(sa))
1883		return;
1884
1885	if ((len = (size_t)(endring - rs)) >= LINESIZ)
1886		memmove(text, rs, LINESIZ);
1887	else {
1888		memmove(text, rs, len);
1889		memmove(text + len, ring, LINESIZ - len);
1890	}
1891	if (++rs == endring)
1892		rs = ring;
1893	text[LINESIZ] = '\r';
1894	text[LINESIZ + 1] = '\n';
1895	(void) sendto(s, text, sizeof(text), 0, sa, size);
1896}
1897
1898/*
1899 * Return a machine readable date and time, in the form of the
1900 * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1901 * returns the number of seconds since midnight, Jan 1, 1970,
1902 * we must add 2208988800 seconds to this figure to make up for
1903 * some seventy years Bell Labs was asleep.
1904 */
1905
1906static uint32_t
1907machtime(void)
1908{
1909	struct timeval tv;
1910
1911	if (gettimeofday(&tv, NULL) < 0) {
1912		DPRINTF("Unable to get time of day");
1913		return (0);
1914	}
1915#define	OFFSET ((uint32_t)25567 * 24*60*60)
1916	return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1917#undef OFFSET
1918}
1919
1920/* ARGSUSED */
1921static void
1922machtime_stream(int s, struct servtab *sep)
1923{
1924	uint32_t result;
1925
1926	result = machtime();
1927	(void) write(s, &result, sizeof(result));
1928}
1929
1930/* ARGSUSED */
1931void
1932machtime_dg(int s, struct servtab *sep)
1933{
1934	uint32_t result;
1935	struct sockaddr_storage ss;
1936	struct sockaddr *sa;
1937	socklen_t size;
1938
1939	sa = (struct sockaddr *)(void *)&ss;
1940	size = sizeof(ss);
1941	if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0)
1942		return;
1943	if (!port_good_dg(sa))
1944		return;
1945	result = machtime();
1946	(void)sendto(s, &result, sizeof(result), 0, sa, size);
1947}
1948
1949/* ARGSUSED */
1950static void
1951daytime_stream(int s,struct servtab *sep)
1952/* Return human-readable time of day */
1953{
1954	char buffer[256];
1955	time_t clk;
1956	int len;
1957
1958	clk = time((time_t *) 0);
1959
1960	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1961	(void) write(s, buffer, (size_t)len);
1962}
1963
1964/* ARGSUSED */
1965void
1966daytime_dg(int s, struct servtab *sep)
1967/* Return human-readable time of day */
1968{
1969	char buffer[256];
1970	time_t clk;
1971	struct sockaddr_storage ss;
1972	struct sockaddr *sa;
1973	socklen_t size;
1974	int len;
1975
1976	clk = time((time_t *) 0);
1977
1978	sa = (struct sockaddr *)(void *)&ss;
1979	size = sizeof(ss);
1980	if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
1981		return;
1982	if (!port_good_dg(sa))
1983		return;
1984	len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1985	(void) sendto(s, buffer, (size_t)len, 0, sa, size);
1986}
1987
1988#ifdef DEBUG_ENABLE
1989/*
1990 * print_service:
1991 *	Dump relevant information to stderr
1992 */
1993static void
1994print_service(const char *action, struct servtab *sep)
1995{
1996
1997	if (isrpcservice(sep))
1998		fprintf(stderr,
1999		    "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
2000#ifdef IPSEC
2001		    " policy=\"%s\""
2002#endif
2003		    "\n",
2004		    action, sep->se_service,
2005		    sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
2006		    sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2007		    (long)sep->se_bi, sep->se_server
2008#ifdef IPSEC
2009		    , (sep->se_policy ? sep->se_policy : "")
2010#endif
2011		    );
2012	else
2013		fprintf(stderr,
2014		    "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
2015#ifdef IPSEC
2016		    " policy=%s"
2017#endif
2018		    "\n",
2019		    action, sep->se_hostaddr, sep->se_service,
2020		    sep->se_type == FAITH_TYPE ? "faith/" : "",
2021		    sep->se_proto,
2022		    sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2023		    (long)sep->se_bi, sep->se_server
2024#ifdef IPSEC
2025		    , (sep->se_policy ? sep->se_policy : "")
2026#endif
2027		    );
2028}
2029#endif
2030
2031static void
2032usage(void)
2033{
2034#ifdef LIBWRAP
2035	(void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2036#else
2037	(void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2038#endif
2039	exit(EXIT_FAILURE);
2040}
2041
2042
2043/*
2044 *  Based on TCPMUX.C by Mark K. Lottor November 1988
2045 *  sri-nic::ps:<mkl>tcpmux.c
2046 */
2047
2048static int		/* # of characters upto \r,\n or \0 */
2049get_line(int fd,	char *buf, int len)
2050{
2051	int count = 0;
2052	ssize_t n;
2053
2054	do {
2055		n = read(fd, buf, (size_t)(len - count));
2056		if (n == 0)
2057			return (count);
2058		if (n < 0)
2059			return (-1);
2060		while (--n >= 0) {
2061			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2062				return (count);
2063			count++;
2064			buf++;
2065		}
2066	} while (count < len);
2067	return (count);
2068}
2069
2070#define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
2071
2072#define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
2073
2074static void
2075tcpmux(int ctrl, struct servtab *sep)
2076{
2077	char service[MAX_SERV_LEN+1];
2078	int len;
2079
2080	/* Get requested service name */
2081	if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) {
2082		strwrite(ctrl, "-Error reading service name\r\n");
2083		goto reject;
2084	}
2085	service[len] = '\0';
2086
2087	DPRINTF("tcpmux: %s: service requested", service);
2088
2089	/*
2090	 * Help is a required command, and lists available services,
2091	 * one per line.
2092	 */
2093	if (!strcasecmp(service, "help")) {
2094		strwrite(ctrl, "+Available services:\r\n");
2095		strwrite(ctrl, "help\r\n");
2096		for (sep = servtab; sep != NULL; sep = sep->se_next) {
2097			if (!ISMUX(sep))
2098				continue;
2099			(void)write(ctrl, sep->se_service,
2100			    strlen(sep->se_service));
2101			strwrite(ctrl, "\r\n");
2102		}
2103		goto reject;
2104	}
2105
2106	/* Try matching a service in inetd.conf with the request */
2107	for (sep = servtab; sep != NULL; sep = sep->se_next) {
2108		if (!ISMUX(sep))
2109			continue;
2110		if (!strcasecmp(service, sep->se_service)) {
2111			if (ISMUXPLUS(sep))
2112				strwrite(ctrl, "+Go\r\n");
2113			run_service(ctrl, sep, 1 /* forked */);
2114			return;
2115		}
2116	}
2117	strwrite(ctrl, "-Service not available\r\n");
2118reject:
2119	_exit(EXIT_FAILURE);
2120}
2121
2122/*
2123 * check if the address/port where send data to is one of the obvious ports
2124 * that are used for denial of service attacks like two echo ports
2125 * just echoing data between them
2126 */
2127static int
2128port_good_dg(struct sockaddr *sa)
2129{
2130	struct in_addr in;
2131	struct sockaddr_in *sin;
2132#ifdef INET6
2133	struct in6_addr *in6;
2134	struct sockaddr_in6 *sin6;
2135#endif
2136	u_int16_t port;
2137	int i;
2138	char hbuf[NI_MAXHOST];
2139
2140	switch (sa->sa_family) {
2141	case AF_INET:
2142		sin = (struct sockaddr_in *)(void *)sa;
2143		in.s_addr = ntohl(sin->sin_addr.s_addr);
2144		port = ntohs(sin->sin_port);
2145#ifdef INET6
2146	v4chk:
2147#endif
2148		if (IN_MULTICAST(in.s_addr))
2149			goto bad;
2150		switch ((in.s_addr & 0xff000000) >> 24) {
2151		case 0: case 127: case 255:
2152			goto bad;
2153		}
2154		if (dg_broadcast(&in))
2155			goto bad;
2156		break;
2157#ifdef INET6
2158	case AF_INET6:
2159		sin6 = (struct sockaddr_in6 *)(void *)sa;
2160		in6 = &sin6->sin6_addr;
2161		port = ntohs(sin6->sin6_port);
2162		if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
2163			goto bad;
2164		if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
2165			memcpy(&in, &in6->s6_addr[12], sizeof(in));
2166			in.s_addr = ntohl(in.s_addr);
2167			goto v4chk;
2168		}
2169		break;
2170#endif
2171	default:
2172		/* XXX unsupported af, is it safe to assume it to be safe? */
2173		return (1);
2174	}
2175
2176	for (i = 0; bad_ports[i] != 0; i++) {
2177		if (port == bad_ports[i])
2178			goto bad;
2179	}
2180
2181	return (1);
2182
2183bad:
2184	if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
2185	    niflags) != 0)
2186		strlcpy(hbuf, "?", sizeof(hbuf));
2187	syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2188		hbuf, port);
2189	return (0);
2190}
2191
2192/* XXX need optimization */
2193static int
2194dg_broadcast(struct in_addr *in)
2195{
2196	struct ifaddrs *ifa, *ifap;
2197	struct sockaddr_in *sin;
2198
2199	if (getifaddrs(&ifap) < 0)
2200		return (0);
2201	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2202		if (ifa->ifa_addr->sa_family != AF_INET ||
2203		    (ifa->ifa_flags & IFF_BROADCAST) == 0)
2204			continue;
2205		sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
2206		if (sin->sin_addr.s_addr == in->s_addr) {
2207			freeifaddrs(ifap);
2208			return (1);
2209		}
2210	}
2211	freeifaddrs(ifap);
2212	return (0);
2213}
2214
2215static int
2216my_kevent(const struct kevent *changelist, size_t nchanges,
2217    struct kevent *eventlist, size_t nevents)
2218{
2219	int	result;
2220
2221	while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2222	    NULL)) < 0)
2223		if (errno != EINTR) {
2224			syslog(LOG_ERR, "kevent: %m");
2225			exit(EXIT_FAILURE);
2226		}
2227
2228	return (result);
2229}
2230
2231static struct kevent *
2232allocchange(void)
2233{
2234	if (changes == __arraycount(changebuf)) {
2235		(void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0);
2236		changes = 0;
2237	}
2238
2239	return (&changebuf[changes++]);
2240}
2241
2242static void
2243config_root(void)
2244{
2245	struct servtab *sep;
2246	/* Uncheck services */
2247	for (sep = servtab; sep != NULL; sep = sep->se_next) {
2248		sep->se_checked = 0;
2249	}
2250	defhost = newstr("*");
2251#ifdef IPSEC
2252	policy = NULL;
2253#endif
2254	fconfig = NULL;
2255	config();
2256	purge_unchecked();
2257}
2258
2259static void
2260purge_unchecked(void)
2261{
2262	struct servtab *sep, **sepp = &servtab;
2263	int servtab_count = 0;
2264	while ((sep = *sepp) != NULL) {
2265		if (sep->se_checked) {
2266			sepp = &sep->se_next;
2267			servtab_count++;
2268			continue;
2269		}
2270		*sepp = sep->se_next;
2271		if (sep->se_fd >= 0)
2272			close_sep(sep);
2273		if (isrpcservice(sep))
2274			unregister_rpc(sep);
2275		if (sep->se_family == AF_LOCAL)
2276			(void)unlink(sep->se_service);
2277#ifdef DEBUG_ENABLE
2278		if (debug)
2279			print_service("FREE", sep);
2280#endif
2281		freeconfig(sep);
2282		free(sep);
2283	}
2284	DPRINTF("%d service(s) loaded.", servtab_count);
2285}
2286
2287static bool
2288is_same_service(const struct servtab *sep, const struct servtab *cp)
2289{
2290	return
2291	    strcmp(sep->se_service, cp->se_service) == 0 &&
2292	    strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
2293	    strcmp(sep->se_proto, cp->se_proto) == 0 &&
2294	    sep->se_family == cp->se_family &&
2295	    ISMUX(sep) == ISMUX(cp);
2296}
2297
2298int
2299parse_protocol(struct servtab *sep)
2300{
2301	int val;
2302
2303	if (strcmp(sep->se_proto, "unix") == 0) {
2304		sep->se_family = AF_LOCAL;
2305	} else {
2306		val = (int)strlen(sep->se_proto);
2307		if (!val) {
2308			ERR("%s: invalid protocol specified",
2309			    sep->se_service);
2310			return -1;
2311		}
2312		val = sep->se_proto[val - 1];
2313		switch (val) {
2314		case '4':	/*tcp4 or udp4*/
2315			sep->se_family = AF_INET;
2316			break;
2317#ifdef INET6
2318		case '6':	/*tcp6 or udp6*/
2319			sep->se_family = AF_INET6;
2320			break;
2321#endif
2322		default:
2323			/* Use 'default' IP version which is IPv4, may eventually be
2324			 * changed to AF_INET6 */
2325			sep->se_family = AF_INET;
2326			break;
2327		}
2328		if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
2329#ifdef RPC
2330			char *cp1, *ccp;
2331			cp1 = strchr(sep->se_service, '/');
2332			if (cp1 == 0) {
2333				ERR("%s: no rpc version",
2334				    sep->se_service);
2335				return -1;
2336			}
2337			*cp1++ = '\0';
2338			sep->se_rpcversl = sep->se_rpcversh =
2339			    (int)strtol(cp1, &ccp, 0);
2340			if (ccp == cp1) {
2341		badafterall:
2342				ERR("%s/%s: bad rpc version",
2343				    sep->se_service, cp1);
2344				return -1;
2345			}
2346			if (*ccp == '-') {
2347				cp1 = ccp + 1;
2348				sep->se_rpcversh = (int)strtol(cp1, &ccp, 0);
2349				if (ccp == cp1)
2350					goto badafterall;
2351			}
2352#else
2353			ERR("%s: rpc services not supported",
2354			    sep->se_service);
2355			return -1;
2356#endif /* RPC */
2357		}
2358	}
2359	return 0;
2360}
2361
2362int
2363parse_wait(struct servtab *sep, int wait)
2364{
2365	if (!ISMUX(sep)) {
2366		sep->se_wait = wait;
2367		return 0;
2368	}
2369	/*
2370	 * Silently enforce "nowait" for TCPMUX services since
2371	 * they don't have an assigned port to listen on.
2372	 */
2373	sep->se_wait = 0;
2374
2375	if (strncmp(sep->se_proto, "tcp", 3)) {
2376		ERR("bad protocol for tcpmux service %s",
2377			sep->se_service);
2378		return -1;
2379	}
2380	if (sep->se_socktype != SOCK_STREAM) {
2381		ERR("bad socket type for tcpmux service %s",
2382		    sep->se_service);
2383		return -1;
2384	}
2385	return 0;
2386}
2387
2388int
2389parse_server(struct servtab *sep, const char *arg){
2390	sep->se_server = newstr(arg);
2391	if (strcmp(sep->se_server, "internal") != 0) {
2392		sep->se_bi = NULL;
2393		return 0;
2394	}
2395	struct biltin *bi;
2396
2397	for (bi = biltins; bi->bi_service; bi++)
2398		if (bi->bi_socktype == sep->se_socktype &&
2399		    strcmp(bi->bi_service, sep->se_service) == 0)
2400			break;
2401	if (bi->bi_service == NULL) {
2402		ERR("Internal service %s unknown",
2403		    sep->se_service);
2404		return -1;
2405	}
2406	sep->se_bi = bi;
2407	sep->se_wait = bi->bi_wait;
2408	return 0;
2409}
2410
2411/* TODO test to make sure accept filter still works */
2412void
2413parse_accept_filter(char *arg, struct servtab *sep) {
2414	char *accf, *accf_arg;
2415	/* one and only one accept filter */
2416	accf = strchr(arg, ':');
2417	if (!accf)
2418		return;
2419	if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') {
2420		/* more than one ||  nothing beyond */
2421		sep->se_socktype = -1;
2422		return;
2423	}
2424
2425	accf++;			/* skip delimiter */
2426	strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name));
2427	accf_arg = strchr(accf, ',');
2428	if (!accf_arg)		/* zero or one arg, no more */
2429		return;
2430
2431	if (strrchr(accf, ',') != accf_arg) {
2432		sep->se_socktype = -1;
2433	} else {
2434		accf_arg++;
2435		strlcpy(sep->se_accf.af_arg, accf_arg,
2436		    sizeof(sep->se_accf.af_arg));
2437	}
2438}
2439
2440void
2441parse_socktype(char* arg, struct servtab* sep)
2442{
2443	/* stream socket may have an accept filter, only check first chars */
2444	if (strncmp(arg, "stream", sizeof("stream") - 1) == 0)
2445		sep->se_socktype = SOCK_STREAM;
2446	else if (strcmp(arg, "dgram") == 0)
2447		sep->se_socktype = SOCK_DGRAM;
2448	else if (strcmp(arg, "rdm") == 0)
2449		sep->se_socktype = SOCK_RDM;
2450	else if (strcmp(arg, "seqpacket") == 0)
2451		sep->se_socktype = SOCK_SEQPACKET;
2452	else if (strcmp(arg, "raw") == 0)
2453		sep->se_socktype = SOCK_RAW;
2454	else
2455		sep->se_socktype = -1;
2456}
2457
2458static struct servtab
2459init_servtab(void)
2460{
2461	/* This does not set every field to default. See enter() as well */
2462	return (struct servtab) {
2463		/*
2464		 * Set se_max to non-zero so uninitialized value is not
2465	 	 * a valid value. Useful in v2 syntax parsing.
2466		 */
2467		.se_service_max = SERVTAB_UNSPEC_SIZE_T,
2468		.se_ip_max = SERVTAB_UNSPEC_SIZE_T,
2469		.se_wait = SERVTAB_UNSPEC_VAL,
2470		.se_socktype = SERVTAB_UNSPEC_VAL
2471		/* All other fields initialized to 0 or null */
2472	};
2473}
2474
2475/* Include directives bookkeeping structure */
2476struct file_list {
2477	/* Absolute path used for checking for circular references */
2478	char *abs;
2479	/* Pointer to the absolute path of the parent config file,
2480	 * on the stack */
2481	struct file_list *next;
2482} *file_list_head;
2483
2484static void
2485include_configs(char *pattern)
2486{
2487	/* Allocate global per-config state on the thread stack */
2488	const char* save_CONFIG;
2489	FILE	*save_fconfig;
2490	size_t	save_line_number;
2491	char    *save_defhost;
2492	struct	file_list new_file;
2493#ifdef IPSEC
2494	char *save_policy;
2495#endif
2496
2497	/* Store current globals on the stack */
2498	save_CONFIG = CONFIG;
2499	save_fconfig = fconfig;
2500	save_line_number = line_number;
2501	save_defhost = defhost;
2502	new_file.abs = realpath(CONFIG, NULL);
2503	new_file.next = file_list_head;
2504#ifdef IPSEC
2505	save_policy = policy;
2506#endif
2507	/* Put new_file at the top of the config stack */
2508	file_list_head = &new_file;
2509	read_glob_configs(pattern);
2510	free((void *)new_file.abs);
2511	/* Pop new_file off the stack */
2512	file_list_head = new_file.next;
2513
2514	/* Restore global per-config state */
2515	CONFIG = save_CONFIG;
2516	fconfig = save_fconfig;
2517	line_number = save_line_number;
2518	defhost = save_defhost;
2519#ifdef IPSEC
2520	policy = save_policy;
2521#endif
2522}
2523
2524static void
2525prepare_next_config(const char *file_name)
2526{
2527	/* Setup new state that is normally only done in main */
2528	CONFIG = file_name;
2529
2530	/* Inherit default host and IPsec policy */
2531	defhost = newstr(defhost);
2532
2533#ifdef IPSEC
2534	policy = (policy == NULL) ? NULL : newstr(policy);
2535#endif
2536}
2537
2538static void
2539read_glob_configs(char *pattern) {
2540	glob_t results;
2541	char *full_pattern;
2542	int glob_result;
2543	full_pattern = gen_file_pattern(CONFIG, pattern);
2544
2545	DPRINTCONF("Found include directive '%s'", full_pattern);
2546
2547	glob_result = glob(full_pattern, GLOB_NOSORT, glob_error, &results);
2548	switch(glob_result) {
2549	case 0:
2550		/* No glob errors */
2551		break;
2552	case GLOB_ABORTED:
2553		ERR("Error while searching for include files");
2554		break;
2555	case GLOB_NOMATCH:
2556		/* It's fine if no files were matched. */
2557		DPRINTCONF("No files matched pattern '%s'", full_pattern);
2558		break;
2559	case GLOB_NOSPACE:
2560		ERR("Error when searching for include files: %s",
2561		    strerror(errno));
2562		break;
2563	default:
2564		ERR("Unknown glob(3) error %d", errno);
2565		break;
2566	}
2567	free(full_pattern);
2568
2569	for (size_t i = 0; i < results.gl_pathc; i++) {
2570		include_matched_path(results.gl_pathv[i]);
2571	}
2572
2573	globfree(&results);
2574}
2575
2576static void
2577include_matched_path(char *glob_path)
2578{
2579	struct stat sb;
2580	char *tmp;
2581
2582	if (lstat(glob_path, &sb)) {
2583		ERR("Error calling stat on path '%s': %s", glob_path,
2584		    strerror(errno));
2585		return;
2586	}
2587
2588	if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
2589		DPRINTCONF("'%s' is not a file.", glob_path);
2590		ERR("The matched path '%s' is not a regular file", glob_path);
2591		return;
2592	}
2593
2594	DPRINTCONF("Include '%s'", glob_path);
2595
2596	if (S_ISLNK(sb.st_mode)) {
2597		tmp = glob_path;
2598		glob_path = realpath(tmp, NULL);
2599	}
2600
2601	/* Ensure the file is not being reincluded .*/
2602	if (check_no_reinclude(glob_path)) {
2603		prepare_next_config(glob_path);
2604		config();
2605	} else {
2606		DPRINTCONF("File '%s' already included in current include "
2607		    "chain", glob_path);
2608		WRN("Including file '%s' would cause a circular "
2609		    "dependency", glob_path);
2610	}
2611
2612	if (S_ISLNK(sb.st_mode)) {
2613		free(glob_path);
2614		glob_path = tmp;
2615	}
2616}
2617
2618static bool
2619check_no_reinclude(const char *glob_path)
2620{
2621	struct file_list *cur = file_list_head;
2622	char *abs_path = realpath(glob_path, NULL);
2623
2624	if (abs_path == NULL) {
2625		ERR("Error checking real path for '%s': %s",
2626			glob_path, strerror(errno));
2627		return false;
2628	}
2629
2630	DPRINTCONF("Absolute path '%s'", abs_path);
2631
2632	for (cur = file_list_head; cur != NULL; cur = cur->next) {
2633		if (strcmp(cur->abs, abs_path) == 0) {
2634			/* file included more than once */
2635			/* TODO relative or abs path for logging error? */
2636			free(abs_path);
2637			return false;
2638		}
2639	}
2640	free(abs_path);
2641	return true;
2642}
2643
2644/* Resolve the pattern relative to the config file the pattern is from  */
2645static char *
2646gen_file_pattern(const char *cur_config, const char *pattern)
2647{
2648	if (pattern[0] == '/') {
2649		/* Absolute paths don't need any normalization */
2650		return newstr(pattern);
2651	}
2652
2653	/* pattern is relative */
2654	/* Find the end of the file's directory */
2655	size_t i, last = 0;
2656	for (i = 0; cur_config[i] != '\0'; i++) {
2657		if (cur_config[i] == '/') {
2658			last = i;
2659		}
2660	}
2661
2662	if (last == 0) {
2663		/* cur_config is just a filename, pattern already correct */
2664		return newstr(pattern);
2665	}
2666
2667	/* Relativize pattern to cur_config file's directory */
2668	char *full_pattern = malloc(last + 1 + strlen(pattern) + 1);
2669	if (full_pattern == NULL) {
2670		syslog(LOG_ERR, "Out of memory.");
2671		exit(EXIT_FAILURE);
2672	}
2673	memcpy(full_pattern, cur_config, last);
2674	full_pattern[last] = '/';
2675	strcpy(&full_pattern[last + 1], pattern);
2676	return full_pattern;
2677}
2678
2679static int
2680glob_error(const char *path, int error)
2681{
2682	WRN("Error while resolving path '%s': %s", path, strerror(error));
2683	return 0;
2684}
2685
2686/* Return 0 on allow, -1 if connection should be blocked */
2687static int
2688rl_process(struct servtab *sep, int ctrl)
2689{
2690	struct se_ip_list_node *node;
2691	time_t now = 0; /* 0 prevents GCC from complaining */
2692	bool istimevalid = false;
2693	char hbuf[NI_MAXHOST];
2694
2695	DPRINTF(SERV_FMT ": processing rate-limiting",
2696	    SERV_PARAMS(sep));
2697	DPRINTF(SERV_FMT ": se_service_max "
2698	    "%zu and se_count %zu", SERV_PARAMS(sep),
2699	    sep->se_service_max, sep->se_count);
2700
2701	/* se_count is incremented if rl_process will return 0 */
2702	if (sep->se_count == 0) {
2703		now = rl_time();
2704		sep->se_time = now;
2705		istimevalid = true;
2706	}
2707
2708	if (sep->se_count >= sep->se_service_max) {
2709		if(!istimevalid) {
2710			now = rl_time();
2711			istimevalid = true;
2712		}
2713
2714		if (now - sep->se_time > CNT_INTVL) {
2715			rl_reset(sep, now);
2716		} else {
2717			syslog(LOG_ERR,
2718			    SERV_FMT ": max spawn rate (%zu in %ji seconds) "
2719			    "already met, closing until end of timeout in "
2720			    "%ju seconds",
2721			    SERV_PARAMS(sep),
2722			    sep->se_service_max,
2723			    (intmax_t)CNT_INTVL,
2724			    (uintmax_t)RETRYTIME);
2725
2726			DPRINTF(SERV_FMT ": service not started",
2727			    SERV_PARAMS(sep));
2728
2729			rl_drop_connection(sep, ctrl);
2730
2731			/* Close the server for 10 minutes */
2732			close_sep(sep);
2733			if (!timingout) {
2734				timingout = 1;
2735				alarm(RETRYTIME);
2736			}
2737
2738			return -1;
2739		}
2740	}
2741
2742	if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2743		rl_get_name(sep, ctrl, hbuf);
2744		node = rl_try_get_ip(sep, hbuf);
2745		if(node == NULL) {
2746			node = rl_add(sep, hbuf);
2747		}
2748
2749		DPRINTF(
2750		    SERV_FMT ": se_ip_max %zu and ip_count %zu",
2751		    SERV_PARAMS(sep), sep->se_ip_max, node->count);
2752
2753		if (node->count >= sep->se_ip_max) {
2754			if (!istimevalid) {
2755				/*
2756				 * Only get the clock time if we didn't
2757				 * already
2758				 */
2759				now = rl_time();
2760				istimevalid = true;
2761			}
2762
2763			if (now - sep->se_time > CNT_INTVL) {
2764				rl_reset(sep, now);
2765				node = rl_add(sep, hbuf);
2766			} else {
2767				if (debug && node->count == sep->se_ip_max) {
2768					/*
2769					 * Only log first failed request to
2770					 * prevent DoS attack writing to system
2771					 * log
2772					 */
2773					syslog(LOG_ERR, SERV_FMT
2774					    ": max ip spawn rate (%zu in "
2775					    "%ji seconds) for "
2776					    "%." TOSTRING(NI_MAXHOST) "s "
2777					    "already met; service not started",
2778					    SERV_PARAMS(sep),
2779					    sep->se_ip_max,
2780					    (intmax_t)CNT_INTVL,
2781					    node->address);
2782				}
2783
2784				DPRINTF(SERV_FMT ": service not started",
2785   				    SERV_PARAMS(sep));
2786
2787				rl_drop_connection(sep, ctrl);
2788				/*
2789				 * Increment so debug-syslog message will
2790				 * trigger only once
2791				 */
2792				node->count++;
2793				return -1;
2794			}
2795		}
2796		node->count++;
2797	}
2798
2799	DPRINTF(SERV_FMT ": running service ", SERV_PARAMS(sep));
2800
2801	sep->se_count++;
2802	return 0;
2803}
2804
2805/* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */
2806static void
2807rl_get_name(struct servtab *sep, int ctrl, char *hbuf)
2808{
2809	struct sockaddr_storage addr;
2810	socklen_t len = sizeof(struct sockaddr_storage);
2811	switch (sep->se_socktype) {
2812	case SOCK_STREAM:
2813		if (getpeername(ctrl, (struct sockaddr *)&addr, &len)) {
2814			/* error, log it and skip ip rate limiting */
2815			syslog(LOG_ERR,
2816				SERV_FMT " failed to get peer name of the "
2817				"connection", SERV_PARAMS(sep));
2818			exit(EXIT_FAILURE);
2819		}
2820		break;
2821	case SOCK_DGRAM: {
2822		struct msghdr header = {
2823			.msg_name = &addr,
2824			.msg_namelen = sizeof(struct sockaddr_storage),
2825			/* scatter/gather and control info is null */
2826		};
2827		ssize_t count;
2828
2829		/* Peek so service can still get the packet */
2830		count = recvmsg(ctrl, &header, MSG_PEEK);
2831		if (count == -1) {
2832			syslog(LOG_ERR,
2833			    "failed to get dgram source address: %s; exiting",
2834			    strerror(errno));
2835			exit(EXIT_FAILURE);
2836		}
2837		break;
2838	}
2839	default:
2840		DPRINTF(SERV_FMT ": ip_max rate limiting not supported for "
2841		    "socktype", SERV_PARAMS(sep));
2842		syslog(LOG_ERR, SERV_FMT
2843		    ": ip_max rate limiting not supported for socktype",
2844		    SERV_PARAMS(sep));
2845		exit(EXIT_FAILURE);
2846	}
2847
2848	if (getnameinfo((struct sockaddr *)&addr,
2849		addr.ss_len, hbuf,
2850		NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) {
2851		/* error, log it and skip ip rate limiting */
2852		syslog(LOG_ERR,
2853		    SERV_FMT ": failed to get name info of the incoming "
2854		    "connection; exiting",
2855		    SERV_PARAMS(sep));
2856		exit(EXIT_FAILURE);
2857	}
2858}
2859
2860static void
2861rl_drop_connection(struct servtab *sep, int ctrl)
2862{
2863
2864	if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
2865		/*
2866		 * If the fd isn't a listen socket,
2867		 * close the individual connection too.
2868		 */
2869		close(ctrl);
2870		return;
2871	}
2872	if (sep->se_socktype != SOCK_DGRAM) {
2873		return;
2874	}
2875	/*
2876	 * Drop the single datagram the service would have
2877	 * consumed if nowait. If this is a wait service, this
2878	 * will consume 1 datagram, and further received packets
2879	 * will be removed in the same way.
2880	 */
2881	struct msghdr header = {
2882		/* All fields null, just consume one message */
2883	};
2884	ssize_t count;
2885
2886	count = recvmsg(ctrl, &header, 0);
2887	if (count == -1) {
2888		syslog(LOG_ERR,
2889		    SERV_FMT ": failed to consume nowait dgram: %s",
2890		    SERV_PARAMS(sep), strerror(errno));
2891		exit(EXIT_FAILURE);
2892	}
2893	DPRINTF(SERV_FMT ": dropped dgram message",
2894	    SERV_PARAMS(sep));
2895}
2896
2897static time_t
2898rl_time(void)
2899{
2900	struct timespec time;
2901	if(clock_gettime(CLOCK_MONOTONIC, &time) == -1) {
2902		syslog(LOG_ERR, "clock_gettime for rate limiting failed: %s; "
2903		    "exiting", strerror(errno));
2904		/* Exit inetd if rate limiting fails */
2905		exit(EXIT_FAILURE);
2906	}
2907	return time.tv_sec;
2908}
2909
2910static struct se_ip_list_node*
2911rl_add(struct servtab *sep, char* ip)
2912{
2913	DPRINTF(
2914	    SERV_FMT ": add ip %s to rate limiting tracking",
2915	    SERV_PARAMS(sep), ip);
2916
2917	/*
2918	 * TODO memory could be saved by using a variable length malloc
2919	 * with only the length of ip instead of the existing address field
2920	 * NI_MAXHOST in length.
2921	 */
2922	struct se_ip_list_node* temp = malloc(sizeof(*temp));
2923	if (temp == NULL) {
2924		syslog(LOG_ERR, "Out of memory.");
2925		exit(EXIT_FAILURE);
2926	}
2927	temp->count = 0;
2928	temp->next = NULL;
2929	strlcpy(temp->address, ip, sizeof(temp->address));
2930
2931	if (sep->se_ip_list_head == NULL) {
2932		/* List empty, insert as head */
2933		sep->se_ip_list_head = temp;
2934	} else {
2935		/* List not empty, insert as head, point next to prev head */
2936		temp->next = sep->se_ip_list_head;
2937		sep->se_ip_list_head = temp;
2938	}
2939
2940	return temp;
2941}
2942
2943static void
2944rl_reset(struct servtab *sep, time_t now)
2945{
2946	DPRINTF(SERV_FMT ": %ji seconds passed; resetting rate limiting ",
2947	    SERV_PARAMS(sep), (intmax_t)(now - sep->se_time));
2948
2949	sep->se_count = 0;
2950	sep->se_time = now;
2951	if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2952		clear_ip_list(sep);
2953	}
2954}
2955
2956static void
2957clear_ip_list(struct servtab *sep) {
2958	struct se_ip_list_node *curr, *next;
2959	curr = sep->se_ip_list_head;
2960
2961	while (curr != NULL) {
2962		next = curr->next;
2963		free(curr);
2964		curr = next;
2965	}
2966	sep->se_ip_list_head = NULL;
2967}
2968
2969static struct se_ip_list_node *
2970rl_try_get_ip(struct servtab *sep, char *ip)
2971{
2972	struct se_ip_list_node *curr;
2973
2974	DPRINTF(
2975	    SERV_FMT ": look up ip %s for ip_max rate limiting",
2976	    SERV_PARAMS(sep), ip);
2977
2978	for (curr = sep->se_ip_list_head; curr != NULL; curr = curr->next) {
2979		if (!strncmp(curr->address, ip, NI_MAXHOST)) {
2980			/* IP addr match */
2981			return curr;
2982		}
2983	}
2984	return NULL;
2985}
2986