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