xref: /openbsd-src/usr.sbin/inetd/inetd.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: inetd.c,v 1.132 2009/11/02 20:03:01 otto Exp $	*/
2 
3 /*
4  * Copyright (c) 1983,1991 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Inetd - Internet super-server
34  *
35  * This program invokes all internet services as needed.
36  * connection-oriented services are invoked each time a
37  * connection is made, by creating a process.  This process
38  * is passed the connection as file descriptor 0 and is
39  * expected to do a getpeername to find out the source host
40  * and port.
41  *
42  * Datagram oriented services are invoked when a datagram
43  * arrives; a process is created and passed a pending message
44  * on file descriptor 0.  Datagram servers may either connect
45  * to their peer, freeing up the original socket for inetd
46  * to receive further messages on, or ``take over the socket'',
47  * processing all arriving datagrams and, eventually, timing
48  * out.	 The first type of server is said to be ``multi-threaded'';
49  * the second type of server ``single-threaded''.
50  *
51  * Inetd uses a configuration file which is read at startup
52  * and, possibly, at some later time in response to a hangup signal.
53  * The configuration file is ``free format'' with fields given in the
54  * order shown below.  Continuation lines for an entry must begin with
55  * a space or tab.  All fields must be present in each entry.
56  *
57  *	service name			must be in /etc/services
58  *	socket type			stream/dgram/raw/rdm/seqpacket
59  *	protocol			must be in /etc/protocols
60  *	wait/nowait[.max]		single-threaded/multi-threaded, max #
61  *	user[.group] or user[:group]	user/group to run daemon as
62  *	server program			full path name
63  *	server program arguments	maximum of MAXARGS (20)
64  *
65  * For RPC services
66  *      service name/version            must be in /etc/rpc
67  *	socket type			stream/dgram/raw/rdm/seqpacket
68  *	protocol			must be in /etc/protocols
69  *	wait/nowait[.max]		single-threaded/multi-threaded
70  *	user[.group] or user[:group]	user to run daemon as
71  *	server program			full path name
72  *	server program arguments	maximum of MAXARGS (20)
73  *
74  * For non-RPC services, the "service name" can be of the form
75  * hostaddress:servicename, in which case the hostaddress is used
76  * as the host portion of the address to listen on.  If hostaddress
77  * consists of a single `*' character, INADDR_ANY is used.
78  *
79  * A line can also consist of just
80  *      hostaddress:
81  * where hostaddress is as in the preceding paragraph.  Such a line must
82  * have no further fields; the specified hostaddress is remembered and
83  * used for all further lines that have no hostaddress specified,
84  * until the next such line (or EOF).  (This is why * is provided to
85  * allow explicit specification of INADDR_ANY.)  A line
86  *      *:
87  * is implicitly in effect at the beginning of the file.
88  *
89  * The hostaddress specifier may (and often will) contain dots;
90  * the service name must not.
91  *
92  * For RPC services, host-address specifiers are accepted and will
93  * work to some extent; however, because of limitations in the
94  * portmapper interface, it will not work to try to give more than
95  * one line for any given RPC service, even if the host-address
96  * specifiers are different.
97  *
98  * Comment lines are indicated by a `#' in column 1.
99  */
100 
101 /*
102  * Here's the scoop concerning the user[.:]group feature:
103  *
104  * 1) set-group-option off.
105  *
106  *	a) user = root:	NO setuid() or setgid() is done
107  *
108  *	b) other:	setgid(primary group as found in passwd)
109  *			initgroups(name, primary group)
110  *			setuid()
111  *
112  * 2) set-group-option on.
113  *
114  *	a) user = root:	setgid(specified group)
115  *			NO initgroups()
116  *			NO setuid()
117  *
118  *	b) other:	setgid(specified group)
119  *			initgroups(name, specified group)
120  *			setuid()
121  *
122  */
123 
124 #include <sys/param.h>
125 #include <sys/stat.h>
126 #include <sys/ioctl.h>
127 #include <sys/socket.h>
128 #include <sys/un.h>
129 #include <sys/file.h>
130 #include <sys/wait.h>
131 #include <sys/time.h>
132 #include <sys/resource.h>
133 
134 #include <net/if.h>
135 #include <netinet/in.h>
136 #include <arpa/inet.h>
137 
138 #include <errno.h>
139 #include <ctype.h>
140 #include <signal.h>
141 #include <netdb.h>
142 #include <syslog.h>
143 #include <pwd.h>
144 #include <grp.h>
145 #include <stdio.h>
146 #include <stdlib.h>
147 #include <unistd.h>
148 #include <string.h>
149 #include <login_cap.h>
150 #include <ifaddrs.h>
151 #include <rpc/rpc.h>
152 #include <rpc/pmap_clnt.h>
153 #include <rpcsvc/nfs_prot.h>
154 #include "pathnames.h"
155 
156 #define	TOOMANY		256		/* don't start more than TOOMANY */
157 #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
158 #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
159 
160 int	 debug = 0;
161 int	 nsock, maxsock;
162 fd_set	*allsockp;
163 int	 allsockn;
164 int	 toomany = TOOMANY;
165 int	 options;
166 int	 timingout;
167 struct	 servent *sp;
168 uid_t	 uid;
169 sigset_t blockmask;
170 sigset_t emptymask;
171 
172 #ifndef OPEN_MAX
173 #define OPEN_MAX	64
174 #endif
175 
176 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
177 #define FD_MARGIN	(8)
178 rlim_t	rlim_nofile_cur = OPEN_MAX;
179 
180 struct rlimit	rlim_nofile;
181 
182 struct	servtab {
183 	char	*se_hostaddr;		/* host address to listen on */
184 	char	*se_service;		/* name of service */
185 	int	se_socktype;		/* type of socket to use */
186 	int	se_family;		/* address family */
187 	char	*se_proto;		/* protocol used */
188 	int	se_rpcprog;		/* rpc program number */
189 	int	se_rpcversl;		/* rpc program lowest version */
190 	int	se_rpcversh;		/* rpc program highest version */
191 #define isrpcservice(sep)	((sep)->se_rpcversl != 0)
192 	pid_t	se_wait;		/* single threaded server */
193 	short	se_checked;		/* looked at during merge */
194 	char	*se_user;		/* user name to run as */
195 	char	*se_group;		/* group name to run as */
196 	struct	biltin *se_bi;		/* if built-in, description */
197 	char	*se_server;		/* server program */
198 #define	MAXARGV 20
199 	char	*se_argv[MAXARGV+1];	/* program arguments */
200 	int	se_fd;			/* open descriptor */
201 	union {
202 		struct	sockaddr se_un_ctrladdr;
203 		struct	sockaddr_in se_un_ctrladdr_in;
204 		struct	sockaddr_in6 se_un_ctrladdr_in6;
205 		struct	sockaddr_un se_un_ctrladdr_un;
206 		struct	sockaddr_storage se_un_ctrladdr_storage;
207 	} se_un;			/* bound address */
208 #define se_ctrladdr	se_un.se_un_ctrladdr
209 #define se_ctrladdr_in	se_un.se_un_ctrladdr_in
210 #define se_ctrladdr_in6	se_un.se_un_ctrladdr_in6
211 #define se_ctrladdr_un	se_un.se_un_ctrladdr_un
212 #define se_ctrladdr_storage	se_un.se_un_ctrladdr_storage
213 	int	se_ctrladdr_size;
214 	int	se_max;			/* max # of instances of this service */
215 	int	se_count;		/* number started since se_time */
216 	struct	timeval se_time;	/* start of se_count */
217 	struct	servtab *se_next;
218 } *servtab;
219 
220 void echo_stream(int, struct servtab *);
221 void discard_stream(int, struct servtab *);
222 void machtime_stream(int, struct servtab *);
223 void daytime_stream(int, struct servtab *);
224 void chargen_stream(int, struct servtab *);
225 void echo_dg(int, struct servtab *);
226 void discard_dg(int, struct servtab *);
227 void machtime_dg(int, struct servtab *);
228 void daytime_dg(int, struct servtab *);
229 void chargen_dg(int, struct servtab *);
230 
231 struct biltin {
232 	char	*bi_service;		/* internally provided service name */
233 	int	bi_socktype;		/* type of socket supported */
234 	short	bi_fork;		/* 1 if should fork before call */
235 	short	bi_wait;		/* 1 if should wait for child */
236 	void	(*bi_fn)(int, struct servtab *);
237 } biltins[] = {
238 	/* Echo received data */
239 	{ "echo",	SOCK_STREAM,	1, 0,	echo_stream },
240 	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg },
241 
242 	/* Internet /dev/null */
243 	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream },
244 	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg },
245 
246 	/* Return 32 bit time since 1900 */
247 	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream },
248 	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg },
249 
250 	/* Return human-readable time */
251 	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream },
252 	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg },
253 
254 	/* Familiar character generator */
255 	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream },
256 	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg },
257 
258 	{ 0 }
259 };
260 
261 volatile sig_atomic_t wantretry;
262 volatile sig_atomic_t wantconfig;
263 volatile sig_atomic_t wantreap;
264 volatile sig_atomic_t wantdie;
265 
266 void	config(int);
267 void	doconfig(void);
268 void	reap(int);
269 void	doreap(void);
270 void	retry(int);
271 void	doretry(void);
272 void	die(int);
273 void	dodie(void);
274 void	logpid(void);
275 void	spawn(struct servtab *, int);
276 int	gettcp(struct servtab *);
277 int	setconfig(void);
278 void	endconfig(void);
279 void	register_rpc(struct servtab *);
280 void	unregister_rpc(struct servtab *);
281 void	freeconfig(struct servtab *);
282 void	print_service(char *, struct servtab *);
283 void	setup(struct servtab *);
284 struct servtab *getconfigent(void);
285 int	bump_nofile(void);
286 struct servtab *enter(struct servtab *);
287 int	matchconf(struct servtab *, struct servtab *);
288 int	dg_broadcast(struct in_addr *in);
289 
290 #define NUMINT	(sizeof(intab) / sizeof(struct inent))
291 char	*CONFIG = _PATH_INETDCONF;
292 
293 void
294 fd_grow(fd_set **fdsp, int *bytes, int fd)
295 {
296 	caddr_t new;
297 	int newbytes;
298 
299 	newbytes = howmany(fd+1, NFDBITS) * sizeof(fd_mask);
300 	if (newbytes > *bytes) {
301 		newbytes *= 2;			/* optimism */
302 		new = realloc(*fdsp, newbytes);
303 		if (new == NULL) {
304 			syslog(LOG_ERR, "Out of memory.");
305 			exit(1);
306 		}
307 		memset(new + *bytes, 0, newbytes - *bytes);
308 		*fdsp = (fd_set *)new;
309 		*bytes = newbytes;
310 	}
311 }
312 
313 struct sigaction sa, sapipe;
314 
315 int
316 main(int argc, char *argv[])
317 {
318 	fd_set *fdsrp = NULL;
319 	int readablen = 0, ch;
320 	struct servtab *sep;
321 	extern char *optarg;
322 	extern int optind;
323 
324 	while ((ch = getopt(argc, argv, "dR:")) != -1)
325 		switch (ch) {
326 		case 'd':
327 			debug = 1;
328 			options |= SO_DEBUG;
329 			break;
330 		case 'R': {	/* invocation rate */
331 			char *p;
332 			int val;
333 
334 			val = strtoul(optarg, &p, 0);
335 			if (val >= 1 && *p == '\0') {
336 				toomany = val;
337 				break;
338 			}
339 			syslog(LOG_ERR,
340 			    "-R %s: bad value for service invocation rate",
341 			    optarg);
342 			break;
343 		}
344 		case '?':
345 		default:
346 			fprintf(stderr,
347 			    "usage: inetd [-d] [-R rate] [configuration_file]\n");
348 			exit(1);
349 		}
350 	argc -= optind;
351 	argv += optind;
352 
353 	uid = getuid();
354 	if (uid != 0)
355 		CONFIG = NULL;
356 	if (argc > 0)
357 		CONFIG = argv[0];
358 	if (CONFIG == NULL) {
359 		fprintf(stderr, "inetd: non-root must specify a config file\n");
360 		exit(1);
361 	}
362 	if (argc > 1) {
363 		fprintf(stderr, "inetd: more than one argument specified\n");
364 		exit(1);
365 	}
366 
367 	umask(022);
368 	if (debug == 0) {
369 		daemon(0, 0);
370 		if (uid == 0)
371 			(void) setlogin("");
372 	}
373 
374 	if (uid == 0) {
375 		gid_t gid = getgid();
376 
377 		/* If run by hand, ensure groups vector gets trashed */
378 		setgroups(1, &gid);
379 	}
380 
381 	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
382 	logpid();
383 
384 	if (getrlimit(RLIMIT_NOFILE, &rlim_nofile) < 0) {
385 		syslog(LOG_ERR, "getrlimit: %m");
386 	} else {
387 		rlim_nofile_cur = rlim_nofile.rlim_cur;
388 		if (rlim_nofile_cur == RLIM_INFINITY)	/* ! */
389 			rlim_nofile_cur = OPEN_MAX;
390 	}
391 
392 	sigemptyset(&emptymask);
393 	sigemptyset(&blockmask);
394 	sigaddset(&blockmask, SIGCHLD);
395 	sigaddset(&blockmask, SIGHUP);
396 	sigaddset(&blockmask, SIGALRM);
397 
398 	memset(&sa, 0, sizeof(sa));
399 	sigemptyset(&sa.sa_mask);
400 	sigaddset(&sa.sa_mask, SIGALRM);
401 	sigaddset(&sa.sa_mask, SIGCHLD);
402 	sigaddset(&sa.sa_mask, SIGHUP);
403 	sa.sa_handler = retry;
404 	sigaction(SIGALRM, &sa, NULL);
405 	doconfig();
406 	sa.sa_handler = config;
407 	sigaction(SIGHUP, &sa, NULL);
408 	sa.sa_handler = reap;
409 	sigaction(SIGCHLD, &sa, NULL);
410 	sa.sa_handler = die;
411 	sigaction(SIGTERM, &sa, NULL);
412 	sa.sa_handler = die;
413 	sigaction(SIGINT, &sa, NULL);
414 	sa.sa_handler = SIG_IGN;
415 	sigaction(SIGPIPE, &sa, &sapipe);
416 
417 	for (;;) {
418 		int n, ctrl = -1;
419 
420 	    restart:
421 		if (nsock == 0) {
422 			(void) sigprocmask(SIG_BLOCK, &blockmask, NULL);
423 			while (nsock == 0) {
424 				if (wantretry || wantconfig || wantreap || wantdie)
425 					break;
426 				sigsuspend(&emptymask);
427 			}
428 			(void) sigprocmask(SIG_SETMASK, &emptymask, NULL);
429 		}
430 
431 		while (wantretry || wantconfig || wantreap || wantdie) {
432 			if (wantretry) {
433 				wantretry = 0;
434 				doretry();
435 			}
436 			if (wantconfig) {
437 				wantconfig = 0;
438 				doconfig();
439 			}
440 			if (wantreap) {
441 				wantreap = 0;
442 				doreap();
443 			}
444 			if (wantdie)
445 				dodie();
446 			goto restart;
447 		}
448 
449 		if (readablen != allsockn) {
450 			if (fdsrp)
451 				free(fdsrp);
452 			fdsrp = (fd_set *)calloc(allsockn, 1);
453 			if (fdsrp == NULL) {
454 				syslog(LOG_ERR, "Out of memory.");
455 				exit(1);
456 			}
457 			readablen = allsockn;
458 		}
459 		bcopy(allsockp, fdsrp, allsockn);
460 
461 		if ((n = select(maxsock + 1, fdsrp, NULL, NULL, NULL)) <= 0) {
462 			if (n < 0 && errno != EINTR) {
463 				syslog(LOG_WARNING, "select: %m");
464 				sleep(1);
465 			}
466 			continue;
467 		}
468 
469 		for (sep = servtab; n && sep; sep = sep->se_next) {
470 			if (sep->se_fd != -1 &&
471 			    FD_ISSET(sep->se_fd, fdsrp)) {
472 				n--;
473 				if (debug)
474 					fprintf(stderr, "someone wants %s\n",
475 					    sep->se_service);
476 				if (!sep->se_wait &&
477 				    sep->se_socktype == SOCK_STREAM) {
478 					ctrl = gettcp(sep);
479 					if (ctrl == -1)
480 						continue;
481 				} else
482 					ctrl = sep->se_fd;
483 				(void) sigprocmask(SIG_BLOCK, &blockmask, NULL);
484 				spawn(sep, ctrl);	/* spawn will unblock */
485 			}
486 		}
487 	}
488 }
489 
490 int
491 gettcp(struct servtab *sep)
492 {
493 	int ctrl;
494 
495 	ctrl = accept(sep->se_fd, NULL, NULL);
496 	if (debug)
497 		fprintf(stderr, "accept, ctrl %d\n", ctrl);
498 	if (ctrl < 0) {
499 		if (errno == EINTR)
500 			return -1;
501 		syslog(LOG_WARNING, "accept (for %s): %m", sep->se_service);
502 		return -1;
503 	}
504 	if ((sep->se_family == AF_INET || sep->se_family == AF_INET6) &&
505 	    sep->se_socktype == SOCK_STREAM) {
506 		struct sockaddr_storage peer;
507 		socklen_t plen = sizeof(peer);
508 		char sbuf[NI_MAXSERV];
509 
510 		if (getpeername(ctrl, (struct sockaddr *)&peer, &plen) < 0) {
511 			syslog(LOG_WARNING, "could not getpeername");
512 			close(ctrl);
513 			return -1;
514 		}
515 		if (getnameinfo((struct sockaddr *)&peer, plen, NULL, 0,
516 		    sbuf, sizeof(sbuf), NI_NUMERICSERV) == 0 &&
517 		    atoi(sbuf) == 20) {
518 			/*
519 			 * ignore things that look like ftp bounce
520 			 */
521 			close(ctrl);
522 			return -1;
523 		}
524 	}
525 	return (ctrl);
526 }
527 
528 
529 int
530 dg_badinput(struct sockaddr *sa)
531 {
532 	struct in_addr in;
533 	struct in6_addr *in6;
534 	u_int16_t port;
535 
536 	switch (sa->sa_family) {
537 	case AF_INET:
538 		in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
539 		port = ntohs(((struct sockaddr_in *)sa)->sin_port);
540 	v4chk:
541 		if (IN_MULTICAST(in.s_addr))
542 			goto bad;
543 		switch ((in.s_addr & 0xff000000) >> 24) {
544 		case 0: case 127: case 255:
545 			goto bad;
546 		}
547 		if (dg_broadcast(&in))
548 			goto bad;
549 		break;
550 	case AF_INET6:
551 		in6 = &((struct sockaddr_in6 *)sa)->sin6_addr;
552 		port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
553 		if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
554 			goto bad;
555 		/*
556 		 * OpenBSD does not support IPv4 mapped address (RFC2553
557 		 * inbound behavior) at all.  We should drop it.
558 		 */
559 		if (IN6_IS_ADDR_V4MAPPED(in6))
560 			goto bad;
561 		if (IN6_IS_ADDR_V4COMPAT(in6)) {
562 			memcpy(&in, &in6->s6_addr[12], sizeof(in));
563 			in.s_addr = ntohl(in.s_addr);
564 			goto v4chk;
565 		}
566 		break;
567 	default:
568 		/* XXX unsupported af, is it safe to assume it to be safe? */
569 		return 0;
570 	}
571 
572 	if (port < IPPORT_RESERVED || port == NFS_PORT)
573 		goto bad;
574 
575 	return (0);
576 
577 bad:
578 	return (1);
579 }
580 
581 int
582 dg_broadcast(struct in_addr *in)
583 {
584 	struct ifaddrs *ifa, *ifap;
585 	struct sockaddr_in *sin;
586 
587 	if (getifaddrs(&ifap) < 0)
588 		return (0);
589 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
590 		if (ifa->ifa_addr->sa_family != AF_INET ||
591 		    (ifa->ifa_flags & IFF_BROADCAST) == 0)
592 			continue;
593 		sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
594 		if (sin->sin_addr.s_addr == in->s_addr) {
595 			freeifaddrs(ifap);
596 			return (1);
597 		}
598 	}
599 	freeifaddrs(ifap);
600 	return (0);
601 }
602 
603 /* ARGSUSED */
604 void
605 reap(int sig)
606 {
607 	wantreap = 1;
608 }
609 
610 void
611 doreap(void)
612 {
613 	struct servtab *sep;
614 	int status;
615 	pid_t pid;
616 
617 	if (debug)
618 		fprintf(stderr, "reaping asked for\n");
619 
620 	for (;;) {
621 		if ((pid = wait3(&status, WNOHANG, NULL)) <= 0) {
622 			if (pid == -1 && errno == EINTR)
623 				continue;
624 			break;
625 		}
626 		if (debug)
627 			fprintf(stderr, "%ld reaped, status %x\n",
628 			    (long)pid, status);
629 		for (sep = servtab; sep; sep = sep->se_next)
630 			if (sep->se_wait == pid) {
631 				if (WIFEXITED(status) && WEXITSTATUS(status))
632 					syslog(LOG_WARNING,
633 					    "%s: exit status %d",
634 					    sep->se_server, WEXITSTATUS(status));
635 				else if (WIFSIGNALED(status))
636 					syslog(LOG_WARNING,
637 					    "%s: exit signal %d",
638 					    sep->se_server, WTERMSIG(status));
639 				sep->se_wait = 1;
640 				fd_grow(&allsockp, &allsockn, sep->se_fd);
641 				FD_SET(sep->se_fd, allsockp);
642 				nsock++;
643 				if (debug)
644 					fprintf(stderr, "restored %s, fd %d\n",
645 					    sep->se_service, sep->se_fd);
646 			}
647 	}
648 }
649 
650 /* ARGSUSED */
651 void
652 config(int sig)
653 {
654 	wantconfig = 1;
655 }
656 
657 void
658 doconfig(void)
659 {
660 	struct servtab *sep, *cp, **sepp;
661 	int add;
662 	char protoname[10];
663 	sigset_t omask;
664 
665 	if (!setconfig()) {
666 		syslog(LOG_ERR, "%s: %m", CONFIG);
667 		exit(1);
668 	}
669 	for (sep = servtab; sep; sep = sep->se_next)
670 		sep->se_checked = 0;
671 	cp = getconfigent();
672 	while (cp != NULL) {
673 		for (sep = servtab; sep; sep = sep->se_next)
674 			if (matchconf(sep, cp))
675 				break;
676 		add = 0;
677 		if (sep != NULL) {
678 			int i;
679 
680 #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;}
681 
682 			sigprocmask(SIG_BLOCK, &blockmask, &omask);
683 			/*
684 			 * sep->se_wait may be holding the pid of a daemon
685 			 * that we're waiting for.  If so, don't overwrite
686 			 * it unless the config file explicitly says don't
687 			 * wait.
688 			 */
689 			if (cp->se_bi == 0 &&
690 			    (sep->se_wait == 1 || cp->se_wait == 0))
691 				sep->se_wait = cp->se_wait;
692 			SWAP(int, cp->se_max, sep->se_max);
693 			SWAP(char *, sep->se_user, cp->se_user);
694 			SWAP(char *, sep->se_group, cp->se_group);
695 			SWAP(char *, sep->se_server, cp->se_server);
696 			for (i = 0; i < MAXARGV; i++)
697 				SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
698 #undef SWAP
699 			if (isrpcservice(sep))
700 				unregister_rpc(sep);
701 			sep->se_rpcversl = cp->se_rpcversl;
702 			sep->se_rpcversh = cp->se_rpcversh;
703 			sigprocmask(SIG_SETMASK, &omask, NULL);
704 			freeconfig(cp);
705 			add = 1;
706 		} else {
707 			sep = enter(cp);
708 		}
709 		sep->se_checked = 1;
710 
711 		switch (sep->se_family) {
712 		case AF_UNIX:
713 			if (sep->se_fd != -1)
714 				break;
715 			sep->se_ctrladdr_size =
716 			    strlcpy(sep->se_ctrladdr_un.sun_path,
717 			    sep->se_service,
718 			    sizeof sep->se_ctrladdr_un.sun_path);
719 			if (sep->se_ctrladdr_size >=
720 			    sizeof sep->se_ctrladdr_un.sun_path) {
721 				syslog(LOG_WARNING, "%s/%s: UNIX domain socket "
722 				    "path too long", sep->se_service,
723 				    sep->se_proto);
724 				goto serv_unknown;
725 			}
726 			sep->se_ctrladdr_un.sun_family = AF_UNIX;
727 			sep->se_ctrladdr_size +=
728 			    1 + sizeof sep->se_ctrladdr_un.sun_family;
729 			(void)unlink(sep->se_service);
730 			setup(sep);
731 			break;
732 		case AF_INET:
733 			sep->se_ctrladdr_in.sin_family = AF_INET;
734 			/* se_ctrladdr_in was set in getconfigent */
735 			sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
736 
737 			if (isrpcservice(sep)) {
738 				struct rpcent *rp;
739 
740 				sep->se_rpcprog = atoi(sep->se_service);
741 				if (sep->se_rpcprog == 0) {
742 					rp = getrpcbyname(sep->se_service);
743 					if (rp == 0) {
744 						syslog(LOG_ERR,
745 						    "%s: unknown rpc service",
746 						    sep->se_service);
747 						goto serv_unknown;
748 					}
749 					sep->se_rpcprog = rp->r_number;
750 				}
751 				if (sep->se_fd == -1)
752 					setup(sep);
753 				if (sep->se_fd != -1)
754 					register_rpc(sep);
755 			} else {
756 				u_short port = htons(atoi(sep->se_service));
757 
758 				if (!port) {
759 					/* XXX */
760 					strncpy(protoname, sep->se_proto,
761 						sizeof(protoname));
762 					if (isdigit(protoname[strlen(protoname) - 1]))
763 						protoname[strlen(protoname) - 1] = '\0';
764 					sp = getservbyname(sep->se_service,
765 					    protoname);
766 					if (sp == 0) {
767 						syslog(LOG_ERR,
768 						    "%s/%s: unknown service",
769 						    sep->se_service, sep->se_proto);
770 						goto serv_unknown;
771 					}
772 					port = sp->s_port;
773 				}
774 				if (port != sep->se_ctrladdr_in.sin_port) {
775 					sep->se_ctrladdr_in.sin_port = port;
776 					if (sep->se_fd != -1) {
777 						FD_CLR(sep->se_fd, allsockp);
778 						nsock--;
779 						(void) close(sep->se_fd);
780 					}
781 					sep->se_fd = -1;
782 				}
783 				if (sep->se_fd == -1)
784 					setup(sep);
785 			}
786 			break;
787 		case AF_INET6:
788 			sep->se_ctrladdr_in6.sin6_family = AF_INET6;
789 			/* se_ctrladdr_in was set in getconfigent */
790 			sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6;
791 
792 			if (isrpcservice(sep)) {
793 				struct rpcent *rp;
794 
795 				sep->se_rpcprog = atoi(sep->se_service);
796 				if (sep->se_rpcprog == 0) {
797 					rp = getrpcbyname(sep->se_service);
798 					if (rp == 0) {
799 						syslog(LOG_ERR,
800 						    "%s: unknown rpc service",
801 						    sep->se_service);
802 						goto serv_unknown;
803 					}
804 					sep->se_rpcprog = rp->r_number;
805 				}
806 				if (sep->se_fd == -1)
807 					setup(sep);
808 				if (sep->se_fd != -1)
809 					register_rpc(sep);
810 			} else {
811 				u_short port = htons(atoi(sep->se_service));
812 
813 				if (!port) {
814 					/* XXX */
815 					strncpy(protoname, sep->se_proto,
816 						sizeof(protoname));
817 					if (isdigit(protoname[strlen(protoname) - 1]))
818 						protoname[strlen(protoname) - 1] = '\0';
819 					sp = getservbyname(sep->se_service,
820 					    protoname);
821 					if (sp == 0) {
822 						syslog(LOG_ERR,
823 						    "%s/%s: unknown service",
824 						    sep->se_service, sep->se_proto);
825 						goto serv_unknown;
826 					}
827 					port = sp->s_port;
828 				}
829 				if (port != sep->se_ctrladdr_in6.sin6_port) {
830 					sep->se_ctrladdr_in6.sin6_port = port;
831 					if (sep->se_fd != -1) {
832 						FD_CLR(sep->se_fd, allsockp);
833 						nsock--;
834 						(void) close(sep->se_fd);
835 					}
836 					sep->se_fd = -1;
837 				}
838 				if (sep->se_fd == -1)
839 					setup(sep);
840 			}
841 			break;
842 		}
843 	serv_unknown:
844 		if (cp->se_next != NULL) {
845 			struct servtab *tmp = cp;
846 
847 			cp = cp->se_next;
848 			free(tmp);
849 		} else {
850 			free(cp);
851 			cp = getconfigent();
852 		}
853 		if (debug)
854 			print_service(add ? "REDO" : "ADD", sep);
855 	}
856 	endconfig();
857 	/*
858 	 * Purge anything not looked at above.
859 	 */
860 	sigprocmask(SIG_BLOCK, &blockmask, &omask);
861 	sepp = &servtab;
862 	while ((sep = *sepp)) {
863 		if (sep->se_checked) {
864 			sepp = &sep->se_next;
865 			continue;
866 		}
867 		*sepp = sep->se_next;
868 		if (sep->se_fd != -1) {
869 			FD_CLR(sep->se_fd, allsockp);
870 			nsock--;
871 			(void) close(sep->se_fd);
872 		}
873 		if (isrpcservice(sep))
874 			unregister_rpc(sep);
875 		if (sep->se_family == AF_UNIX)
876 			(void)unlink(sep->se_service);
877 		if (debug)
878 			print_service("FREE", sep);
879 		freeconfig(sep);
880 		free(sep);
881 	}
882 	sigprocmask(SIG_SETMASK, &omask, NULL);
883 }
884 
885 /* ARGSUSED */
886 void
887 retry(int sig)
888 {
889 	wantretry = 1;
890 }
891 
892 void
893 doretry(void)
894 {
895 	struct servtab *sep;
896 
897 	timingout = 0;
898 	for (sep = servtab; sep; sep = sep->se_next) {
899 		if (sep->se_fd == -1) {
900 			switch (sep->se_family) {
901 			case AF_UNIX:
902 			case AF_INET:
903 			case AF_INET6:
904 				setup(sep);
905 				if (sep->se_fd != -1 && isrpcservice(sep))
906 					register_rpc(sep);
907 				break;
908 			}
909 		}
910 	}
911 }
912 
913 /* ARGSUSED */
914 void
915 die(int sig)
916 {
917 	wantdie = 1;
918 }
919 
920 void
921 dodie(void)
922 {
923 	struct servtab *sep;
924 
925 	for (sep = servtab; sep; sep = sep->se_next) {
926 		if (sep->se_fd == -1)
927 			continue;
928 
929 		switch (sep->se_family) {
930 		case AF_UNIX:
931 			(void)unlink(sep->se_service);
932 			break;
933 		case AF_INET:
934 		case AF_INET6:
935 			if (sep->se_wait == 1 && isrpcservice(sep))
936 				unregister_rpc(sep);
937 			break;
938 		}
939 		(void)close(sep->se_fd);
940 	}
941 	(void)unlink(_PATH_INETDPID);
942 	exit(0);
943 }
944 
945 void
946 setup(struct servtab *sep)
947 {
948 	int on = 1;
949 	int r;
950 	mode_t mask = 0;
951 
952 	if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
953 		syslog(LOG_ERR, "%s/%s: socket: %m",
954 		    sep->se_service, sep->se_proto);
955 		return;
956 	}
957 #define	turnon(fd, opt) \
958 setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on))
959 	if (strncmp(sep->se_proto, "tcp", 3) == 0 && (options & SO_DEBUG) &&
960 	    turnon(sep->se_fd, SO_DEBUG) < 0)
961 		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
962 	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
963 		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
964 #undef turnon
965 	if (isrpcservice(sep)) {
966 		struct passwd *pwd;
967 
968 		/*
969 		 * for RPC services, attempt to use a reserved port
970 		 * if they are going to be running as root.
971 		 *
972 		 * Also, zero out the port for all RPC services; let bind()
973 		 * find one.
974 		 */
975 		sep->se_ctrladdr_in.sin_port = 0;
976 		if (sep->se_user && (pwd = getpwnam(sep->se_user)) &&
977 		    pwd->pw_uid == 0 && uid == 0)
978 			r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in);
979 		else {
980 			r = bind(sep->se_fd, &sep->se_ctrladdr,
981 			    sep->se_ctrladdr_size);
982 			if (r == 0) {
983 				socklen_t len = sep->se_ctrladdr_size;
984 				int saveerrno = errno;
985 
986 				/* update se_ctrladdr_in.sin_port */
987 				r = getsockname(sep->se_fd, &sep->se_ctrladdr,
988 				    &len);
989 				if (r <= 0)
990 					errno = saveerrno;
991 			}
992 		}
993 	} else {
994 		if (sep->se_family == AF_UNIX)
995 			mask = umask(0111);
996 		r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size);
997 		if (sep->se_family == AF_UNIX)
998 			umask(mask);
999 	}
1000 	if (r < 0) {
1001 		syslog(LOG_ERR, "%s/%s: bind: %m",
1002 		    sep->se_service, sep->se_proto);
1003 		(void) close(sep->se_fd);
1004 		sep->se_fd = -1;
1005 		if (!timingout) {
1006 			timingout = 1;
1007 			alarm(RETRYTIME);
1008 		}
1009 		return;
1010 	}
1011 	if (sep->se_socktype == SOCK_STREAM)
1012 		listen(sep->se_fd, 10);
1013 
1014 	fd_grow(&allsockp, &allsockn, sep->se_fd);
1015 	FD_SET(sep->se_fd, allsockp);
1016 	nsock++;
1017 	if (sep->se_fd > maxsock) {
1018 		maxsock = sep->se_fd;
1019 		if (maxsock > rlim_nofile_cur - FD_MARGIN)
1020 			bump_nofile();
1021 	}
1022 }
1023 
1024 void
1025 register_rpc(struct servtab *sep)
1026 {
1027 	socklen_t n;
1028 	struct sockaddr_in sin;
1029 	struct protoent *pp;
1030 
1031 	if ((pp = getprotobyname(sep->se_proto+4)) == NULL) {
1032 		syslog(LOG_ERR, "%s: getproto: %m",
1033 		    sep->se_proto);
1034 		return;
1035 	}
1036 	n = sizeof sin;
1037 	if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) {
1038 		syslog(LOG_ERR, "%s/%s: getsockname: %m",
1039 		    sep->se_service, sep->se_proto);
1040 		return;
1041 	}
1042 
1043 	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1044 		if (debug)
1045 			fprintf(stderr, "pmap_set: %u %u %u %u\n",
1046 			    sep->se_rpcprog, n, pp->p_proto,
1047 			    ntohs(sin.sin_port));
1048 		(void)pmap_unset(sep->se_rpcprog, n);
1049 		if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port)))
1050 			syslog(LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m",
1051 			    sep->se_service, sep->se_proto,
1052 			    sep->se_rpcprog, n, pp->p_proto,
1053 			    ntohs(sin.sin_port));
1054 	}
1055 }
1056 
1057 void
1058 unregister_rpc(struct servtab *sep)
1059 {
1060 	int n;
1061 
1062 	for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1063 		if (debug)
1064 			fprintf(stderr, "pmap_unset(%u, %u)\n",
1065 			    sep->se_rpcprog, n);
1066 		if (!pmap_unset(sep->se_rpcprog, n))
1067 			syslog(LOG_ERR, "pmap_unset(%u, %u)",
1068 			    sep->se_rpcprog, n);
1069 	}
1070 }
1071 
1072 
1073 struct servtab *
1074 enter(struct servtab *cp)
1075 {
1076 	struct servtab *sep;
1077 	sigset_t omask;
1078 
1079 	sep = (struct servtab *)malloc(sizeof (*sep));
1080 	if (sep == NULL) {
1081 		syslog(LOG_ERR, "Out of memory.");
1082 		exit(1);
1083 	}
1084 	*sep = *cp;
1085 	sep->se_fd = -1;
1086 	sep->se_rpcprog = -1;
1087 	sigprocmask(SIG_BLOCK, &blockmask, &omask);
1088 	sep->se_next = servtab;
1089 	servtab = sep;
1090 	sigprocmask(SIG_SETMASK, &omask, NULL);
1091 	return (sep);
1092 }
1093 
1094 int
1095 matchconf(struct servtab *old, struct servtab *new)
1096 {
1097 	if (strcmp(old->se_service, new->se_service) != 0)
1098 		return (0);
1099 
1100 	if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0)
1101 		return (0);
1102 
1103 	if (strcmp(old->se_proto, new->se_proto) != 0)
1104 		return (0);
1105 
1106 	/*
1107 	 * If the new servtab is bound to a specific address, check that the
1108 	 * old servtab is bound to the same entry. If the new service is not
1109 	 * bound to a specific address then the check of se_hostaddr above
1110 	 * is sufficient.
1111 	 */
1112 
1113 	if (old->se_family == AF_INET && new->se_family == AF_INET &&
1114 	    bcmp(&old->se_ctrladdr_in.sin_addr,
1115 	    &new->se_ctrladdr_in.sin_addr,
1116 	    sizeof(new->se_ctrladdr_in.sin_addr)) != 0)
1117 		return (0);
1118 
1119 	if (old->se_family == AF_INET6 && new->se_family == AF_INET6 &&
1120 	    bcmp(&old->se_ctrladdr_in6.sin6_addr,
1121 	    &new->se_ctrladdr_in6.sin6_addr,
1122 	    sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0)
1123 		return (0);
1124 	if (old->se_family == AF_INET6 && new->se_family == AF_INET6 &&
1125 	    old->se_ctrladdr_in6.sin6_scope_id !=
1126 	    new->se_ctrladdr_in6.sin6_scope_id)
1127 		return (0);
1128 
1129 	return (1);
1130 }
1131 
1132 FILE		*fconfig = NULL;
1133 char		line[1024];
1134 char		*defhost;
1135 char		*skip(char **, int);
1136 char		*nextline(FILE *);
1137 char		*newstr(char *);
1138 struct servtab	*dupconfig(struct servtab *);
1139 
1140 int
1141 setconfig(void)
1142 {
1143 	if (defhost)
1144 		free(defhost);
1145 	defhost = newstr("*");
1146 	if (fconfig != NULL) {
1147 		fseek(fconfig, 0L, SEEK_SET);
1148 		return (1);
1149 	}
1150 	fconfig = fopen(CONFIG, "r");
1151 	return (fconfig != NULL);
1152 }
1153 
1154 void
1155 endconfig(void)
1156 {
1157 	if (fconfig) {
1158 		(void) fclose(fconfig);
1159 		fconfig = NULL;
1160 	}
1161 	if (defhost) {
1162 		free(defhost);
1163 		defhost = 0;
1164 	}
1165 }
1166 
1167 struct servtab *
1168 getconfigent(void)
1169 {
1170 	struct servtab *sep, *tsep;
1171 	char *arg, *cp, *hostdelim, *s;
1172 	int argc;
1173 
1174 	sep = (struct servtab *) malloc(sizeof(struct servtab));
1175 	if (sep == NULL) {
1176 		syslog(LOG_ERR, "malloc: %m");
1177 		exit(1);
1178 	}
1179 
1180 	memset(sep, 0, sizeof *sep);
1181 more:
1182 	freeconfig(sep);
1183 
1184 	while ((cp = nextline(fconfig)) && *cp == '#')
1185 		;
1186 	if (cp == NULL) {
1187 		free(sep);
1188 		return (NULL);
1189 	}
1190 
1191 	memset(sep, 0, sizeof *sep);
1192 	arg = skip(&cp, 0);
1193 	if (arg == NULL) {
1194 		/* A blank line. */
1195 		goto more;
1196 	}
1197 
1198 	/* Check for a host name. */
1199 	hostdelim = strrchr(arg, ':');
1200 	if (hostdelim) {
1201 		*hostdelim = '\0';
1202 		if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1203 			hostdelim[-1] = '\0';
1204 			sep->se_hostaddr = newstr(arg + 1);
1205 		} else if (hostdelim == arg)
1206 			sep->se_hostaddr = newstr("*");
1207 		else
1208 			sep->se_hostaddr = newstr(arg);
1209 		arg = hostdelim + 1;
1210 		/*
1211 		 * If the line is of the form `host:', then just change the
1212 		 * default host for the following lines.
1213 		 */
1214 		if (*arg == '\0') {
1215 			arg = skip(&cp, 0);
1216 			if (cp == NULL) {
1217 				free(defhost);
1218 				defhost = newstr(sep->se_hostaddr);
1219 				goto more;
1220 			}
1221 		}
1222 	} else
1223 		sep->se_hostaddr = newstr(defhost);
1224 
1225 	sep->se_service = newstr(arg);
1226 	if ((arg = skip(&cp, 1)) == NULL)
1227 		goto more;
1228 
1229 	if (strcmp(arg, "stream") == 0)
1230 		sep->se_socktype = SOCK_STREAM;
1231 	else if (strcmp(arg, "dgram") == 0)
1232 		sep->se_socktype = SOCK_DGRAM;
1233 	else if (strcmp(arg, "rdm") == 0)
1234 		sep->se_socktype = SOCK_RDM;
1235 	else if (strcmp(arg, "seqpacket") == 0)
1236 		sep->se_socktype = SOCK_SEQPACKET;
1237 	else if (strcmp(arg, "raw") == 0)
1238 		sep->se_socktype = SOCK_RAW;
1239 	else
1240 		sep->se_socktype = -1;
1241 
1242 	if ((arg = skip(&cp, 1)) == NULL)
1243 		goto more;
1244 
1245 	sep->se_proto = newstr(arg);
1246 
1247 	if (strcmp(sep->se_proto, "unix") == 0) {
1248 		sep->se_family = AF_UNIX;
1249 	} else {
1250 		int s;
1251 
1252 		sep->se_family = AF_INET;
1253 		if (sep->se_proto[strlen(sep->se_proto) - 1] == '6')
1254 			sep->se_family = AF_INET6;
1255 
1256 		/* check if the family is supported */
1257 		s = socket(sep->se_family, SOCK_DGRAM, 0);
1258 		if (s < 0) {
1259 			syslog(LOG_WARNING, "%s/%s: %s: the address family is "
1260 			    "not supported by the kernel", sep->se_service,
1261 			    sep->se_proto, sep->se_hostaddr);
1262 			goto more;
1263 		}
1264 		close(s);
1265 
1266 		if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1267 			char *cp, *ccp;
1268 			long l;
1269 
1270 			cp = strchr(sep->se_service, '/');
1271 			if (cp == 0) {
1272 				syslog(LOG_ERR, "%s: no rpc version",
1273 				    sep->se_service);
1274 				goto more;
1275 			}
1276 			*cp++ = '\0';
1277 			l = strtol(cp, &ccp, 0);
1278 			if (ccp == cp || l < 0 || l > INT_MAX) {
1279 		badafterall:
1280 				syslog(LOG_ERR, "%s/%s: bad rpc version",
1281 				    sep->se_service, cp);
1282 				goto more;
1283 			}
1284 			sep->se_rpcversl = sep->se_rpcversh = l;
1285 			if (*ccp == '-') {
1286 				cp = ccp + 1;
1287 				l = strtol(cp, &ccp, 0);
1288 				if (ccp == cp || l < 0 || l > INT_MAX ||
1289 				    l < sep->se_rpcversl || *ccp)
1290 					goto badafterall;
1291 				sep->se_rpcversh = l;
1292 			} else if (*ccp != '\0')
1293 				goto badafterall;
1294 		}
1295 	}
1296 	arg = skip(&cp, 1);
1297 	if (arg == NULL)
1298 		goto more;
1299 
1300 	s = strchr(arg, '.');
1301 	if (s) {
1302 		char *p;
1303 
1304 		*s++ = '\0';
1305 		sep->se_max = strtoul(s, &p, 0);
1306 		if (sep->se_max < 1 || *p) {
1307 			syslog(LOG_ERR,
1308 			    "%s: illegal max field \"%s\", setting to %d",
1309 			    sep->se_service, s, toomany);
1310 			sep->se_max = toomany;
1311 		}
1312 	} else
1313 		sep->se_max = toomany;
1314 
1315 	sep->se_wait = strcmp(arg, "wait") == 0;
1316 	if ((arg = skip(&cp, 1)) == NULL)
1317 		goto more;
1318 	sep->se_user = newstr(arg);
1319 	arg = strchr(sep->se_user, '.');
1320 	if (arg == NULL)
1321 		arg = strchr(sep->se_user, ':');
1322 	if (arg) {
1323 		*arg++ = '\0';
1324 		sep->se_group = newstr(arg);
1325 	}
1326 	if ((arg = skip(&cp, 1)) == NULL)
1327 		goto more;
1328 
1329 	sep->se_server = newstr(arg);
1330 	if (strcmp(sep->se_server, "internal") == 0) {
1331 		struct biltin *bi;
1332 
1333 		for (bi = biltins; bi->bi_service; bi++)
1334 			if (bi->bi_socktype == sep->se_socktype &&
1335 			    strcmp(bi->bi_service, sep->se_service) == 0)
1336 				break;
1337 		if (bi->bi_service == 0) {
1338 			syslog(LOG_ERR, "internal service %s unknown",
1339 			    sep->se_service);
1340 			goto more;
1341 		}
1342 		sep->se_bi = bi;
1343 		sep->se_wait = bi->bi_wait;
1344 	} else
1345 		sep->se_bi = NULL;
1346 	argc = 0;
1347 	for (arg = skip(&cp, 0); cp; arg = skip(&cp, 0)) {
1348 		if (argc < MAXARGV)
1349 			sep->se_argv[argc++] = newstr(arg);
1350 	}
1351 	if (argc == 0 && sep->se_bi == NULL) {
1352 		if ((arg = strrchr(sep->se_server, '/')) != NULL)
1353 			arg++;
1354 		else
1355 			arg = sep->se_server;
1356 		sep->se_argv[argc++] = newstr(arg);
1357 	}
1358 	while (argc <= MAXARGV)
1359 		sep->se_argv[argc++] = NULL;
1360 
1361 	/*
1362 	 * Resolve each hostname in the se_hostaddr list (if any)
1363 	 * and create a new entry for each resolved address.
1364 	 */
1365 	if (sep->se_hostaddr != NULL && strcmp(sep->se_proto, "unix") != 0) {
1366 		struct addrinfo hints, *res0, *res;
1367 		char *host, *hostlist0, *hostlist, *port;
1368 		int error;
1369 
1370 		hostlist = hostlist0 = sep->se_hostaddr;
1371 		sep->se_hostaddr = NULL;
1372 		sep->se_checked = -1;
1373 		while ((host = strsep(&hostlist, ",")) != NULL) {
1374 			if (*host == '\0')
1375 				continue;
1376 
1377 			memset(&hints, 0, sizeof(hints));
1378 			hints.ai_family = sep->se_family;
1379 			hints.ai_socktype = sep->se_socktype;
1380 			hints.ai_flags = AI_PASSIVE;
1381 			port = "0";
1382 			/* XXX shortened IPv4 syntax is now forbidden */
1383 			error = getaddrinfo(strcmp(host, "*") ? host : NULL,
1384 			    port, &hints, &res0);
1385 			if (error) {
1386 				syslog(LOG_ERR, "%s/%s: %s: %s",
1387 				    sep->se_service, sep->se_proto,
1388 				    host, gai_strerror(error));
1389 				continue;
1390 			}
1391 			for (res = res0; res; res = res->ai_next) {
1392 				if (res->ai_addrlen >
1393 				    sizeof(sep->se_ctrladdr_storage))
1394 					continue;
1395 				/*
1396 				 * If sep is unused, store host in there.
1397 				 * Otherwise, dup a new entry and prepend it.
1398 				 */
1399 				if (sep->se_checked == -1) {
1400 					sep->se_checked = 0;
1401 				} else {
1402 					tsep = dupconfig(sep);
1403 					tsep->se_next = sep;
1404 					sep = tsep;
1405 				}
1406 				sep->se_hostaddr = newstr(host);
1407 				memcpy(&sep->se_ctrladdr_storage,
1408 				    res->ai_addr, res->ai_addrlen);
1409 				sep->se_ctrladdr_size = res->ai_addrlen;
1410 			}
1411 			freeaddrinfo(res0);
1412 		}
1413 		free(hostlist0);
1414 		if (sep->se_checked == -1)
1415 			goto more;	/* no resolvable names/addresses */
1416 	}
1417 
1418 	return (sep);
1419 }
1420 
1421 void
1422 freeconfig(struct servtab *cp)
1423 {
1424 	int i;
1425 
1426 	free(cp->se_hostaddr);
1427 	cp->se_hostaddr = NULL;
1428 	free(cp->se_service);
1429 	cp->se_service = NULL;
1430 	free(cp->se_proto);
1431 	cp->se_proto = NULL;
1432 	free(cp->se_user);
1433 	cp->se_user = NULL;
1434 	free(cp->se_group);
1435 	cp->se_group = NULL;
1436 	free(cp->se_server);
1437 	cp->se_server = NULL;
1438 	for (i = 0; i < MAXARGV; i++) {
1439 		free(cp->se_argv[i]);
1440 		cp->se_argv[i] = NULL;
1441 	}
1442 }
1443 
1444 char *
1445 skip(char **cpp, int report)
1446 {
1447 	char *cp = *cpp;
1448 	char *start;
1449 
1450 erp:
1451 	if (*cpp == NULL) {
1452 		if (report)
1453 			syslog(LOG_ERR, "syntax error in inetd config file");
1454 		return (NULL);
1455 	}
1456 
1457 again:
1458 	while (*cp == ' ' || *cp == '\t')
1459 		cp++;
1460 	if (*cp == '\0') {
1461 		int c;
1462 
1463 		c = getc(fconfig);
1464 		(void) ungetc(c, fconfig);
1465 		if (c == ' ' || c == '\t')
1466 			if ((cp = nextline(fconfig)))
1467 				goto again;
1468 		*cpp = NULL;
1469 		goto erp;
1470 	}
1471 	start = cp;
1472 	while (*cp && *cp != ' ' && *cp != '\t')
1473 		cp++;
1474 	if (*cp != '\0')
1475 		*cp++ = '\0';
1476 	if ((*cpp = cp) == NULL)
1477 		goto erp;
1478 
1479 	return (start);
1480 }
1481 
1482 char *
1483 nextline(FILE *fd)
1484 {
1485 	if (fgets(line, sizeof (line), fd) == NULL)
1486 		return (NULL);
1487 	line[strcspn(line, "\n")] = '\0';
1488 	return (line);
1489 }
1490 
1491 char *
1492 newstr(char *cp)
1493 {
1494 	if ((cp = strdup(cp ? cp : "")))
1495 		return(cp);
1496 	syslog(LOG_ERR, "strdup: %m");
1497 	exit(1);
1498 }
1499 
1500 struct servtab *
1501 dupconfig(struct servtab *sep)
1502 {
1503 	struct servtab *newtab;
1504 	int argc;
1505 
1506 	newtab = (struct servtab *) malloc(sizeof(struct servtab));
1507 
1508 	if (newtab == NULL) {
1509 		syslog(LOG_ERR, "malloc: %m");
1510 		exit(1);
1511 	}
1512 
1513 	memset(newtab, 0, sizeof(struct servtab));
1514 
1515 	newtab->se_service = sep->se_service ? newstr(sep->se_service) : NULL;
1516 	newtab->se_socktype = sep->se_socktype;
1517 	newtab->se_family = sep->se_family;
1518 	newtab->se_proto = sep->se_proto ? newstr(sep->se_proto) : NULL;
1519 	newtab->se_rpcprog = sep->se_rpcprog;
1520 	newtab->se_rpcversl = sep->se_rpcversl;
1521 	newtab->se_rpcversh = sep->se_rpcversh;
1522 	newtab->se_wait = sep->se_wait;
1523 	newtab->se_user = sep->se_user ? newstr(sep->se_user) : NULL;
1524 	newtab->se_group = sep->se_group ? newstr(sep->se_group) : NULL;
1525 	newtab->se_bi = sep->se_bi;
1526 	newtab->se_server = sep->se_server ? newstr(sep->se_server) : 0;
1527 
1528 	for (argc = 0; argc <= MAXARGV; argc++)
1529 		newtab->se_argv[argc] = sep->se_argv[argc] ?
1530 		    newstr(sep->se_argv[argc]) : NULL;
1531 	newtab->se_max = sep->se_max;
1532 
1533 	return (newtab);
1534 }
1535 
1536 void
1537 inetd_setproctitle(char *a, int s)
1538 {
1539 	socklen_t size;
1540 	struct sockaddr_storage ss;
1541 	char hbuf[NI_MAXHOST];
1542 
1543 	size = sizeof(ss);
1544 	if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1545 		if (getnameinfo((struct sockaddr *)&ss, size, hbuf,
1546 		    sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0)
1547 			setproctitle("-%s [%s]", a, hbuf);
1548 		else
1549 			setproctitle("-%s [?]", a);
1550 	} else
1551 		setproctitle("-%s", a);
1552 }
1553 
1554 void
1555 logpid(void)
1556 {
1557 	FILE *fp;
1558 
1559 	if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) {
1560 		fprintf(fp, "%ld\n", (long)getpid());
1561 		(void)fclose(fp);
1562 	}
1563 }
1564 
1565 int
1566 bump_nofile(void)
1567 {
1568 #define FD_CHUNK	32
1569 
1570 	struct rlimit rl;
1571 
1572 	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1573 		syslog(LOG_ERR, "getrlimit: %m");
1574 		return -1;
1575 	}
1576 	rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1577 	rl.rlim_cur = MIN(FD_SETSIZE, rl.rlim_cur + FD_CHUNK);
1578 	if (rl.rlim_cur <= rlim_nofile_cur) {
1579 		syslog(LOG_ERR,
1580 		    "bump_nofile: cannot extend file limit, max = %d",
1581 		    (int)rl.rlim_cur);
1582 		return -1;
1583 	}
1584 
1585 	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1586 		syslog(LOG_ERR, "setrlimit: %m");
1587 		return -1;
1588 	}
1589 
1590 	rlim_nofile_cur = rl.rlim_cur;
1591 	return 0;
1592 }
1593 
1594 /*
1595  * Internet services provided internally by inetd:
1596  */
1597 #define	BUFSIZE	4096
1598 
1599 /* ARGSUSED */
1600 void
1601 echo_stream(int s, struct servtab *sep)
1602 {
1603 	char buffer[BUFSIZE];
1604 	int i;
1605 
1606 	inetd_setproctitle(sep->se_service, s);
1607 	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1608 	    write(s, buffer, i) > 0)
1609 		;
1610 	exit(0);
1611 }
1612 
1613 /* ARGSUSED */
1614 void
1615 echo_dg(int s, struct servtab *sep)
1616 {
1617 	char buffer[BUFSIZE];
1618 	int i;
1619 	socklen_t size;
1620 	struct sockaddr_storage ss;
1621 
1622 	size = sizeof(ss);
1623 	if ((i = recvfrom(s, buffer, sizeof(buffer), 0,
1624 	    (struct sockaddr *)&ss, &size)) < 0)
1625 		return;
1626 	if (dg_badinput((struct sockaddr *)&ss))
1627 		return;
1628 	(void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss, size);
1629 }
1630 
1631 /* ARGSUSED */
1632 void
1633 discard_stream(int s, struct servtab *sep)
1634 {
1635 	char buffer[BUFSIZE];
1636 
1637 	inetd_setproctitle(sep->se_service, s);
1638 	while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1639 	    errno == EINTR)
1640 		;
1641 	exit(0);
1642 }
1643 
1644 /* ARGSUSED */
1645 void
1646 discard_dg(int s, struct servtab *sep)
1647 {
1648 	char buffer[BUFSIZE];
1649 
1650 	(void) read(s, buffer, sizeof(buffer));
1651 }
1652 
1653 #include <ctype.h>
1654 #define LINESIZ 72
1655 char ring[128];
1656 char *endring;
1657 
1658 void
1659 initring(void)
1660 {
1661 	int i;
1662 
1663 	endring = ring;
1664 
1665 	for (i = 0; i <= sizeof ring; ++i)
1666 		if (isprint(i))
1667 			*endring++ = i;
1668 }
1669 
1670 /* ARGSUSED */
1671 void
1672 chargen_stream(int s, struct servtab *sep)
1673 {
1674 	char *rs;
1675 	int len;
1676 	char text[LINESIZ+2];
1677 
1678 	inetd_setproctitle(sep->se_service, s);
1679 
1680 	if (!endring) {
1681 		initring();
1682 		rs = ring;
1683 	}
1684 
1685 	text[LINESIZ] = '\r';
1686 	text[LINESIZ + 1] = '\n';
1687 	for (rs = ring;;) {
1688 		if ((len = endring - rs) >= LINESIZ)
1689 			memmove(text, rs, LINESIZ);
1690 		else {
1691 			memmove(text, rs, len);
1692 			memmove(text + len, ring, LINESIZ - len);
1693 		}
1694 		if (++rs == endring)
1695 			rs = ring;
1696 		if (write(s, text, sizeof(text)) != sizeof(text))
1697 			break;
1698 	}
1699 	exit(0);
1700 }
1701 
1702 /* ARGSUSED */
1703 void
1704 chargen_dg(int s, struct servtab *sep)
1705 {
1706 	struct sockaddr_storage ss;
1707 	static char *rs;
1708 	int len;
1709 	socklen_t size;
1710 	char text[LINESIZ+2];
1711 
1712 	if (endring == 0) {
1713 		initring();
1714 		rs = ring;
1715 	}
1716 
1717 	size = sizeof(ss);
1718 	if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss,
1719 	    &size) < 0)
1720 		return;
1721 	if (dg_badinput((struct sockaddr *)&ss))
1722 		return;
1723 
1724 	if ((len = endring - rs) >= LINESIZ)
1725 		memmove(text, rs, LINESIZ);
1726 	else {
1727 		memmove(text, rs, len);
1728 		memmove(text + len, ring, LINESIZ - len);
1729 	}
1730 	if (++rs == endring)
1731 		rs = ring;
1732 	text[LINESIZ] = '\r';
1733 	text[LINESIZ + 1] = '\n';
1734 	(void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size);
1735 }
1736 
1737 /*
1738  * Return a machine readable date and time, in the form of the
1739  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1740  * returns the number of seconds since midnight, Jan 1, 1970,
1741  * we must add 2208988800 seconds to this figure to make up for
1742  * some seventy years Bell Labs was asleep.
1743  */
1744 u_int32_t
1745 machtime(void)
1746 {
1747 	struct timeval tv;
1748 
1749 	if (gettimeofday(&tv, NULL) < 0)
1750 		return (0L);
1751 
1752 	return (htonl((u_int32_t)tv.tv_sec + 2208988800UL));
1753 }
1754 
1755 /* ARGSUSED */
1756 void
1757 machtime_stream(s, sep)
1758 	int s;
1759 	struct servtab *sep;
1760 {
1761 	u_int32_t result;
1762 
1763 	result = machtime();
1764 	(void) write(s, &result, sizeof(result));
1765 }
1766 
1767 /* ARGSUSED */
1768 void
1769 machtime_dg(int s, struct servtab *sep)
1770 {
1771 	u_int32_t result;
1772 	struct sockaddr_storage ss;
1773 	socklen_t size;
1774 
1775 	size = sizeof(ss);
1776 	if (recvfrom(s, &result, sizeof(result), 0,
1777 	    (struct sockaddr *)&ss, &size) < 0)
1778 		return;
1779 	if (dg_badinput((struct sockaddr *)&ss))
1780 		return;
1781 	result = machtime();
1782 	(void) sendto(s, &result, sizeof(result), 0,
1783 	    (struct sockaddr *)&ss, size);
1784 }
1785 
1786 /* Return human-readable time of day */
1787 /* ARGSUSED */
1788 void
1789 daytime_stream(int s, struct servtab *sep)
1790 {
1791 	char buffer[256];
1792 	time_t clock;
1793 
1794 	clock = time(NULL);
1795 
1796 	(void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
1797 	(void) write(s, buffer, strlen(buffer));
1798 }
1799 
1800 /* Return human-readable time of day */
1801 /* ARGSUSED */
1802 void
1803 daytime_dg(int s, struct servtab *sep)
1804 {
1805 	char buffer[256];
1806 	time_t clock;
1807 	struct sockaddr_storage ss;
1808 	socklen_t size;
1809 
1810 	clock = time(NULL);
1811 
1812 	size = sizeof(ss);
1813 	if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss,
1814 	    &size) < 0)
1815 		return;
1816 	if (dg_badinput((struct sockaddr *)&ss))
1817 		return;
1818 	(void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
1819 	(void) sendto(s, buffer, strlen(buffer), 0, (struct sockaddr *)&ss,
1820 	    size);
1821 }
1822 
1823 /*
1824  * print_service:
1825  *	Dump relevant information to stderr
1826  */
1827 void
1828 print_service(char *action, struct servtab *sep)
1829 {
1830 	if (strcmp(sep->se_hostaddr, "*") == 0)
1831 		fprintf(stderr, "%s: %s ", action, sep->se_service);
1832 	else
1833 		fprintf(stderr, "%s: %s:%s ", action, sep->se_hostaddr,
1834 		    sep->se_service);
1835 
1836 	if (isrpcservice(sep))
1837 		fprintf(stderr, "rpcprog=%d, rpcvers=%d/%d, proto=%s,",
1838 		    sep->se_rpcprog, sep->se_rpcversh,
1839 		    sep->se_rpcversl, sep->se_proto);
1840 	else
1841 		fprintf(stderr, "proto=%s,", sep->se_proto);
1842 
1843 	fprintf(stderr,
1844 	    " wait.max=%hd.%d user:group=%s:%s builtin=%lx server=%s\n",
1845 	    sep->se_wait, sep->se_max, sep->se_user,
1846 	    sep->se_group ? sep->se_group : "wheel",
1847 	    (long)sep->se_bi, sep->se_server);
1848 }
1849 
1850 void
1851 spawn(struct servtab *sep, int ctrl)
1852 {
1853 	struct passwd *pwd;
1854 	int tmpint, dofork;
1855 	struct group *grp = NULL;
1856 	char buf[50];
1857 	pid_t pid;
1858 
1859 	pid = 0;
1860 	dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
1861 	if (dofork) {
1862 		if (sep->se_count++ == 0)
1863 		    (void)gettimeofday(&sep->se_time, NULL);
1864 		else if (sep->se_count >= sep->se_max) {
1865 			struct timeval now;
1866 
1867 			(void)gettimeofday(&now, NULL);
1868 			if (now.tv_sec - sep->se_time.tv_sec >
1869 			    CNT_INTVL) {
1870 				sep->se_time = now;
1871 				sep->se_count = 1;
1872 			} else {
1873 				if (!sep->se_wait &&
1874 				    sep->se_socktype == SOCK_STREAM)
1875 					close(ctrl);
1876 				if (sep->se_family == AF_INET &&
1877 				    ntohs(sep->se_ctrladdr_in.sin_port) >=
1878 				    IPPORT_RESERVED) {
1879 					/*
1880 					 * Cannot close it -- there are
1881 					 * thieves on the system.
1882 					 * Simply ignore the connection.
1883 					 */
1884 					--sep->se_count;
1885 					sigprocmask(SIG_SETMASK, &emptymask,
1886 					    NULL);
1887 					return;
1888 				}
1889 				syslog(LOG_ERR,
1890 				    "%s/%s server failing (looping), service terminated",
1891 				    sep->se_service, sep->se_proto);
1892 				if (!sep->se_wait &&
1893 				    sep->se_socktype == SOCK_STREAM)
1894 					close(ctrl);
1895 				FD_CLR(sep->se_fd, allsockp);
1896 				(void) close(sep->se_fd);
1897 				sep->se_fd = -1;
1898 				sep->se_count = 0;
1899 				nsock--;
1900 				sigprocmask(SIG_SETMASK, &emptymask,
1901 				    NULL);
1902 				if (!timingout) {
1903 					timingout = 1;
1904 					alarm(RETRYTIME);
1905 				}
1906 				return;
1907 			}
1908 		}
1909 		pid = fork();
1910 	}
1911 	if (pid < 0) {
1912 		syslog(LOG_ERR, "fork: %m");
1913 		if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
1914 			close(ctrl);
1915 		sigprocmask(SIG_SETMASK, &emptymask, NULL);
1916 		sleep(1);
1917 		return;
1918 	}
1919 	if (pid && sep->se_wait) {
1920 		sep->se_wait = pid;
1921 		FD_CLR(sep->se_fd, allsockp);
1922 		nsock--;
1923 	}
1924 	sigprocmask(SIG_SETMASK, &emptymask, NULL);
1925 	if (pid == 0) {
1926 		if (sep->se_bi)
1927 			(*sep->se_bi->bi_fn)(ctrl, sep);
1928 		else {
1929 			if ((pwd = getpwnam(sep->se_user)) == NULL) {
1930 				syslog(LOG_ERR,
1931 				    "getpwnam: %s: No such user",
1932 				    sep->se_user);
1933 				if (sep->se_socktype != SOCK_STREAM)
1934 					recv(0, buf, sizeof (buf), 0);
1935 				exit(1);
1936 			}
1937 			if (setsid() <0)
1938 				syslog(LOG_ERR, "%s: setsid: %m",
1939 				    sep->se_service);
1940 			if (sep->se_group &&
1941 			    (grp = getgrnam(sep->se_group)) == NULL) {
1942 				syslog(LOG_ERR,
1943 				    "getgrnam: %s: No such group",
1944 				    sep->se_group);
1945 				if (sep->se_socktype != SOCK_STREAM)
1946 					recv(0, buf, sizeof (buf), 0);
1947 				exit(1);
1948 			}
1949 			if (uid != 0) {
1950 				/* a user running private inetd */
1951 				if (uid != pwd->pw_uid)
1952 					exit(1);
1953 			} else {
1954 				tmpint = LOGIN_SETALL &
1955 				    ~(LOGIN_SETGROUP|LOGIN_SETLOGIN);
1956 				if (pwd->pw_uid)
1957 					tmpint |= LOGIN_SETGROUP|LOGIN_SETLOGIN;
1958 				if (sep->se_group) {
1959 					pwd->pw_gid = grp->gr_gid;
1960 					tmpint |= LOGIN_SETGROUP;
1961 				}
1962 				if (setusercontext(NULL, pwd, pwd->pw_uid,
1963 				    tmpint) < 0) {
1964 					syslog(LOG_ERR,
1965 					    "%s/%s: setusercontext: %m",
1966 					    sep->se_service, sep->se_proto);
1967 					exit(1);
1968 				}
1969 			}
1970 			if (debug)
1971 				fprintf(stderr, "%ld execv %s\n",
1972 				    (long)getpid(), sep->se_server);
1973 			if (ctrl != STDIN_FILENO) {
1974 				dup2(ctrl, STDIN_FILENO);
1975 				close(ctrl);
1976 			}
1977 			dup2(STDIN_FILENO, STDOUT_FILENO);
1978 			dup2(STDIN_FILENO, STDERR_FILENO);
1979 			closelog();
1980 			closefrom(3);
1981 			sigaction(SIGPIPE, &sapipe, NULL);
1982 			execv(sep->se_server, sep->se_argv);
1983 			if (sep->se_socktype != SOCK_STREAM)
1984 				recv(0, buf, sizeof (buf), 0);
1985 			syslog(LOG_ERR, "execv %s: %m", sep->se_server);
1986 			exit(1);
1987 		}
1988 	}
1989 	if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
1990 		close(ctrl);
1991 }
1992