xref: /freebsd/usr.sbin/inetd/inetd.c (revision 6e8394b8baa7d5d9153ab90de6824bcd19b3b4e1)
1 /*
2  * Copyright (c) 1983, 1991, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
37 	The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)from: inetd.c	8.4 (Berkeley) 4/13/94";
43 #endif
44 static const char rcsid[] =
45 	"$Id: inetd.c,v 1.50 1999/06/17 09:16:08 sheldonh Exp $";
46 #endif /* not lint */
47 
48 /*
49  * Inetd - Internet super-server
50  *
51  * This program invokes all internet services as needed.  Connection-oriented
52  * services are invoked each time a connection is made, by creating a process.
53  * This process is passed the connection as file descriptor 0 and is expected
54  * to do a getpeername to find out the source host and port.
55  *
56  * Datagram oriented services are invoked when a datagram
57  * arrives; a process is created and passed a pending message
58  * on file descriptor 0.  Datagram servers may either connect
59  * to their peer, freeing up the original socket for inetd
60  * to receive further messages on, or ``take over the socket'',
61  * processing all arriving datagrams and, eventually, timing
62  * out.	 The first type of server is said to be ``multi-threaded'';
63  * the second type of server ``single-threaded''.
64  *
65  * Inetd uses a configuration file which is read at startup
66  * and, possibly, at some later time in response to a hangup signal.
67  * The configuration file is ``free format'' with fields given in the
68  * order shown below.  Continuation lines for an entry must being with
69  * a space or tab.  All fields must be present in each entry.
70  *
71  *	service name			must be in /etc/services or must
72  *					name a tcpmux service
73  *	socket type			stream/dgram/raw/rdm/seqpacket
74  *	protocol			must be in /etc/protocols
75  *	wait/nowait			single-threaded/multi-threaded
76  *	user				user to run daemon as
77  *	server program			full path name
78  *	server program arguments	maximum of MAXARGS (20)
79  *
80  * TCP services without official port numbers are handled with the
81  * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
82  * requests. When a connection is made from a foreign host, the service
83  * requested is passed to tcpmux, which looks it up in the servtab list
84  * and returns the proper entry for the service. Tcpmux returns a
85  * negative reply if the service doesn't exist, otherwise the invoked
86  * server is expected to return the positive reply if the service type in
87  * inetd.conf file has the prefix "tcpmux/". If the service type has the
88  * prefix "tcpmux/+", tcpmux will return the positive reply for the
89  * process; this is for compatibility with older server code, and also
90  * allows you to invoke programs that use stdin/stdout without putting any
91  * special server code in them. Services that use tcpmux are "nowait"
92  * because they do not have a well-known port and hence cannot listen
93  * for new requests.
94  *
95  * For RPC services
96  *	service name/version		must be in /etc/rpc
97  *	socket type			stream/dgram/raw/rdm/seqpacket
98  *	protocol			must be in /etc/protocols
99  *	wait/nowait			single-threaded/multi-threaded
100  *	user				user to run daemon as
101  *	server program			full path name
102  *	server program arguments	maximum of MAXARGS
103  *
104  * Comment lines are indicated by a `#' in column 1.
105  */
106 #include <sys/param.h>
107 #include <sys/stat.h>
108 #include <sys/ioctl.h>
109 #include <sys/socket.h>
110 #include <sys/wait.h>
111 #include <sys/time.h>
112 #include <sys/resource.h>
113 
114 #include <netinet/in.h>
115 #include <netinet/tcp.h>
116 #include <arpa/inet.h>
117 #include <rpc/rpc.h>
118 #include <rpc/pmap_clnt.h>
119 
120 #include <errno.h>
121 #include <err.h>
122 #include <fcntl.h>
123 #include <grp.h>
124 #include <netdb.h>
125 #include <pwd.h>
126 #include <signal.h>
127 #include <stdio.h>
128 #include <stdlib.h>
129 #include <string.h>
130 #include <syslog.h>
131 #include <unistd.h>
132 #include <libutil.h>
133 #include <sysexits.h>
134 
135 #ifdef LIBWRAP
136 # include <tcpd.h>
137 #ifndef LIBWRAP_ALLOW_FACILITY
138 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
139 #endif
140 #ifndef LIBWRAP_ALLOW_SEVERITY
141 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
142 #endif
143 #ifndef LIBWRAP_DENY_FACILITY
144 # define LIBWRAP_DENY_FACILITY LOG_AUTH
145 #endif
146 #ifndef LIBWRAP_DENY_SEVERITY
147 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
148 #endif
149 int allow_severity;
150 int deny_severity;
151 #endif
152 
153 #ifdef LOGIN_CAP
154 #include <login_cap.h>
155 
156 /* see init.c */
157 #define RESOURCE_RC "daemon"
158 
159 #endif
160 
161 #include "pathnames.h"
162 
163 #ifndef	MAXCHILD
164 #define	MAXCHILD	-1		/* maximum number of this service
165 					   < 0 = no limit */
166 #endif
167 
168 #ifndef	MAXCPM
169 #define	MAXCPM		-1		/* rate limit invocations from a
170 					   single remote address,
171 					   < 0 = no limit */
172 #endif
173 
174 #define	TOOMANY		256		/* don't start more than TOOMANY */
175 #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
176 #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
177 #define MAX_MAXCHLD	32767		/* max allowable max children */
178 
179 #define	SIGBLOCK	(sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
180 
181 int	debug = 0;
182 int	log = 0;
183 int	nsock, maxsock;
184 fd_set	allsock;
185 int	options;
186 int	timingout;
187 int	toomany = TOOMANY;
188 int	maxchild = MAXCHILD;
189 int	maxcpm = MAXCPM;
190 struct	servent *sp;
191 struct	rpcent *rpc;
192 struct	in_addr bind_address;
193 int	signalpipe[2];
194 
195 struct	servtab {
196 	char	*se_service;		/* name of service */
197 	int	se_socktype;		/* type of socket to use */
198 	char	*se_proto;		/* protocol used */
199 	int	se_maxchild;		/* max number of children */
200 	int	se_maxcpm;		/* max connects per IP per minute */
201 	int	se_numchild;		/* current number of children */
202 	pid_t	*se_pids;		/* array of child pids */
203 	char	*se_user;		/* user name to run as */
204 	char    *se_group;              /* group name to run as */
205 #ifdef  LOGIN_CAP
206 	char    *se_class;              /* login class name to run with */
207 #endif
208 	struct	biltin *se_bi;		/* if built-in, description */
209 	char	*se_server;		/* server program */
210 	char	*se_server_name;	/* server program without path */
211 #define	MAXARGV 20
212 	char	*se_argv[MAXARGV+1];	/* program arguments */
213 	int	se_fd;			/* open descriptor */
214 	struct	sockaddr_in se_ctrladdr;/* bound address */
215 	u_char	se_type;		/* type: normal, mux, or mux+ */
216 	u_char	se_checked;		/* looked at during merge */
217 	u_char	se_accept;		/* i.e., wait/nowait mode */
218 	u_char	se_rpc;			/* ==1 if RPC service */
219 	int	se_rpc_prog;		/* RPC program number */
220 	u_int	se_rpc_lowvers;		/* RPC low version */
221 	u_int	se_rpc_highvers;	/* RPC high version */
222 	int	se_count;		/* number started since se_time */
223 	struct	timeval se_time;	/* start of se_count */
224 	struct	servtab *se_next;
225 } *servtab;
226 
227 #define NORM_TYPE	0
228 #define MUX_TYPE	1
229 #define MUXPLUS_TYPE	2
230 #define TTCP_TYPE	3
231 #define ISMUX(sep)	(((sep)->se_type == MUX_TYPE) || \
232 			 ((sep)->se_type == MUXPLUS_TYPE))
233 #define ISMUXPLUS(sep)	((sep)->se_type == MUXPLUS_TYPE)
234 #define ISTTCP(sep)	((sep)->se_type == TTCP_TYPE)
235 
236 
237 void		chargen_dg __P((int, struct servtab *));
238 void		chargen_stream __P((int, struct servtab *));
239 void		close_sep __P((struct servtab *));
240 void		flag_signal __P((char));
241 void		flag_config __P((int));
242 void		config __P((void));
243 void		daytime_dg __P((int, struct servtab *));
244 void		daytime_stream __P((int, struct servtab *));
245 void		discard_dg __P((int, struct servtab *));
246 void		discard_stream __P((int, struct servtab *));
247 void		echo_dg __P((int, struct servtab *));
248 void		echo_stream __P((int, struct servtab *));
249 void		endconfig __P((void));
250 struct servtab *enter __P((struct servtab *));
251 void		freeconfig __P((struct servtab *));
252 struct servtab *getconfigent __P((void));
253 void		ident_stream __P((int, struct servtab *));
254 void		machtime_dg __P((int, struct servtab *));
255 void		machtime_stream __P((int, struct servtab *));
256 char	       *newstr __P((char *));
257 char	       *nextline __P((FILE *));
258 void		print_service __P((char *, struct servtab *));
259 void		addchild __P((struct servtab *, int));
260 void		flag_reapchild __P((int));
261 void		reapchild __P((void));
262 void		enable __P((struct servtab *));
263 void		disable __P((struct servtab *));
264 void		flag_retry __P((int));
265 void		retry __P((void));
266 int		setconfig __P((void));
267 void		setup __P((struct servtab *));
268 char	       *sskip __P((char **));
269 char	       *skip __P((char **));
270 struct servtab *tcpmux __P((int));
271 int		cpmip __P((struct servtab *, int));
272 
273 void		unregisterrpc __P((register struct servtab *sep));
274 
275 struct biltin {
276 	char	*bi_service;		/* internally provided service name */
277 	int	bi_socktype;		/* type of socket supported */
278 	short	bi_fork;		/* 1 if should fork before call */
279 	int	bi_maxchild;		/* max number of children (-1=default) */
280 	void	(*bi_fn)();		/* function which performs it */
281 } biltins[] = {
282 	/* Echo received data */
283 	{ "echo",	SOCK_STREAM,	1, -1,	echo_stream },
284 	{ "echo",	SOCK_DGRAM,	0, 1,	echo_dg },
285 
286 	/* Internet /dev/null */
287 	{ "discard",	SOCK_STREAM,	1, -1,	discard_stream },
288 	{ "discard",	SOCK_DGRAM,	0, 1,	discard_dg },
289 
290 	/* Return 32 bit time since 1970 */
291 	{ "time",	SOCK_STREAM,	0, -1,	machtime_stream },
292 	{ "time",	SOCK_DGRAM,	0, 1,	machtime_dg },
293 
294 	/* Return human-readable time */
295 	{ "daytime",	SOCK_STREAM,	0, -1,	daytime_stream },
296 	{ "daytime",	SOCK_DGRAM,	0, 1,	daytime_dg },
297 
298 	/* Familiar character generator */
299 	{ "chargen",	SOCK_STREAM,	1, -1,	chargen_stream },
300 	{ "chargen",	SOCK_DGRAM,	0, 1,	chargen_dg },
301 
302 	{ "tcpmux",	SOCK_STREAM,	1, -1,	(void (*)())tcpmux },
303 
304 	{ "ident",	SOCK_STREAM,	1, -1,	ident_stream },
305 
306 	{ NULL }
307 };
308 
309 #define NUMINT	(sizeof(intab) / sizeof(struct inent))
310 char	*CONFIG = _PATH_INETDCONF;
311 char	*pid_file = _PATH_INETDPID;
312 
313 #ifdef OLD_SETPROCTITLE
314 char	**Argv;
315 char 	*LastArg;
316 #endif
317 
318 int
319 getvalue(arg, value, whine)
320 	char *arg, *whine;
321 	int  *value;
322 {
323 	int  tmp;
324 	char *p;
325 
326 	tmp = strtol(arg, &p, 0);
327 	if (tmp < 1 || *p) {
328 		syslog(LOG_ERR, whine, arg);
329 		return 1;			/* failure */
330 	}
331 	*value = tmp;
332 	return 0;				/* success */
333 }
334 
335 int
336 main(argc, argv, envp)
337 	int argc;
338 	char *argv[], *envp[];
339 {
340 	struct servtab *sep;
341 	struct passwd *pwd;
342 	struct group *grp;
343 	struct sigaction sa, sapipe;
344 	int tmpint, ch, dofork;
345 	pid_t pid;
346 	char buf[50];
347 #ifdef LOGIN_CAP
348 	login_cap_t *lc = NULL;
349 #endif
350 #ifdef LIBWRAP
351 	struct request_info req;
352 	int denied;
353 	char *service = NULL;
354 #else
355 	struct  sockaddr_in peer;
356 	int i;
357 #endif
358 
359 
360 #ifdef OLD_SETPROCTITLE
361 	Argv = argv;
362 	if (envp == 0 || *envp == 0)
363 		envp = argv;
364 	while (*envp)
365 		envp++;
366 	LastArg = envp[-1] + strlen(envp[-1]);
367 #endif
368 
369 	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
370 
371 	bind_address.s_addr = htonl(INADDR_ANY);
372 	while ((ch = getopt(argc, argv, "dlR:a:c:C:p:")) != -1)
373 		switch(ch) {
374 		case 'd':
375 			debug = 1;
376 			options |= SO_DEBUG;
377 			break;
378 		case 'l':
379 			log = 1;
380 			break;
381 		case 'R':
382 			getvalue(optarg, &toomany,
383 				"-R %s: bad value for service invocation rate");
384 			break;
385 		case 'c':
386 			getvalue(optarg, &maxchild,
387 				"-c %s: bad value for maximum children");
388 			break;
389 		case 'C':
390 			getvalue(optarg, &maxcpm,
391 				"-C %s: bad value for maximum children/minute");
392 			break;
393 		case 'a':
394 			if (!inet_aton(optarg, &bind_address)) {
395 				syslog(LOG_ERR,
396 			         "-a %s: invalid IP address", optarg);
397 				exit(EX_USAGE);
398 			}
399 			break;
400 		case 'p':
401 			pid_file = optarg;
402 			break;
403 		case '?':
404 		default:
405 			syslog(LOG_ERR,
406 				"usage: inetd [-dl] [-a address] [-R rate]"
407 				" [-c maximum] [-C rate]"
408 				" [-p pidfile] [conf-file]");
409 			exit(EX_USAGE);
410 		}
411 	argc -= optind;
412 	argv += optind;
413 
414 	if (argc > 0)
415 		CONFIG = argv[0];
416 	if (debug == 0) {
417 		FILE *fp;
418 		if (daemon(0, 0) < 0) {
419 			syslog(LOG_WARNING, "daemon(0,0) failed: %m");
420 		}
421 		/*
422 		 * In case somebody has started inetd manually, we need to
423 		 * clear the logname, so that old servers run as root do not
424 		 * get the user's logname..
425 		 */
426 		if (setlogin("") < 0) {
427 			syslog(LOG_WARNING, "cannot clear logname: %m");
428 			/* no big deal if it fails.. */
429 		}
430 		pid = getpid();
431 		fp = fopen(pid_file, "w");
432 		if (fp) {
433 			fprintf(fp, "%ld\n", (long)pid);
434 			fclose(fp);
435 		} else {
436 			syslog(LOG_WARNING, "%s: %m", pid_file);
437 		}
438 	}
439 	sa.sa_flags = 0;
440 	sigemptyset(&sa.sa_mask);
441 	sigaddset(&sa.sa_mask, SIGALRM);
442 	sigaddset(&sa.sa_mask, SIGCHLD);
443 	sigaddset(&sa.sa_mask, SIGHUP);
444 	sa.sa_handler = flag_retry;
445 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
446 	config();
447 	sa.sa_handler = flag_config;
448 	sigaction(SIGHUP, &sa, (struct sigaction *)0);
449 	sa.sa_handler = flag_reapchild;
450 	sigaction(SIGCHLD, &sa, (struct sigaction *)0);
451 	sa.sa_handler = SIG_IGN;
452 	sigaction(SIGPIPE, &sa, &sapipe);
453 
454 	{
455 		/* space for daemons to overwrite environment for ps */
456 #define	DUMMYSIZE	100
457 		char dummy[DUMMYSIZE];
458 
459 		(void)memset(dummy, 'x', DUMMYSIZE - 1);
460 		dummy[DUMMYSIZE - 1] = '\0';
461 		(void)setenv("inetd_dummy", dummy, 1);
462 	}
463 
464 	if (pipe(signalpipe) != 0) {
465 		syslog(LOG_ERR, "pipe: %%m");
466 		exit(EX_OSERR);
467 	}
468 	FD_SET(signalpipe[0], &allsock);
469 	nsock++;
470 	if (signalpipe[0] > maxsock)
471 	    maxsock = signalpipe[0];
472 
473 	for (;;) {
474 	    int n, ctrl;
475 	    fd_set readable;
476 
477 	    if (nsock == 0) {
478 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
479 		exit(EX_SOFTWARE);
480 	    }
481 	    readable = allsock;
482 	    if ((n = select(maxsock + 1, &readable, (fd_set *)0,
483 		(fd_set *)0, (struct timeval *)0)) <= 0) {
484 		    if (n < 0 && errno != EINTR) {
485 			syslog(LOG_WARNING, "select: %m");
486 			sleep(1);
487 		    }
488 		    continue;
489 	    }
490 	    /* handle any queued signal flags */
491 	    if (FD_ISSET(signalpipe[0], &readable)) {
492 		int n;
493 		if (ioctl(signalpipe[0], FIONREAD, &n) != 0) {
494 		    syslog(LOG_ERR, "ioctl: %m");
495 		    exit(EX_OSERR);
496 		}
497 		while (--n >= 0) {
498 		    char c;
499 		    if (read(signalpipe[0], &c, 1) != 1) {
500 			syslog(LOG_ERR, "read: %m");
501 			exit(EX_OSERR);
502 		    }
503 		    if (debug)
504 			warnx("Handling signal flag %c", c);
505 		    switch(c) {
506 		    case 'A': /* sigalrm */
507 			retry();
508 			break;
509 		    case 'C': /* sigchld */
510 			reapchild();
511 			break;
512 		    case 'H': /* sighup */
513 			config();
514 			break;
515 		    }
516 		}
517 	    }
518 	    for (sep = servtab; n && sep; sep = sep->se_next)
519 	        if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
520 		    n--;
521 		    if (debug)
522 			    warnx("someone wants %s", sep->se_service);
523 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
524 			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
525 				(int *)0);
526 			    if (debug)
527 				    warnx("accept, ctrl %d", ctrl);
528 			    if (ctrl < 0) {
529 				    if (errno != EINTR)
530 					    syslog(LOG_WARNING,
531 						"accept (for %s): %m",
532 						sep->se_service);
533                                       if (sep->se_accept &&
534                                           sep->se_socktype == SOCK_STREAM)
535                                               close(ctrl);
536 				    continue;
537 			    }
538 			    if (cpmip(sep, ctrl) < 0) {
539 				close(ctrl);
540 				continue;
541 			    }
542 #ifndef LIBWRAP
543 			    if (log) {
544 				i = sizeof peer;
545 				if (getpeername(ctrl, (struct sockaddr *)
546 						&peer, &i)) {
547 					syslog(LOG_WARNING,
548 						"getpeername(for %s): %m",
549 						sep->se_service);
550 					close(ctrl);
551 					continue;
552 				}
553 				syslog(LOG_INFO,"%s from %s",
554 					sep->se_service,
555 					inet_ntoa(peer.sin_addr));
556 			    }
557 #endif
558 		    } else
559 			    ctrl = sep->se_fd;
560 		    (void) sigblock(SIGBLOCK);
561 		    pid = 0;
562 #ifdef LIBWRAP_INTERNAL
563 		    /*
564 		     * When builtins are wrapped, avoid a minor optimization
565 		     * that breaks hosts_options(5) twist.
566 		     */
567 		    dofork = 1;
568 #else
569 		    dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
570 #endif
571 		    if (dofork) {
572 			    if (sep->se_count++ == 0)
573 				(void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
574 			    else if (sep->se_count >= toomany) {
575 				struct timeval now;
576 
577 				(void)gettimeofday(&now, (struct timezone *)NULL);
578 				if (now.tv_sec - sep->se_time.tv_sec >
579 				    CNT_INTVL) {
580 					sep->se_time = now;
581 					sep->se_count = 1;
582 				} else {
583 					syslog(LOG_ERR,
584 			"%s/%s server failing (looping), service terminated",
585 					    sep->se_service, sep->se_proto);
586 					close_sep(sep);
587 					sigsetmask(0L);
588 					if (!timingout) {
589 						timingout = 1;
590 						alarm(RETRYTIME);
591 					}
592 					continue;
593 				}
594 			    }
595 			    pid = fork();
596 		    }
597 		    if (pid < 0) {
598 			    syslog(LOG_ERR, "fork: %m");
599 			    if (sep->se_accept &&
600 				sep->se_socktype == SOCK_STREAM)
601 				    close(ctrl);
602 			    sigsetmask(0L);
603 			    sleep(1);
604 			    continue;
605 		    }
606 		    if (pid)
607 			addchild(sep, pid);
608 		    sigsetmask(0L);
609 		    if (pid == 0) {
610 			    if (dofork) {
611 				if (debug)
612 					warnx("+ closing from %d", maxsock);
613 				for (tmpint = maxsock; tmpint > 2; tmpint--)
614 					if (tmpint != ctrl)
615 						(void) close(tmpint);
616 			    }
617 			    /*
618 			     * Call tcpmux to find the real service to exec.
619 			     */
620 			    if (sep->se_bi &&
621 				sep->se_bi->bi_fn == (void (*)()) tcpmux) {
622 				    sep = tcpmux(ctrl);
623 				    if (sep == NULL) {
624 					    close(ctrl);
625 					    _exit(0);
626 				    }
627 			    }
628 #ifdef LIBWRAP
629 #ifndef LIBWRAP_INTERNAL
630 			    if (sep->se_bi == 0)
631 #endif
632 			    if (sep->se_accept
633 				&& sep->se_socktype == SOCK_STREAM) {
634 				service = sep->se_server_name ?
635 				    sep->se_server_name : sep->se_service;
636 				request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, NULL);
637 				fromhost(&req);
638 				deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
639 				allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
640 				denied = !hosts_access(&req);
641 				if (denied) {
642 				    syslog(deny_severity,
643 				        "refused connection from %.500s, service %s (%s)",
644 				        eval_client(&req), service, sep->se_proto);
645 				    goto reject;
646 				}
647 				if (log) {
648 				    syslog(allow_severity,
649 				        "connection from %.500s, service %s (%s)",
650 					eval_client(&req), service, sep->se_proto);
651 				}
652 			    }
653 #endif /* LIBWRAP */
654 			    if (sep->se_bi) {
655 				(*sep->se_bi->bi_fn)(ctrl, sep);
656 				/* NOTREACHED */
657 			    } else {
658 				if (debug)
659 					warnx("%d execl %s",
660 						getpid(), sep->se_server);
661 				dup2(ctrl, 0);
662 				close(ctrl);
663 				dup2(0, 1);
664 				dup2(0, 2);
665 				if ((pwd = getpwnam(sep->se_user)) == NULL) {
666 					syslog(LOG_ERR,
667 					    "%s/%s: %s: No such user",
668 						sep->se_service, sep->se_proto,
669 						sep->se_user);
670 					if (sep->se_socktype != SOCK_STREAM)
671 						recv(0, buf, sizeof (buf), 0);
672 					_exit(EX_NOUSER);
673 				}
674 				grp = NULL;
675 				if (   sep->se_group != NULL
676 				    && (grp = getgrnam(sep->se_group)) == NULL
677 				   ) {
678 					syslog(LOG_ERR,
679 					    "%s/%s: %s: No such group",
680 						sep->se_service, sep->se_proto,
681 						sep->se_group);
682 					if (sep->se_socktype != SOCK_STREAM)
683 						recv(0, buf, sizeof (buf), 0);
684 					_exit(EX_NOUSER);
685 				}
686 				if (grp != NULL)
687 					pwd->pw_gid = grp->gr_gid;
688 #ifdef LOGIN_CAP
689 				if ((lc = login_getclass(sep->se_class)) == NULL) {
690 					/* error syslogged by getclass */
691 					syslog(LOG_ERR,
692 					    "%s/%s: %s: login class error",
693 						sep->se_service, sep->se_proto,
694 						sep->se_class);
695 					if (sep->se_socktype != SOCK_STREAM)
696 						recv(0, buf, sizeof (buf), 0);
697 					_exit(EX_NOUSER);
698 				}
699 #endif
700 				if (setsid() < 0) {
701 					syslog(LOG_ERR,
702 						"%s: can't setsid(): %m",
703 						 sep->se_service);
704 					/* _exit(EX_OSERR); not fatal yet */
705 				}
706 #ifdef LOGIN_CAP
707 				if (setusercontext(lc, pwd, pwd->pw_uid,
708 				    LOGIN_SETALL) != 0) {
709 					syslog(LOG_ERR,
710 					 "%s: can't setusercontext(..%s..): %m",
711 					 sep->se_service, sep->se_user);
712 					_exit(EX_OSERR);
713 				}
714 #else
715 				if (pwd->pw_uid) {
716 					if (setlogin(sep->se_user) < 0) {
717 						syslog(LOG_ERR,
718 						 "%s: can't setlogin(%s): %m",
719 						 sep->se_service, sep->se_user);
720 						/* _exit(EX_OSERR); not yet */
721 					}
722 					if (setgid(pwd->pw_gid) < 0) {
723 						syslog(LOG_ERR,
724 						  "%s: can't set gid %d: %m",
725 						  sep->se_service, pwd->pw_gid);
726 						_exit(EX_OSERR);
727 					}
728 					(void) initgroups(pwd->pw_name,
729 							pwd->pw_gid);
730 					if (setuid(pwd->pw_uid) < 0) {
731 						syslog(LOG_ERR,
732 						  "%s: can't set uid %d: %m",
733 						  sep->se_service, pwd->pw_uid);
734 						_exit(EX_OSERR);
735 					}
736 				}
737 #endif
738 				sigaction(SIGPIPE, &sapipe,
739 				    (struct sigaction *)0);
740 				execv(sep->se_server, sep->se_argv);
741 				syslog(LOG_ERR,
742 				    "cannot execute %s: %m", sep->se_server);
743 #ifdef LIBWRAP
744 			    reject:
745 #endif
746 				if (sep->se_socktype != SOCK_STREAM)
747 					recv(0, buf, sizeof (buf), 0);
748 			    }
749 			    if (dofork)
750 				_exit(0);
751 		    }
752 		    if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
753 			    close(ctrl);
754 		}
755 	}
756 }
757 
758 /*
759  * Add a signal flag to the signal flag queue for later handling
760  */
761 
762 void flag_signal(c)
763     char c;
764 {
765 	if (write(signalpipe[1], &c, 1) != 1) {
766 		syslog(LOG_ERR, "write: %m");
767 		exit(EX_OSERR);
768 	}
769 }
770 
771 /*
772  * Record a new child pid for this service. If we've reached the
773  * limit on children, then stop accepting incoming requests.
774  */
775 
776 void
777 addchild(struct servtab *sep, pid_t pid)
778 {
779 #ifdef SANITY_CHECK
780 	if (sep->se_numchild >= sep->se_maxchild) {
781 		syslog(LOG_ERR, "%s: %d >= %d",
782 		    __FUNCTION__, sep->se_numchild, sep->se_maxchild);
783 		exit(EX_SOFTWARE);
784 	}
785 #endif
786 	if (sep->se_maxchild == 0)
787 		return;
788 	sep->se_pids[sep->se_numchild++] = pid;
789 	if (sep->se_numchild == sep->se_maxchild)
790 		disable(sep);
791 }
792 
793 /*
794  * Some child process has exited. See if it's on somebody's list.
795  */
796 
797 void
798 flag_reapchild(signo)
799 	int signo;
800 {
801 	flag_signal('C');
802 }
803 
804 void
805 reapchild()
806 {
807 	int k, status;
808 	pid_t pid;
809 	struct servtab *sep;
810 
811 	for (;;) {
812 		pid = wait3(&status, WNOHANG, (struct rusage *)0);
813 		if (pid <= 0)
814 			break;
815 		if (debug)
816 			warnx("%d reaped, status %#x", pid, status);
817 		for (sep = servtab; sep; sep = sep->se_next) {
818 			for (k = 0; k < sep->se_numchild; k++)
819 				if (sep->se_pids[k] == pid)
820 					break;
821 			if (k == sep->se_numchild)
822 				continue;
823 			if (sep->se_numchild == sep->se_maxchild)
824 				enable(sep);
825 			sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
826 			if (status)
827 				syslog(LOG_WARNING,
828 				    "%s[%d]: exit status 0x%x",
829 				    sep->se_server, pid, status);
830 			break;
831 		}
832 	}
833 }
834 
835 void
836 flag_config(signo)
837 	int signo;
838 {
839 	flag_signal('H');
840 }
841 
842 void config()
843 {
844 	struct servtab *sep, *new, **sepp;
845 	long omask;
846 
847 	if (!setconfig()) {
848 		syslog(LOG_ERR, "%s: %m", CONFIG);
849 		return;
850 	}
851 	for (sep = servtab; sep; sep = sep->se_next)
852 		sep->se_checked = 0;
853 	while ((new = getconfigent())) {
854 		if (getpwnam(new->se_user) == NULL) {
855 			syslog(LOG_ERR,
856 				"%s/%s: No such user '%s', service ignored",
857 				new->se_service, new->se_proto, new->se_user);
858 			continue;
859 		}
860 		if (new->se_group && getgrnam(new->se_group) == NULL) {
861 			syslog(LOG_ERR,
862 				"%s/%s: No such group '%s', service ignored",
863 				new->se_service, new->se_proto, new->se_group);
864 			continue;
865 		}
866 #ifdef LOGIN_CAP
867 		if (login_getclass(new->se_class) == NULL) {
868 			/* error syslogged by getclass */
869 			syslog(LOG_ERR,
870 				"%s/%s: %s: login class error, service ignored",
871 				new->se_service, new->se_proto, new->se_class);
872 			continue;
873 		}
874 #endif
875 		for (sep = servtab; sep; sep = sep->se_next)
876 			if (strcmp(sep->se_service, new->se_service) == 0 &&
877 			    strcmp(sep->se_proto, new->se_proto) == 0)
878 				break;
879 		if (sep != 0) {
880 			int i;
881 
882 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
883 			omask = sigblock(SIGBLOCK);
884 			/* copy over outstanding child pids */
885 			if (sep->se_maxchild && new->se_maxchild) {
886 				new->se_numchild = sep->se_numchild;
887 				if (new->se_numchild > new->se_maxchild)
888 					new->se_numchild = new->se_maxchild;
889 				memcpy(new->se_pids, sep->se_pids,
890 				    new->se_numchild * sizeof(*new->se_pids));
891 			}
892 			SWAP(sep->se_pids, new->se_pids);
893 			sep->se_maxchild = new->se_maxchild;
894 			sep->se_numchild = new->se_numchild;
895 			sep->se_maxcpm = new->se_maxcpm;
896 			/* might need to turn on or off service now */
897 			if (sep->se_fd >= 0) {
898 			      if (sep->se_maxchild
899 				  && sep->se_numchild == sep->se_maxchild) {
900 				      if (FD_ISSET(sep->se_fd, &allsock))
901 					  disable(sep);
902 			      } else {
903 				      if (!FD_ISSET(sep->se_fd, &allsock))
904 					  enable(sep);
905 			      }
906 			}
907 			sep->se_accept = new->se_accept;
908 			SWAP(sep->se_user, new->se_user);
909 			SWAP(sep->se_group, new->se_group);
910 #ifdef LOGIN_CAP
911 			SWAP(sep->se_class, new->se_class);
912 #endif
913 			SWAP(sep->se_server, new->se_server);
914 			SWAP(sep->se_server_name, new->se_server_name);
915 			for (i = 0; i < MAXARGV; i++)
916 				SWAP(sep->se_argv[i], new->se_argv[i]);
917 			sigsetmask(omask);
918 			freeconfig(new);
919 			if (debug)
920 				print_service("REDO", sep);
921 		} else {
922 			sep = enter(new);
923 			if (debug)
924 				print_service("ADD ", sep);
925 		}
926 		sep->se_checked = 1;
927 		if (ISMUX(sep)) {
928 			sep->se_fd = -1;
929 			continue;
930 		}
931 		if (!sep->se_rpc) {
932 			sp = getservbyname(sep->se_service, sep->se_proto);
933 			if (sp == 0) {
934 				syslog(LOG_ERR, "%s/%s: unknown service",
935 			    	sep->se_service, sep->se_proto);
936 				sep->se_checked = 0;
937 				continue;
938 			}
939 			if (sp->s_port != sep->se_ctrladdr.sin_port) {
940 				sep->se_ctrladdr.sin_family = AF_INET;
941 				sep->se_ctrladdr.sin_addr = bind_address;
942 				sep->se_ctrladdr.sin_port = sp->s_port;
943 				if (sep->se_fd >= 0)
944 					close_sep(sep);
945 			}
946 		} else {
947 			rpc = getrpcbyname(sep->se_service);
948 			if (rpc == 0) {
949 				syslog(LOG_ERR, "%s/%s unknown RPC service.",
950 					sep->se_service, sep->se_proto);
951 				if (sep->se_fd != -1)
952 					(void) close(sep->se_fd);
953 				sep->se_fd = -1;
954 					continue;
955 			}
956 			if (rpc->r_number != sep->se_rpc_prog) {
957 				if (sep->se_rpc_prog)
958 					unregisterrpc(sep);
959 				sep->se_rpc_prog = rpc->r_number;
960 				if (sep->se_fd != -1)
961 					(void) close(sep->se_fd);
962 				sep->se_fd = -1;
963 			}
964 		}
965 		if (sep->se_fd == -1)
966 			setup(sep);
967 	}
968 	endconfig();
969 	/*
970 	 * Purge anything not looked at above.
971 	 */
972 	omask = sigblock(SIGBLOCK);
973 	sepp = &servtab;
974 	while ((sep = *sepp)) {
975 		if (sep->se_checked) {
976 			sepp = &sep->se_next;
977 			continue;
978 		}
979 		*sepp = sep->se_next;
980 		if (sep->se_fd >= 0)
981 			close_sep(sep);
982 		if (debug)
983 			print_service("FREE", sep);
984 		if (sep->se_rpc && sep->se_rpc_prog > 0)
985 			unregisterrpc(sep);
986 		freeconfig(sep);
987 		free((char *)sep);
988 	}
989 	(void) sigsetmask(omask);
990 }
991 
992 void
993 unregisterrpc(sep)
994 	struct servtab *sep;
995 {
996         int i;
997         struct servtab *sepp;
998 	long omask;
999 
1000 	omask = sigblock(SIGBLOCK);
1001         for (sepp = servtab; sepp; sepp = sepp->se_next) {
1002                 if (sepp == sep)
1003                         continue;
1004 		if (sep->se_checked == 0 ||
1005                     !sepp->se_rpc ||
1006                     sep->se_rpc_prog != sepp->se_rpc_prog)
1007 			continue;
1008                 return;
1009         }
1010         if (debug)
1011                 print_service("UNREG", sep);
1012         for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++)
1013                 pmap_unset(sep->se_rpc_prog, i);
1014         if (sep->se_fd != -1)
1015                 (void) close(sep->se_fd);
1016         sep->se_fd = -1;
1017 	(void) sigsetmask(omask);
1018 }
1019 
1020 void
1021 flag_retry(signo)
1022 	int signo;
1023 {
1024 	flag_signal('A');
1025 }
1026 
1027 void
1028 retry()
1029 {
1030 	struct servtab *sep;
1031 
1032 	timingout = 0;
1033 	for (sep = servtab; sep; sep = sep->se_next)
1034 		if (sep->se_fd == -1 && !ISMUX(sep))
1035 			setup(sep);
1036 }
1037 
1038 void
1039 setup(sep)
1040 	struct servtab *sep;
1041 {
1042 	int on = 1;
1043 
1044 	if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
1045 		if (debug)
1046 			warn("socket failed on %s/%s",
1047 				sep->se_service, sep->se_proto);
1048 		syslog(LOG_ERR, "%s/%s: socket: %m",
1049 		    sep->se_service, sep->se_proto);
1050 		return;
1051 	}
1052 #define	turnon(fd, opt) \
1053 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1054 	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1055 	    turnon(sep->se_fd, SO_DEBUG) < 0)
1056 		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1057 	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1058 		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1059 #ifdef SO_PRIVSTATE
1060 	if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1061 		syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1062 #endif
1063 #undef turnon
1064 	if (sep->se_type == TTCP_TYPE)
1065 		if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1066 		    (char *)&on, sizeof (on)) < 0)
1067 			syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1068 	if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1069 	    sizeof (sep->se_ctrladdr)) < 0) {
1070 		if (debug)
1071 			warn("bind failed on %s/%s",
1072 				sep->se_service, sep->se_proto);
1073 		syslog(LOG_ERR, "%s/%s: bind: %m",
1074 		    sep->se_service, sep->se_proto);
1075 		(void) close(sep->se_fd);
1076 		sep->se_fd = -1;
1077 		if (!timingout) {
1078 			timingout = 1;
1079 			alarm(RETRYTIME);
1080 		}
1081 		return;
1082 	}
1083         if (sep->se_rpc) {
1084                 int i, len = sizeof(struct sockaddr);
1085 
1086                 if (getsockname(sep->se_fd,
1087 				(struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1088                         syslog(LOG_ERR, "%s/%s: getsockname: %m",
1089                                sep->se_service, sep->se_proto);
1090                         (void) close(sep->se_fd);
1091                         sep->se_fd = -1;
1092                         return;
1093                 }
1094                 if (debug)
1095                         print_service("REG ", sep);
1096                 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1097                         pmap_unset(sep->se_rpc_prog, i);
1098                         pmap_set(sep->se_rpc_prog, i,
1099                                  (sep->se_socktype == SOCK_DGRAM)
1100                                  ? IPPROTO_UDP : IPPROTO_TCP,
1101                                  ntohs(sep->se_ctrladdr.sin_port));
1102                 }
1103 
1104         }
1105 	if (sep->se_socktype == SOCK_STREAM)
1106 		listen(sep->se_fd, 64);
1107 	enable(sep);
1108 	if (debug) {
1109 		warnx("registered %s on %d",
1110 			sep->se_server, sep->se_fd);
1111 	}
1112 }
1113 
1114 /*
1115  * Finish with a service and its socket.
1116  */
1117 void
1118 close_sep(sep)
1119 	struct servtab *sep;
1120 {
1121 	if (sep->se_fd >= 0) {
1122 		if (FD_ISSET(sep->se_fd, &allsock))
1123 			disable(sep);
1124 		(void) close(sep->se_fd);
1125 		sep->se_fd = -1;
1126 	}
1127 	sep->se_count = 0;
1128 	sep->se_numchild = 0;	/* forget about any existing children */
1129 }
1130 
1131 struct servtab *
1132 enter(cp)
1133 	struct servtab *cp;
1134 {
1135 	struct servtab *sep;
1136 	long omask;
1137 
1138 	sep = (struct servtab *)malloc(sizeof (*sep));
1139 	if (sep == (struct servtab *)0) {
1140 		syslog(LOG_ERR, "Out of memory.");
1141 		exit(EX_OSERR);
1142 	}
1143 	*sep = *cp;
1144 	sep->se_fd = -1;
1145 	omask = sigblock(SIGBLOCK);
1146 	sep->se_next = servtab;
1147 	servtab = sep;
1148 	sigsetmask(omask);
1149 	return (sep);
1150 }
1151 
1152 void
1153 enable(struct servtab *sep)
1154 {
1155 	if (debug)
1156 		warnx(
1157 		    "enabling %s, fd %d", sep->se_service, sep->se_fd);
1158 #ifdef SANITY_CHECK
1159 	if (sep->se_fd < 0) {
1160 		syslog(LOG_ERR,
1161 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1162 		exit(EX_SOFTWARE);
1163 	}
1164 	if (ISMUX(sep)) {
1165 		syslog(LOG_ERR,
1166 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1167 		exit(EX_SOFTWARE);
1168 	}
1169 	if (FD_ISSET(sep->se_fd, &allsock)) {
1170 		syslog(LOG_ERR,
1171 		    "%s: %s: not off", __FUNCTION__, sep->se_service);
1172 		exit(EX_SOFTWARE);
1173 	}
1174 #endif
1175 	FD_SET(sep->se_fd, &allsock);
1176 	nsock++;
1177 	if (sep->se_fd > maxsock)
1178 		maxsock = sep->se_fd;
1179 }
1180 
1181 void
1182 disable(struct servtab *sep)
1183 {
1184 	if (debug)
1185 		warnx(
1186 		    "disabling %s, fd %d", sep->se_service, sep->se_fd);
1187 #ifdef SANITY_CHECK
1188 	if (sep->se_fd < 0) {
1189 		syslog(LOG_ERR,
1190 		    "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1191 		exit(EX_SOFTWARE);
1192 	}
1193 	if (ISMUX(sep)) {
1194 		syslog(LOG_ERR,
1195 		    "%s: %s: is mux", __FUNCTION__, sep->se_service);
1196 		exit(EX_SOFTWARE);
1197 	}
1198 	if (!FD_ISSET(sep->se_fd, &allsock)) {
1199 		syslog(LOG_ERR,
1200 		    "%s: %s: not on", __FUNCTION__, sep->se_service);
1201 		exit(EX_SOFTWARE);
1202 	}
1203 	if (nsock == 0) {
1204 		syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
1205 		exit(EX_SOFTWARE);
1206 	}
1207 #endif
1208 	FD_CLR(sep->se_fd, &allsock);
1209 	nsock--;
1210 	if (sep->se_fd == maxsock)
1211 		maxsock--;
1212 }
1213 
1214 FILE	*fconfig = NULL;
1215 struct	servtab serv;
1216 char	line[LINE_MAX];
1217 
1218 int
1219 setconfig()
1220 {
1221 
1222 	if (fconfig != NULL) {
1223 		fseek(fconfig, 0L, SEEK_SET);
1224 		return (1);
1225 	}
1226 	fconfig = fopen(CONFIG, "r");
1227 	return (fconfig != NULL);
1228 }
1229 
1230 void
1231 endconfig()
1232 {
1233 	if (fconfig) {
1234 		(void) fclose(fconfig);
1235 		fconfig = NULL;
1236 	}
1237 }
1238 
1239 struct servtab *
1240 getconfigent()
1241 {
1242 	struct servtab *sep = &serv;
1243 	int argc;
1244 	char *cp, *arg, *s;
1245 	char *versp;
1246 	static char TCPMUX_TOKEN[] = "tcpmux/";
1247 #define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
1248 
1249 more:
1250 	while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
1251 		;
1252 	if (cp == NULL)
1253 		return ((struct servtab *)0);
1254 	/*
1255 	 * clear the static buffer, since some fields (se_ctrladdr,
1256 	 * for example) don't get initialized here.
1257 	 */
1258 	memset((caddr_t)sep, 0, sizeof *sep);
1259 	arg = skip(&cp);
1260 	if (cp == NULL) {
1261 		/* got an empty line containing just blanks/tabs. */
1262 		goto more;
1263 	}
1264 	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1265 		char *c = arg + MUX_LEN;
1266 		if (*c == '+') {
1267 			sep->se_type = MUXPLUS_TYPE;
1268 			c++;
1269 		} else
1270 			sep->se_type = MUX_TYPE;
1271 		sep->se_service = newstr(c);
1272 	} else {
1273 		sep->se_service = newstr(arg);
1274 		sep->se_type = NORM_TYPE;
1275 	}
1276 	arg = sskip(&cp);
1277 	if (strcmp(arg, "stream") == 0)
1278 		sep->se_socktype = SOCK_STREAM;
1279 	else if (strcmp(arg, "dgram") == 0)
1280 		sep->se_socktype = SOCK_DGRAM;
1281 	else if (strcmp(arg, "rdm") == 0)
1282 		sep->se_socktype = SOCK_RDM;
1283 	else if (strcmp(arg, "seqpacket") == 0)
1284 		sep->se_socktype = SOCK_SEQPACKET;
1285 	else if (strcmp(arg, "raw") == 0)
1286 		sep->se_socktype = SOCK_RAW;
1287 	else
1288 		sep->se_socktype = -1;
1289 
1290 	arg = sskip(&cp);
1291 	if (strcmp(arg, "tcp/ttcp") == 0) {
1292 		sep->se_type = TTCP_TYPE;
1293 		sep->se_proto = newstr("tcp");
1294 	} else {
1295 		sep->se_proto = newstr(arg);
1296 	}
1297         if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1298                 memmove(sep->se_proto, sep->se_proto + 4,
1299                     strlen(sep->se_proto) + 1 - 4);
1300                 sep->se_rpc = 1;
1301                 sep->se_rpc_prog = sep->se_rpc_lowvers =
1302 			sep->se_rpc_lowvers = 0;
1303                 sep->se_ctrladdr.sin_family = AF_INET;
1304                 sep->se_ctrladdr.sin_port = 0;
1305                 sep->se_ctrladdr.sin_addr = bind_address;
1306                 if ((versp = rindex(sep->se_service, '/'))) {
1307                         *versp++ = '\0';
1308                         switch (sscanf(versp, "%d-%d",
1309                                        &sep->se_rpc_lowvers,
1310                                        &sep->se_rpc_highvers)) {
1311                         case 2:
1312                                 break;
1313                         case 1:
1314                                 sep->se_rpc_highvers =
1315                                         sep->se_rpc_lowvers;
1316                                 break;
1317                         default:
1318                                 syslog(LOG_ERR,
1319 					"bad RPC version specifier; %s\n",
1320 					sep->se_service);
1321                                 freeconfig(sep);
1322                                 goto more;
1323                         }
1324                 }
1325                 else {
1326                         sep->se_rpc_lowvers =
1327                                 sep->se_rpc_highvers = 1;
1328                 }
1329         }
1330 	arg = sskip(&cp);
1331 	if (!strncmp(arg, "wait", 4))
1332 		sep->se_accept = 0;
1333 	else if (!strncmp(arg, "nowait", 6))
1334 		sep->se_accept = 1;
1335 	else {
1336 		syslog(LOG_ERR,
1337 			"%s: bad wait/nowait for service %s",
1338 			CONFIG, sep->se_service);
1339 		goto more;
1340 	}
1341 	sep->se_maxchild = -1;
1342 	sep->se_maxcpm = -1;
1343 	if ((s = strchr(arg, '/')) != NULL) {
1344 		char *eptr;
1345 		u_long val;
1346 
1347 		val = strtoul(s + 1, &eptr, 10);
1348 		if (eptr == s + 1 || val > MAX_MAXCHLD) {
1349 			syslog(LOG_ERR,
1350 				"%s: bad max-child for service %s",
1351 				CONFIG, sep->se_service);
1352 			goto more;
1353 		}
1354 		if (debug)
1355 			if (!sep->se_accept && val != 1)
1356 				warnx("maxchild=%lu for wait service %s"
1357 				    " not recommended", val, sep->se_service);
1358 		sep->se_maxchild = val;
1359 		if (*eptr == '/')
1360 			sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1361 		/*
1362 		 * explicitly do not check for \0 for future expansion /
1363 		 * backwards compatibility
1364 		 */
1365 	}
1366 	if (ISMUX(sep)) {
1367 		/*
1368 		 * Silently enforce "nowait" mode for TCPMUX services
1369 		 * since they don't have an assigned port to listen on.
1370 		 */
1371 		sep->se_accept = 1;
1372 		if (strcmp(sep->se_proto, "tcp")) {
1373 			syslog(LOG_ERR,
1374 				"%s: bad protocol for tcpmux service %s",
1375 				CONFIG, sep->se_service);
1376 			goto more;
1377 		}
1378 		if (sep->se_socktype != SOCK_STREAM) {
1379 			syslog(LOG_ERR,
1380 				"%s: bad socket type for tcpmux service %s",
1381 				CONFIG, sep->se_service);
1382 			goto more;
1383 		}
1384 	}
1385 	sep->se_user = newstr(sskip(&cp));
1386 #ifdef LOGIN_CAP
1387 	if ((s = strrchr(sep->se_user, '/')) != NULL) {
1388 		*s = '\0';
1389 		sep->se_class = newstr(s + 1);
1390 	} else
1391 		sep->se_class = newstr(RESOURCE_RC);
1392 #endif
1393 	if ((s = strrchr(sep->se_user, ':')) != NULL) {
1394 		*s = '\0';
1395 		sep->se_group = newstr(s + 1);
1396 	} else
1397 		sep->se_group = NULL;
1398 	sep->se_server = newstr(sskip(&cp));
1399 	if ((sep->se_server_name = rindex(sep->se_server, '/')))
1400 		sep->se_server_name++;
1401 	if (strcmp(sep->se_server, "internal") == 0) {
1402 		struct biltin *bi;
1403 
1404 		for (bi = biltins; bi->bi_service; bi++)
1405 			if (bi->bi_socktype == sep->se_socktype &&
1406 			    strcmp(bi->bi_service, sep->se_service) == 0)
1407 				break;
1408 		if (bi->bi_service == 0) {
1409 			syslog(LOG_ERR, "internal service %s unknown",
1410 				sep->se_service);
1411 			goto more;
1412 		}
1413 		sep->se_accept = 1;	/* force accept mode for built-ins */
1414 		sep->se_bi = bi;
1415 	} else
1416 		sep->se_bi = NULL;
1417 	if (sep->se_maxcpm < 0)
1418 		sep->se_maxcpm = maxcpm;
1419 	if (sep->se_maxchild < 0) {	/* apply default max-children */
1420 		if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1421 			sep->se_maxchild = sep->se_bi->bi_maxchild;
1422 		else if (sep->se_accept)
1423 			sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1424 		else
1425 			sep->se_maxchild = 1;
1426 	}
1427 	if (sep->se_maxchild) {
1428 		sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1429 		if (sep->se_pids == NULL) {
1430 			syslog(LOG_ERR, "Out of memory.");
1431 			exit(EX_OSERR);
1432 		}
1433 	}
1434 	argc = 0;
1435 	for (arg = skip(&cp); cp; arg = skip(&cp))
1436 		if (argc < MAXARGV) {
1437 			sep->se_argv[argc++] = newstr(arg);
1438 		} else {
1439 			syslog(LOG_ERR,
1440 				"%s: too many arguments for service %s",
1441 				CONFIG, sep->se_service);
1442 			goto more;
1443 		}
1444 	while (argc <= MAXARGV)
1445 		sep->se_argv[argc++] = NULL;
1446 	return (sep);
1447 }
1448 
1449 void
1450 freeconfig(cp)
1451 	struct servtab *cp;
1452 {
1453 	int i;
1454 
1455 	if (cp->se_service)
1456 		free(cp->se_service);
1457 	if (cp->se_proto)
1458 		free(cp->se_proto);
1459 	if (cp->se_user)
1460 		free(cp->se_user);
1461 	if (cp->se_group)
1462 		free(cp->se_group);
1463 #ifdef LOGIN_CAP
1464 	if (cp->se_class)
1465 		free(cp->se_class);
1466 #endif
1467 	if (cp->se_server)
1468 		free(cp->se_server);
1469 	if (cp->se_pids)
1470 		free(cp->se_pids);
1471 	for (i = 0; i < MAXARGV; i++)
1472 		if (cp->se_argv[i])
1473 			free(cp->se_argv[i]);
1474 }
1475 
1476 
1477 /*
1478  * Safe skip - if skip returns null, log a syntax error in the
1479  * configuration file and exit.
1480  */
1481 char *
1482 sskip(cpp)
1483 	char **cpp;
1484 {
1485 	char *cp;
1486 
1487 	cp = skip(cpp);
1488 	if (cp == NULL) {
1489 		syslog(LOG_ERR, "%s: syntax error", CONFIG);
1490 		exit(EX_DATAERR);
1491 	}
1492 	return (cp);
1493 }
1494 
1495 char *
1496 skip(cpp)
1497 	char **cpp;
1498 {
1499 	char *cp = *cpp;
1500 	char *start;
1501 	char quote = '\0';
1502 
1503 again:
1504 	while (*cp == ' ' || *cp == '\t')
1505 		cp++;
1506 	if (*cp == '\0') {
1507 		int c;
1508 
1509 		c = getc(fconfig);
1510 		(void) ungetc(c, fconfig);
1511 		if (c == ' ' || c == '\t')
1512 			if ((cp = nextline(fconfig)))
1513 				goto again;
1514 		*cpp = (char *)0;
1515 		return ((char *)0);
1516 	}
1517 	if (*cp == '"' || *cp == '\'')
1518 		quote = *cp++;
1519 	start = cp;
1520 	if (quote)
1521 		while (*cp && *cp != quote)
1522 			cp++;
1523 	else
1524 		while (*cp && *cp != ' ' && *cp != '\t')
1525 			cp++;
1526 	if (*cp != '\0')
1527 		*cp++ = '\0';
1528 	*cpp = cp;
1529 	return (start);
1530 }
1531 
1532 char *
1533 nextline(fd)
1534 	FILE *fd;
1535 {
1536 	char *cp;
1537 
1538 	if (fgets(line, sizeof (line), fd) == NULL)
1539 		return ((char *)0);
1540 	cp = strchr(line, '\n');
1541 	if (cp)
1542 		*cp = '\0';
1543 	return (line);
1544 }
1545 
1546 char *
1547 newstr(cp)
1548 	char *cp;
1549 {
1550 	if ((cp = strdup(cp ? cp : "")))
1551 		return (cp);
1552 	syslog(LOG_ERR, "strdup: %m");
1553 	exit(EX_OSERR);
1554 }
1555 
1556 #ifdef OLD_SETPROCTITLE
1557 void
1558 inetd_setproctitle(a, s)
1559 	char *a;
1560 	int s;
1561 {
1562 	int size;
1563 	char *cp;
1564 	struct sockaddr_in sin;
1565 	char buf[80];
1566 
1567 	cp = Argv[0];
1568 	size = sizeof(sin);
1569 	if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1570 		(void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
1571 	else
1572 		(void) sprintf(buf, "-%s", a);
1573 	strncpy(cp, buf, LastArg - cp);
1574 	cp += strlen(cp);
1575 	while (cp < LastArg)
1576 		*cp++ = ' ';
1577 }
1578 #else
1579 void
1580 inetd_setproctitle(a, s)
1581 	char *a;
1582 	int s;
1583 {
1584 	int size;
1585 	struct sockaddr_in sin;
1586 	char buf[80];
1587 
1588 	size = sizeof(sin);
1589 	if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1590 		(void) sprintf(buf, "%s [%s]", a, inet_ntoa(sin.sin_addr));
1591 	else
1592 		(void) sprintf(buf, "%s", a);
1593 	setproctitle("%s", buf);
1594 }
1595 #endif
1596 
1597 
1598 /*
1599  * Internet services provided internally by inetd:
1600  */
1601 #define	BUFSIZE	8192
1602 
1603 #define IDENT_RESPONSE ":ERROR:HIDDEN-USER\r\n"
1604 
1605 /* ARGSUSED */
1606 void
1607 ident_stream(s, sep)		/* Ident service */
1608 	int s;
1609 	struct servtab *sep;
1610 {
1611 	char buffer[BUFSIZE];
1612 	int i, j;
1613 
1614 	inetd_setproctitle(sep->se_service, s);
1615 	j = 0;
1616 	while ((i = read(s, buffer + j, sizeof(buffer) - j)) > 0) {
1617 		j += i;
1618 		buffer[j] = '\0';
1619 		if (strchr(buffer, '\n'))
1620 			break;
1621 		if (strchr(buffer, '\r'))
1622 			break;
1623 	}
1624 	while (j > 0 && (buffer[j-1] == '\n' || buffer[j-1] == '\r'))
1625 		j--;
1626 	write(s, buffer, j);
1627 	write(s, IDENT_RESPONSE, strlen(IDENT_RESPONSE));
1628 	exit(0);
1629 }
1630 /* ARGSUSED */
1631 void
1632 echo_stream(s, sep)		/* Echo service -- echo data back */
1633 	int s;
1634 	struct servtab *sep;
1635 {
1636 	char buffer[BUFSIZE];
1637 	int i;
1638 
1639 	inetd_setproctitle(sep->se_service, s);
1640 	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1641 	    write(s, buffer, i) > 0)
1642 		;
1643 	exit(0);
1644 }
1645 
1646 int check_loop(sin, sep)
1647 	struct sockaddr_in *sin;
1648 	struct servtab *sep;
1649 {
1650 	struct servtab *se2;
1651 
1652 	for (se2 = servtab; se2; se2 = se2->se_next) {
1653 		if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
1654 			continue;
1655 
1656 		if (sin->sin_port == se2->se_ctrladdr.sin_port) {
1657 			syslog(LOG_WARNING,
1658 			       "%s/%s:%s/%s loop request REFUSED from %s",
1659 			       sep->se_service, sep->se_proto,
1660 			       se2->se_service, se2->se_proto,
1661 			       inet_ntoa(sin->sin_addr));
1662 			return 1;
1663 		}
1664 	}
1665 	return 0;
1666 }
1667 
1668 /* ARGSUSED */
1669 void
1670 echo_dg(s, sep)			/* Echo service -- echo data back */
1671 	int s;
1672 	struct servtab *sep;
1673 {
1674 	char buffer[BUFSIZE];
1675 	int i, size;
1676 	struct sockaddr_in sin;
1677 
1678 	size = sizeof(sin);
1679 	if ((i = recvfrom(s, buffer, sizeof(buffer), 0,
1680 			  (struct sockaddr *)&sin, &size)) < 0)
1681 		return;
1682 
1683 	if (check_loop(&sin, sep))
1684 		return;
1685 
1686 	(void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin,
1687 		      sizeof(sin));
1688 }
1689 
1690 /* ARGSUSED */
1691 void
1692 discard_stream(s, sep)		/* Discard service -- ignore data */
1693 	int s;
1694 	struct servtab *sep;
1695 {
1696 	int ret;
1697 	char buffer[BUFSIZE];
1698 
1699 	inetd_setproctitle(sep->se_service, s);
1700 	while (1) {
1701 		while ((ret = read(s, buffer, sizeof(buffer))) > 0)
1702 			;
1703 		if (ret == 0 || errno != EINTR)
1704 			break;
1705 	}
1706 	exit(0);
1707 }
1708 
1709 /* ARGSUSED */
1710 void
1711 discard_dg(s, sep)		/* Discard service -- ignore data */
1712 	int s;
1713 	struct servtab *sep;
1714 {
1715 	char buffer[BUFSIZE];
1716 
1717 	(void) read(s, buffer, sizeof(buffer));
1718 }
1719 
1720 #include <ctype.h>
1721 #define LINESIZ 72
1722 char ring[128];
1723 char *endring;
1724 
1725 void
1726 initring()
1727 {
1728 	int i;
1729 
1730 	endring = ring;
1731 
1732 	for (i = 0; i <= 128; ++i)
1733 		if (isprint(i))
1734 			*endring++ = i;
1735 }
1736 
1737 /* ARGSUSED */
1738 void
1739 chargen_stream(s, sep)		/* Character generator */
1740 	int s;
1741 	struct servtab *sep;
1742 {
1743 	int len;
1744 	char *rs, text[LINESIZ+2];
1745 
1746 	inetd_setproctitle(sep->se_service, s);
1747 
1748 	if (!endring) {
1749 		initring();
1750 		rs = ring;
1751 	}
1752 
1753 	text[LINESIZ] = '\r';
1754 	text[LINESIZ + 1] = '\n';
1755 	for (rs = ring;;) {
1756 		if ((len = endring - rs) >= LINESIZ)
1757 			memmove(text, rs, LINESIZ);
1758 		else {
1759 			memmove(text, rs, len);
1760 			memmove(text + len, ring, LINESIZ - len);
1761 		}
1762 		if (++rs == endring)
1763 			rs = ring;
1764 		if (write(s, text, sizeof(text)) != sizeof(text))
1765 			break;
1766 	}
1767 	exit(0);
1768 }
1769 
1770 /* ARGSUSED */
1771 void
1772 chargen_dg(s, sep)		/* Character generator */
1773 	int s;
1774 	struct servtab *sep;
1775 {
1776 	struct sockaddr_in sin;
1777 	static char *rs;
1778 	int len, size;
1779 	char text[LINESIZ+2];
1780 
1781 	if (endring == 0) {
1782 		initring();
1783 		rs = ring;
1784 	}
1785 
1786 	size = sizeof(sin);
1787 	if (recvfrom(s, text, sizeof(text), 0,
1788 		     (struct sockaddr *)&sin, &size) < 0)
1789 		return;
1790 
1791 	if (check_loop(&sin, sep))
1792 		return;
1793 
1794 	if ((len = endring - rs) >= LINESIZ)
1795 		memmove(text, rs, LINESIZ);
1796 	else {
1797 		memmove(text, rs, len);
1798 		memmove(text + len, ring, LINESIZ - len);
1799 	}
1800 	if (++rs == endring)
1801 		rs = ring;
1802 	text[LINESIZ] = '\r';
1803 	text[LINESIZ + 1] = '\n';
1804 	(void) sendto(s, text, sizeof(text), 0,
1805 		      (struct sockaddr *)&sin, sizeof(sin));
1806 }
1807 
1808 /*
1809  * Return a machine readable date and time, in the form of the
1810  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1811  * returns the number of seconds since midnight, Jan 1, 1970,
1812  * we must add 2208988800 seconds to this figure to make up for
1813  * some seventy years Bell Labs was asleep.
1814  */
1815 
1816 unsigned long
1817 machtime()
1818 {
1819 	struct timeval tv;
1820 
1821 	if (gettimeofday(&tv, (struct timezone *)NULL) < 0) {
1822 		if (debug)
1823 			warnx("unable to get time of day");
1824 		return (0L);
1825 	}
1826 #define	OFFSET ((u_long)25567 * 24*60*60)
1827 	return (htonl((long)(tv.tv_sec + OFFSET)));
1828 #undef OFFSET
1829 }
1830 
1831 /* ARGSUSED */
1832 void
1833 machtime_stream(s, sep)
1834 	int s;
1835 	struct servtab *sep;
1836 {
1837 	unsigned long result;
1838 
1839 	result = machtime();
1840 	(void) write(s, (char *) &result, sizeof(result));
1841 }
1842 
1843 /* ARGSUSED */
1844 void
1845 machtime_dg(s, sep)
1846 	int s;
1847 	struct servtab *sep;
1848 {
1849 	unsigned long result;
1850 	struct sockaddr_in sin;
1851 	int size;
1852 
1853 	size = sizeof(sin);
1854 	if (recvfrom(s, (char *)&result, sizeof(result), 0,
1855 		     (struct sockaddr *)&sin, &size) < 0)
1856 		return;
1857 
1858 	if (check_loop(&sin, sep))
1859 		return;
1860 
1861 	result = machtime();
1862 	(void) sendto(s, (char *) &result, sizeof(result), 0,
1863 		      (struct sockaddr *)&sin, sizeof(sin));
1864 }
1865 
1866 /* ARGSUSED */
1867 void
1868 daytime_stream(s, sep)		/* Return human-readable time of day */
1869 	int s;
1870 	struct servtab *sep;
1871 {
1872 	char buffer[256];
1873 	time_t clock;
1874 
1875 	clock = time((time_t *) 0);
1876 
1877 	(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
1878 	(void) write(s, buffer, strlen(buffer));
1879 }
1880 
1881 /* ARGSUSED */
1882 void
1883 daytime_dg(s, sep)		/* Return human-readable time of day */
1884 	int s;
1885 	struct servtab *sep;
1886 {
1887 	char buffer[256];
1888 	time_t clock;
1889 	struct sockaddr_in sin;
1890 	int size;
1891 
1892 	clock = time((time_t *) 0);
1893 
1894 	size = sizeof(sin);
1895 	if (recvfrom(s, buffer, sizeof(buffer), 0,
1896 		     (struct sockaddr *)&sin, &size) < 0)
1897 		return;
1898 
1899 	if (check_loop(&sin, sep))
1900 		return;
1901 
1902 	(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
1903 	(void) sendto(s, buffer, strlen(buffer), 0,
1904 		      (struct sockaddr *)&sin, sizeof(sin));
1905 }
1906 
1907 /*
1908  * print_service:
1909  *	Dump relevant information to stderr
1910  */
1911 void
1912 print_service(action, sep)
1913 	char *action;
1914 	struct servtab *sep;
1915 {
1916 	fprintf(stderr,
1917 #ifdef LOGIN_CAP
1918 	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s class=%s builtin=%p server=%s\n",
1919 #else
1920 	    "%s: %s proto=%s accept=%d max=%d user=%s group=%s builtin=%p server=%s\n",
1921 #endif
1922 	    action, sep->se_service, sep->se_proto,
1923 	    sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
1924 #ifdef LOGIN_CAP
1925 	    sep->se_class,
1926 #endif
1927 	    (void *) sep->se_bi, sep->se_server);
1928 }
1929 
1930 /*
1931  *  Based on TCPMUX.C by Mark K. Lottor November 1988
1932  *  sri-nic::ps:<mkl>tcpmux.c
1933  */
1934 
1935 
1936 static int		/* # of characters upto \r,\n or \0 */
1937 getline(fd, buf, len)
1938 	int fd;
1939 	char *buf;
1940 	int len;
1941 {
1942 	int count = 0, n;
1943 	struct sigaction sa;
1944 
1945 	sa.sa_flags = 0;
1946 	sigemptyset(&sa.sa_mask);
1947 	sa.sa_handler = SIG_DFL;
1948 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
1949 	do {
1950 		alarm(10);
1951 		n = read(fd, buf, len-count);
1952 		alarm(0);
1953 		if (n == 0)
1954 			return (count);
1955 		if (n < 0)
1956 			return (-1);
1957 		while (--n >= 0) {
1958 			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
1959 				return (count);
1960 			count++;
1961 			buf++;
1962 		}
1963 	} while (count < len);
1964 	return (count);
1965 }
1966 
1967 #define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
1968 
1969 #define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
1970 
1971 struct servtab *
1972 tcpmux(s)
1973 	int s;
1974 {
1975 	struct servtab *sep;
1976 	char service[MAX_SERV_LEN+1];
1977 	int len;
1978 
1979 	/* Get requested service name */
1980 	if ((len = getline(s, service, MAX_SERV_LEN)) < 0) {
1981 		strwrite(s, "-Error reading service name\r\n");
1982 		return (NULL);
1983 	}
1984 	service[len] = '\0';
1985 
1986 	if (debug)
1987 		warnx("tcpmux: someone wants %s", service);
1988 
1989 	/*
1990 	 * Help is a required command, and lists available services,
1991 	 * one per line.
1992 	 */
1993 	if (!strcasecmp(service, "help")) {
1994 		for (sep = servtab; sep; sep = sep->se_next) {
1995 			if (!ISMUX(sep))
1996 				continue;
1997 			(void)write(s,sep->se_service,strlen(sep->se_service));
1998 			strwrite(s, "\r\n");
1999 		}
2000 		return (NULL);
2001 	}
2002 
2003 	/* Try matching a service in inetd.conf with the request */
2004 	for (sep = servtab; sep; sep = sep->se_next) {
2005 		if (!ISMUX(sep))
2006 			continue;
2007 		if (!strcasecmp(service, sep->se_service)) {
2008 			if (ISMUXPLUS(sep)) {
2009 				strwrite(s, "+Go\r\n");
2010 			}
2011 			return (sep);
2012 		}
2013 	}
2014 	strwrite(s, "-Service not available\r\n");
2015 	return (NULL);
2016 }
2017 
2018 #define CPMHSIZE	256
2019 #define CPMHMASK	(CPMHSIZE-1)
2020 #define CHTGRAN		10
2021 #define CHTSIZE		6
2022 
2023 typedef struct CTime {
2024 	unsigned long 	ct_Ticks;
2025 	int		ct_Count;
2026 } CTime;
2027 
2028 typedef struct CHash {
2029 	struct in_addr	ch_Addr;
2030 	time_t		ch_LTime;
2031 	char		*ch_Service;
2032 	CTime		ch_Times[CHTSIZE];
2033 } CHash;
2034 
2035 CHash	CHashAry[CPMHSIZE];
2036 
2037 int
2038 cpmip(sep, ctrl)
2039 	struct servtab *sep;
2040 	int ctrl;
2041 {
2042 	struct sockaddr_in rsin;
2043 	int rsinLen = sizeof(rsin);
2044 	int r = 0;
2045 
2046 	/*
2047 	 * If getpeername() fails, just let it through (if logging is
2048 	 * enabled the condition is caught elsewhere)
2049 	 */
2050 
2051 	if (sep->se_maxcpm > 0 &&
2052 	    getpeername(ctrl, (struct sockaddr *)&rsin, &rsinLen) == 0 ) {
2053 		time_t t = time(NULL);
2054 		int hv = 0xABC3D20F;
2055 		int i;
2056 		int cnt = 0;
2057 		CHash *chBest = NULL;
2058 		unsigned int ticks = t / CHTGRAN;
2059 
2060 		{
2061 			char *p;
2062 			int i;
2063 
2064 			for (i = 0, p = (char *)&rsin.sin_addr;
2065 			    i < sizeof(rsin.sin_addr);
2066 			    ++i, ++p) {
2067 				hv = (hv << 5) ^ (hv >> 23) ^ *p;
2068 			}
2069 			hv = (hv ^ (hv >> 16));
2070 		}
2071 		for (i = 0; i < 5; ++i) {
2072 			CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2073 
2074 			if (rsin.sin_addr.s_addr == ch->ch_Addr.s_addr &&
2075 			    ch->ch_Service && strcmp(sep->se_service,
2076 			    ch->ch_Service) == 0) {
2077 				chBest = ch;
2078 				break;
2079 			}
2080 			if (chBest == NULL || ch->ch_LTime == 0 ||
2081 			    ch->ch_LTime < chBest->ch_LTime) {
2082 				chBest = ch;
2083 			}
2084 		}
2085 		if (rsin.sin_addr.s_addr != chBest->ch_Addr.s_addr ||
2086 		    chBest->ch_Service == NULL ||
2087 		    strcmp(sep->se_service, chBest->ch_Service) != 0) {
2088 			chBest->ch_Addr = rsin.sin_addr;
2089 			if (chBest->ch_Service)
2090 				free(chBest->ch_Service);
2091 			chBest->ch_Service = strdup(sep->se_service);
2092 			bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2093 		}
2094 		chBest->ch_LTime = t;
2095 		{
2096 			CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2097 			if (ct->ct_Ticks != ticks) {
2098 				ct->ct_Ticks = ticks;
2099 				ct->ct_Count = 0;
2100 			}
2101 			++ct->ct_Count;
2102 		}
2103 		for (i = 0; i < CHTSIZE; ++i) {
2104 			CTime *ct = &chBest->ch_Times[i];
2105 			if (ct->ct_Ticks <= ticks &&
2106 			    ct->ct_Ticks >= ticks - CHTSIZE) {
2107 				cnt += ct->ct_Count;
2108 			}
2109 		}
2110 		if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
2111 			r = -1;
2112 			syslog(LOG_ERR,
2113 			    "%s from %s exceeded counts/min (limit %d/min)",
2114 			    sep->se_service, inet_ntoa(rsin.sin_addr),
2115 			    sep->se_maxcpm);
2116 		}
2117 	}
2118 	return(r);
2119 }
2120