]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/inetd/inetd.c
This commit was generated by cvs2svn to compensate for changes in r94691,
[FreeBSD/FreeBSD.git] / usr.sbin / inetd / inetd.c
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   "$FreeBSD$";
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 begin with
69  * a space or tab.  All fields must be present in each entry.
70  *
71  *      service name                    must be in /etc/services
72  *                                      or name a tcpmux service 
73  *                                      or specify a unix domain socket
74  *      socket type                     stream/dgram/raw/rdm/seqpacket
75  *      protocol                        tcp[4][6][/faith,ttcp], udp[4][6], unix
76  *      wait/nowait                     single-threaded/multi-threaded
77  *      user                            user to run daemon as
78  *      server program                  full path name
79  *      server program arguments        maximum of MAXARGS (20)
80  *
81  * TCP services without official port numbers are handled with the
82  * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
83  * requests. When a connection is made from a foreign host, the service
84  * requested is passed to tcpmux, which looks it up in the servtab list
85  * and returns the proper entry for the service. Tcpmux returns a
86  * negative reply if the service doesn't exist, otherwise the invoked
87  * server is expected to return the positive reply if the service type in
88  * inetd.conf file has the prefix "tcpmux/". If the service type has the
89  * prefix "tcpmux/+", tcpmux will return the positive reply for the
90  * process; this is for compatibility with older server code, and also
91  * allows you to invoke programs that use stdin/stdout without putting any
92  * special server code in them. Services that use tcpmux are "nowait"
93  * because they do not have a well-known port and hence cannot listen
94  * for new requests.
95  *
96  * For RPC services
97  *      service name/version            must be in /etc/rpc
98  *      socket type                     stream/dgram/raw/rdm/seqpacket
99  *      protocol                        rpc/tcp, rpc/udp
100  *      wait/nowait                     single-threaded/multi-threaded
101  *      user                            user to run daemon as
102  *      server program                  full path name
103  *      server program arguments        maximum of MAXARGS
104  *
105  * Comment lines are indicated by a `#' in column 1.
106  *
107  * #ifdef IPSEC
108  * Comment lines that start with "#@" denote IPsec policy string, as described
109  * in ipsec_set_policy(3).  This will affect all the following items in
110  * inetd.conf(8).  To reset the policy, just use "#@" line.  By default,
111  * there's no IPsec policy.
112  * #endif
113  */
114 #include <sys/param.h>
115 #include <sys/ioctl.h>
116 #include <sys/wait.h>
117 #include <sys/time.h>
118 #include <sys/resource.h>
119 #include <sys/stat.h>
120 #include <sys/un.h>
121
122 #include <netinet/in.h>
123 #include <netinet/tcp.h>
124 #include <arpa/inet.h>
125 #include <rpc/rpc.h>
126 #include <rpc/pmap_clnt.h>
127
128 #include <errno.h>
129 #include <err.h>
130 #include <fcntl.h>
131 #include <grp.h>
132 #include <netdb.h>
133 #include <pwd.h>
134 #include <signal.h>
135 #include <stdio.h>
136 #include <stdlib.h>
137 #include <string.h>
138 #include <syslog.h>
139 #include <tcpd.h>
140 #include <unistd.h>
141 #include <libutil.h>
142 #include <sysexits.h>
143 #include <ctype.h>
144
145 #include "inetd.h"
146 #include "pathnames.h"
147
148 #ifdef IPSEC
149 #include <netinet6/ipsec.h>
150 #ifndef IPSEC_POLICY_IPSEC      /* no ipsec support on old ipsec */
151 #undef IPSEC
152 #endif
153 #endif
154
155 /* wrapper for KAME-special getnameinfo() */
156 #ifndef NI_WITHSCOPEID
157 #define NI_WITHSCOPEID  0
158 #endif
159
160 #ifndef LIBWRAP_ALLOW_FACILITY
161 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
162 #endif
163 #ifndef LIBWRAP_ALLOW_SEVERITY
164 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
165 #endif
166 #ifndef LIBWRAP_DENY_FACILITY
167 # define LIBWRAP_DENY_FACILITY LOG_AUTH
168 #endif
169 #ifndef LIBWRAP_DENY_SEVERITY
170 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
171 #endif
172
173 #define ISWRAP(sep)     \
174            ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
175         && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
176         && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
177             || (sep)->se_socktype == SOCK_DGRAM))
178
179 #ifdef LOGIN_CAP
180 #include <login_cap.h>
181
182 /* see init.c */
183 #define RESOURCE_RC "daemon"
184
185 #endif
186
187 #ifndef MAXCHILD
188 #define MAXCHILD        -1              /* maximum number of this service
189                                            < 0 = no limit */
190 #endif
191
192 #ifndef MAXCPM
193 #define MAXCPM          -1              /* rate limit invocations from a
194                                            single remote address,
195                                            < 0 = no limit */
196 #endif
197
198 #ifndef TOOMANY
199 #define TOOMANY         256             /* don't start more than TOOMANY */
200 #endif
201 #define CNT_INTVL       60              /* servers in CNT_INTVL sec. */
202 #define RETRYTIME       (60*10)         /* retry after bind or server fail */
203 #define MAX_MAXCHLD     32767           /* max allowable max children */
204
205 #define SIGBLOCK        (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
206
207 void            close_sep __P((struct servtab *));
208 void            flag_signal __P((int));
209 void            flag_config __P((int));
210 void            config __P((void));
211 int             cpmip __P((const struct servtab *, int));
212 void            endconfig __P((void));
213 struct servtab *enter __P((struct servtab *));
214 void            freeconfig __P((struct servtab *));
215 struct servtab *getconfigent __P((void));
216 int             matchservent __P((const char *, const char *, const char *));
217 char           *nextline __P((FILE *));
218 void            addchild __P((struct servtab *, int));
219 void            flag_reapchild __P((int));
220 void            reapchild __P((void));
221 void            enable __P((struct servtab *));
222 void            disable __P((struct servtab *));
223 void            flag_retry __P((int));
224 void            retry __P((void));
225 int             setconfig __P((void));
226 void            setup __P((struct servtab *));
227 #ifdef IPSEC
228 void            ipsecsetup __P((struct servtab *));
229 #endif
230 void            unregisterrpc __P((register struct servtab *sep));
231
232 int     allow_severity;
233 int     deny_severity;
234 int     wrap_ex = 0;
235 int     wrap_bi = 0;
236 int     debug = 0;
237 int     log = 0;
238 int     maxsock;                        /* highest-numbered descriptor */
239 fd_set  allsock;
240 int     options;
241 int     timingout;
242 int     toomany = TOOMANY;
243 int     maxchild = MAXCHILD;
244 int     maxcpm = MAXCPM;
245 struct  servent *sp;
246 struct  rpcent *rpc;
247 char    *hostname = NULL;
248 struct  sockaddr_in *bind_sa4;
249 int     no_v4bind = 1;
250 #ifdef INET6
251 struct  sockaddr_in6 *bind_sa6;
252 int     no_v6bind = 1;
253 #endif
254 int     signalpipe[2];
255 #ifdef SANITY_CHECK
256 int     nsock;
257 #endif
258 uid_t   euid;
259 gid_t   egid;
260 mode_t  mask;
261
262 struct  servtab *servtab;
263
264 extern struct biltin biltins[];
265
266 #define NUMINT  (sizeof(intab) / sizeof(struct inent))
267 const char      *CONFIG = _PATH_INETDCONF;
268 const char      *pid_file = _PATH_INETDPID;
269
270 int
271 getvalue(arg, value, whine)
272         const char *arg, *whine;
273         int  *value;
274 {
275         int  tmp;
276         char *p;
277
278         tmp = strtol(arg, &p, 0);
279         if (tmp < 0 || *p) {
280                 syslog(LOG_ERR, whine, arg);
281                 return 1;                       /* failure */
282         }
283         *value = tmp;
284         return 0;                               /* success */
285 }
286
287 int
288 main(argc, argv)
289         int argc;
290         char *argv[];
291 {
292         struct servtab *sep;
293         struct passwd *pwd;
294         struct group *grp;
295         struct sigaction sa, saalrm, sachld, sahup, sapipe;
296         int tmpint, ch, dofork;
297         pid_t pid;
298         char buf[50];
299 #ifdef LOGIN_CAP
300         login_cap_t *lc = NULL;
301 #endif
302         struct request_info req;
303         int denied;
304         char *service = NULL;
305         union {
306                 struct sockaddr peer_un;
307                 struct sockaddr_in peer_un4;
308                 struct sockaddr_in6 peer_un6;
309                 struct sockaddr_storage peer_max;
310         } p_un;
311 #define peer    p_un.peer_un
312 #define peer4   p_un.peer_un4
313 #define peer6   p_un.peer_un6
314 #define peermax p_un.peer_max
315         int i;
316         struct addrinfo hints, *res;
317         const char *servname;
318         int error;
319
320         openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
321
322         while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:")) != -1)
323                 switch(ch) {
324                 case 'd':
325                         debug = 1;
326                         options |= SO_DEBUG;
327                         break;
328                 case 'l':
329                         log = 1;
330                         break;
331                 case 'R':
332                         getvalue(optarg, &toomany,
333                                 "-R %s: bad value for service invocation rate");
334                         break;
335                 case 'c':
336                         getvalue(optarg, &maxchild,
337                                 "-c %s: bad value for maximum children");
338                         break;
339                 case 'C':
340                         getvalue(optarg, &maxcpm,
341                                 "-C %s: bad value for maximum children/minute");
342                         break;
343                 case 'a':
344                         hostname = optarg;
345                         break;
346                 case 'p':
347                         pid_file = optarg;
348                         break;
349                 case 'w':
350                         wrap_ex++;
351                         break;
352                 case 'W':
353                         wrap_bi++;
354                         break;
355                 case '?':
356                 default:
357                         syslog(LOG_ERR,
358                                 "usage: inetd [-dlwW] [-a address] [-R rate]"
359                                 " [-c maximum] [-C rate]"
360                                 " [-p pidfile] [conf-file]");
361                         exit(EX_USAGE);
362                 }
363         /*
364          * Initialize Bind Addrs.
365          *   When hostname is NULL, wild card bind addrs are obtained from
366          *   getaddrinfo(). But getaddrinfo() requires at least one of
367          *   hostname or servname is non NULL.
368          *   So when hostname is NULL, set dummy value to servname.
369          */
370         servname = (hostname == NULL) ? "discard" /* dummy */ : NULL;
371
372         bzero(&hints, sizeof(struct addrinfo));
373         hints.ai_flags = AI_PASSIVE;
374         hints.ai_family = AF_UNSPEC;
375         error = getaddrinfo(hostname, servname, &hints, &res);
376         if (error != 0) {
377                 syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
378                 if (error == EAI_SYSTEM)
379                         syslog(LOG_ERR, "%s", strerror(errno));
380                 exit(EX_USAGE);
381         }
382         do {
383                 if (res->ai_addr == NULL) {
384                         syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
385                         exit(EX_USAGE);
386                 }
387                 switch (res->ai_addr->sa_family) {
388                 case AF_INET:
389                         if (no_v4bind == 0)
390                                 continue;
391                         bind_sa4 = (struct sockaddr_in *)res->ai_addr;
392                         /* init port num in case servname is dummy */
393                         bind_sa4->sin_port = 0;
394                         no_v4bind = 0;
395                         continue;
396 #ifdef INET6
397                 case AF_INET6:
398                         if (no_v6bind == 0)
399                                 continue;
400                         bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
401                         /* init port num in case servname is dummy */
402                         bind_sa6->sin6_port = 0;
403                         no_v6bind = 0;
404                         continue;
405 #endif
406                 }
407                 if (no_v4bind == 0
408 #ifdef INET6
409                     && no_v6bind == 0
410 #endif
411                     )
412                         break;
413         } while ((res = res->ai_next) != NULL);
414         if (no_v4bind != 0
415 #ifdef INET6
416             && no_v6bind != 0
417 #endif
418             ) {
419                 syslog(LOG_ERR, "-a %s: unknown address family", hostname);
420                 exit(EX_USAGE);
421         }
422
423         euid = geteuid();
424         egid = getegid();
425         umask(mask = umask(0777));
426
427         argc -= optind;
428         argv += optind;
429
430         if (argc > 0)
431                 CONFIG = argv[0];
432         if (debug == 0) {
433                 FILE *fp;
434                 if (daemon(0, 0) < 0) {
435                         syslog(LOG_WARNING, "daemon(0,0) failed: %m");
436                 }
437                 /*
438                  * In case somebody has started inetd manually, we need to
439                  * clear the logname, so that old servers run as root do not
440                  * get the user's logname..
441                  */
442                 if (setlogin("") < 0) {
443                         syslog(LOG_WARNING, "cannot clear logname: %m");
444                         /* no big deal if it fails.. */
445                 }
446                 pid = getpid();
447                 fp = fopen(pid_file, "w");
448                 if (fp) {
449                         fprintf(fp, "%ld\n", (long)pid);
450                         fclose(fp);
451                 } else {
452                         syslog(LOG_WARNING, "%s: %m", pid_file);
453                 }
454         }
455         sa.sa_flags = 0;
456         sigemptyset(&sa.sa_mask);
457         sigaddset(&sa.sa_mask, SIGALRM);
458         sigaddset(&sa.sa_mask, SIGCHLD);
459         sigaddset(&sa.sa_mask, SIGHUP);
460         sa.sa_handler = flag_retry;
461         sigaction(SIGALRM, &sa, &saalrm);
462         config();
463         sa.sa_handler = flag_config;
464         sigaction(SIGHUP, &sa, &sahup);
465         sa.sa_handler = flag_reapchild;
466         sigaction(SIGCHLD, &sa, &sachld);
467         sa.sa_handler = SIG_IGN;
468         sigaction(SIGPIPE, &sa, &sapipe);
469
470         {
471                 /* space for daemons to overwrite environment for ps */
472 #define DUMMYSIZE       100
473                 char dummy[DUMMYSIZE];
474
475                 (void)memset(dummy, 'x', DUMMYSIZE - 1);
476                 dummy[DUMMYSIZE - 1] = '\0';
477                 (void)setenv("inetd_dummy", dummy, 1);
478         }
479
480         if (pipe(signalpipe) != 0) {
481                 syslog(LOG_ERR, "pipe: %m");
482                 exit(EX_OSERR);
483         }
484         FD_SET(signalpipe[0], &allsock);
485 #ifdef SANITY_CHECK
486         nsock++;
487 #endif
488         if (signalpipe[0] > maxsock)
489             maxsock = signalpipe[0];
490         if (signalpipe[1] > maxsock)
491             maxsock = signalpipe[1];
492
493         for (;;) {
494             int n, ctrl;
495             fd_set readable;
496
497 #ifdef SANITY_CHECK
498             if (nsock == 0) {
499                 syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
500                 exit(EX_SOFTWARE);
501             }
502 #endif
503             readable = allsock;
504             if ((n = select(maxsock + 1, &readable, (fd_set *)0,
505                 (fd_set *)0, (struct timeval *)0)) <= 0) {
506                     if (n < 0 && errno != EINTR) {
507                         syslog(LOG_WARNING, "select: %m");
508                         sleep(1);
509                     }
510                     continue;
511             }
512             /* handle any queued signal flags */
513             if (FD_ISSET(signalpipe[0], &readable)) {
514                 int nsig;
515                 if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) {
516                     syslog(LOG_ERR, "ioctl: %m");
517                     exit(EX_OSERR);
518                 }
519                 while (--nsig >= 0) {
520                     char c;
521                     if (read(signalpipe[0], &c, 1) != 1) {
522                         syslog(LOG_ERR, "read: %m");
523                         exit(EX_OSERR);
524                     }
525                     if (debug)
526                         warnx("handling signal flag %c", c);
527                     switch(c) {
528                     case 'A': /* sigalrm */
529                         retry();
530                         break;
531                     case 'C': /* sigchld */
532                         reapchild();
533                         break;
534                     case 'H': /* sighup */
535                         config();
536                         break;
537                     }
538                 }
539             }
540             for (sep = servtab; n && sep; sep = sep->se_next)
541                 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
542                     n--;
543                     if (debug)
544                             warnx("someone wants %s", sep->se_service);
545                     if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
546                             i = 1;
547                             if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
548                                     syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m");
549                             ctrl = accept(sep->se_fd, (struct sockaddr *)0,
550                                 (socklen_t *)0);
551                             if (debug)
552                                     warnx("accept, ctrl %d", ctrl);
553                             if (ctrl < 0) {
554                                     if (errno != EINTR)
555                                             syslog(LOG_WARNING,
556                                                 "accept (for %s): %m",
557                                                 sep->se_service);
558                                       if (sep->se_accept &&
559                                           sep->se_socktype == SOCK_STREAM)
560                                               close(ctrl);
561                                     continue;
562                             }
563                             i = 0;
564                             if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
565                                     syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m");
566                             if (ioctl(ctrl, FIONBIO, &i) < 0)
567                                     syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m");
568                             if (cpmip(sep, ctrl) < 0) {
569                                 close(ctrl);
570                                 continue;
571                             }
572                     } else
573                             ctrl = sep->se_fd;
574                     if (log && !ISWRAP(sep)) {
575                             char pname[INET6_ADDRSTRLEN] = "unknown";
576                             socklen_t sl;
577                             sl = sizeof peermax;
578                             if (getpeername(ctrl, (struct sockaddr *)
579                                             &peermax, &sl)) {
580                                     sl = sizeof peermax;
581                                     if (recvfrom(ctrl, buf, sizeof(buf),
582                                         MSG_PEEK,
583                                         (struct sockaddr *)&peermax,
584                                         &sl) >= 0) {
585                                       getnameinfo((struct sockaddr *)&peermax,
586                                                   peer.sa_len,
587                                                   pname, sizeof(pname),
588                                                   NULL, 0, 
589                                                   NI_NUMERICHOST|
590                                                   NI_WITHSCOPEID);
591                                     }
592                             } else {
593                                     getnameinfo((struct sockaddr *)&peermax,
594                                                 peer.sa_len,
595                                                 pname, sizeof(pname),
596                                                 NULL, 0, 
597                                                 NI_NUMERICHOST|
598                                                 NI_WITHSCOPEID);
599                             }
600                             syslog(LOG_INFO,"%s from %s", sep->se_service, pname);
601                     }
602                     (void) sigblock(SIGBLOCK);
603                     pid = 0;
604                     /*
605                      * Fork for all external services, builtins which need to
606                      * fork and anything we're wrapping (as wrapping might
607                      * block or use hosts_options(5) twist).
608                      */
609                     dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep);
610                     if (dofork) {
611                             if (sep->se_count++ == 0)
612                                 (void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
613                             else if (toomany > 0 && sep->se_count >= toomany) {
614                                 struct timeval now;
615
616                                 (void)gettimeofday(&now, (struct timezone *)NULL);
617                                 if (now.tv_sec - sep->se_time.tv_sec >
618                                     CNT_INTVL) {
619                                         sep->se_time = now;
620                                         sep->se_count = 1;
621                                 } else {
622                                         syslog(LOG_ERR,
623                         "%s/%s server failing (looping), service terminated",
624                                             sep->se_service, sep->se_proto);
625                                         if (sep->se_accept &&
626                                             sep->se_socktype == SOCK_STREAM)
627                                                 close(ctrl);
628                                         close_sep(sep);
629                                         sigsetmask(0L);
630                                         if (!timingout) {
631                                                 timingout = 1;
632                                                 alarm(RETRYTIME);
633                                         }
634                                         continue;
635                                 }
636                             }
637                             pid = fork();
638                     }
639                     if (pid < 0) {
640                             syslog(LOG_ERR, "fork: %m");
641                             if (sep->se_accept &&
642                                 sep->se_socktype == SOCK_STREAM)
643                                     close(ctrl);
644                             sigsetmask(0L);
645                             sleep(1);
646                             continue;
647                     }
648                     if (pid)
649                         addchild(sep, pid);
650                     sigsetmask(0L);
651                     if (pid == 0) {
652                             if (dofork) {
653                                 if (debug)
654                                         warnx("+ closing from %d", maxsock);
655                                 for (tmpint = maxsock; tmpint > 2; tmpint--)
656                                         if (tmpint != ctrl)
657                                                 (void) close(tmpint);
658                                 sigaction(SIGALRM, &saalrm, (struct sigaction *)0);
659                                 sigaction(SIGCHLD, &sachld, (struct sigaction *)0);
660                                 sigaction(SIGHUP, &sahup, (struct sigaction *)0);
661                                 /* SIGPIPE reset before exec */
662                             }
663                             /*
664                              * Call tcpmux to find the real service to exec.
665                              */
666                             if (sep->se_bi &&
667                                 sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) {
668                                     sep = tcpmux(ctrl);
669                                     if (sep == NULL) {
670                                             close(ctrl);
671                                             _exit(0);
672                                     }
673                             }
674                             if (ISWRAP(sep)) {
675                                 inetd_setproctitle("wrapping", ctrl);
676                                 service = sep->se_server_name ?
677                                     sep->se_server_name : sep->se_service;
678                                 request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, NULL);
679                                 fromhost(&req);
680                                 deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
681                                 allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
682                                 denied = !hosts_access(&req);
683                                 if (denied) {
684                                     syslog(deny_severity,
685                                         "refused connection from %.500s, service %s (%s)",
686                                         eval_client(&req), service, sep->se_proto);
687                                     if (sep->se_socktype != SOCK_STREAM)
688                                         recv(ctrl, buf, sizeof (buf), 0);
689                                     if (dofork) {
690                                         sleep(1);
691                                         _exit(0);
692                                     }
693                                 }
694                                 if (log) {
695                                     syslog(allow_severity,
696                                         "connection from %.500s, service %s (%s)",
697                                         eval_client(&req), service, sep->se_proto);
698                                 }
699                             }
700                             if (sep->se_bi) {
701                                 (*sep->se_bi->bi_fn)(ctrl, sep);
702                             } else {
703                                 if (debug)
704                                         warnx("%d execl %s",
705                                                 getpid(), sep->se_server);
706                                 dup2(ctrl, 0);
707                                 close(ctrl);
708                                 dup2(0, 1);
709                                 dup2(0, 2);
710                                 if ((pwd = getpwnam(sep->se_user)) == NULL) {
711                                         syslog(LOG_ERR,
712                                             "%s/%s: %s: no such user",
713                                                 sep->se_service, sep->se_proto,
714                                                 sep->se_user);
715                                         if (sep->se_socktype != SOCK_STREAM)
716                                                 recv(0, buf, sizeof (buf), 0);
717                                         _exit(EX_NOUSER);
718                                 }
719                                 grp = NULL;
720                                 if (   sep->se_group != NULL
721                                     && (grp = getgrnam(sep->se_group)) == NULL
722                                    ) {
723                                         syslog(LOG_ERR,
724                                             "%s/%s: %s: no such group",
725                                                 sep->se_service, sep->se_proto,
726                                                 sep->se_group);
727                                         if (sep->se_socktype != SOCK_STREAM)
728                                                 recv(0, buf, sizeof (buf), 0);
729                                         _exit(EX_NOUSER);
730                                 }
731                                 if (grp != NULL)
732                                         pwd->pw_gid = grp->gr_gid;
733 #ifdef LOGIN_CAP
734                                 if ((lc = login_getclass(sep->se_class)) == NULL) {
735                                         /* error syslogged by getclass */
736                                         syslog(LOG_ERR,
737                                             "%s/%s: %s: login class error",
738                                                 sep->se_service, sep->se_proto,
739                                                 sep->se_class);
740                                         if (sep->se_socktype != SOCK_STREAM)
741                                                 recv(0, buf, sizeof (buf), 0);
742                                         _exit(EX_NOUSER);
743                                 }
744 #endif
745                                 if (setsid() < 0) {
746                                         syslog(LOG_ERR,
747                                                 "%s: can't setsid(): %m",
748                                                  sep->se_service);
749                                         /* _exit(EX_OSERR); not fatal yet */
750                                 }
751 #ifdef LOGIN_CAP
752                                 if (setusercontext(lc, pwd, pwd->pw_uid,
753                                     LOGIN_SETALL) != 0) {
754                                         syslog(LOG_ERR,
755                                          "%s: can't setusercontext(..%s..): %m",
756                                          sep->se_service, sep->se_user);
757                                         _exit(EX_OSERR);
758                                 }
759 #else
760                                 if (pwd->pw_uid) {
761                                         if (setlogin(sep->se_user) < 0) {
762                                                 syslog(LOG_ERR,
763                                                  "%s: can't setlogin(%s): %m",
764                                                  sep->se_service, sep->se_user);
765                                                 /* _exit(EX_OSERR); not yet */
766                                         }
767                                         if (setgid(pwd->pw_gid) < 0) {
768                                                 syslog(LOG_ERR,
769                                                   "%s: can't set gid %d: %m",
770                                                   sep->se_service, pwd->pw_gid);
771                                                 _exit(EX_OSERR);
772                                         }
773                                         (void) initgroups(pwd->pw_name,
774                                                         pwd->pw_gid);
775                                         if (setuid(pwd->pw_uid) < 0) {
776                                                 syslog(LOG_ERR,
777                                                   "%s: can't set uid %d: %m",
778                                                   sep->se_service, pwd->pw_uid);
779                                                 _exit(EX_OSERR);
780                                         }
781                                 }
782 #endif
783                                 sigaction(SIGPIPE, &sapipe,
784                                     (struct sigaction *)0);
785                                 execv(sep->se_server, sep->se_argv);
786                                 syslog(LOG_ERR,
787                                     "cannot execute %s: %m", sep->se_server);
788                                 if (sep->se_socktype != SOCK_STREAM)
789                                         recv(0, buf, sizeof (buf), 0);
790                             }
791                             if (dofork)
792                                 _exit(0);
793                     }
794                     if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
795                             close(ctrl);
796                 }
797         }
798 }
799
800 /*
801  * Add a signal flag to the signal flag queue for later handling
802  */
803
804 void
805 flag_signal(c)
806         int c;
807 {
808         char ch = c;
809
810         if (write(signalpipe[1], &ch, 1) != 1) {
811                 syslog(LOG_ERR, "write: %m");
812                 _exit(EX_OSERR);
813         }
814 }
815
816 /*
817  * Record a new child pid for this service. If we've reached the
818  * limit on children, then stop accepting incoming requests.
819  */
820
821 void
822 addchild(struct servtab *sep, pid_t pid)
823 {
824         if (sep->se_maxchild <= 0)
825                 return;
826 #ifdef SANITY_CHECK
827         if (sep->se_numchild >= sep->se_maxchild) {
828                 syslog(LOG_ERR, "%s: %d >= %d",
829                     __FUNCTION__, sep->se_numchild, sep->se_maxchild);
830                 exit(EX_SOFTWARE);
831         }
832 #endif
833         sep->se_pids[sep->se_numchild++] = pid;
834         if (sep->se_numchild == sep->se_maxchild)
835                 disable(sep);
836 }
837
838 /*
839  * Some child process has exited. See if it's on somebody's list.
840  */
841
842 void
843 flag_reapchild(signo)
844         int signo __unused;
845 {
846         flag_signal('C');
847 }
848
849 void
850 reapchild()
851 {
852         int k, status;
853         pid_t pid;
854         struct servtab *sep;
855
856         for (;;) {
857                 pid = wait3(&status, WNOHANG, (struct rusage *)0);
858                 if (pid <= 0)
859                         break;
860                 if (debug)
861                         warnx("%d reaped, status %#x", pid, status);
862                 for (sep = servtab; sep; sep = sep->se_next) {
863                         for (k = 0; k < sep->se_numchild; k++)
864                                 if (sep->se_pids[k] == pid)
865                                         break;
866                         if (k == sep->se_numchild)
867                                 continue;
868                         if (sep->se_numchild == sep->se_maxchild)
869                                 enable(sep);
870                         sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
871                         if (status)
872                                 syslog(LOG_WARNING,
873                                     "%s[%d]: exit status 0x%x",
874                                     sep->se_server, pid, status);
875                         break;
876                 }
877         }
878 }
879
880 void
881 flag_config(signo)
882         int signo __unused;
883 {
884         flag_signal('H');
885 }
886
887 void
888 config()
889 {
890         struct servtab *sep, *new, **sepp;
891         long omask;
892
893         if (!setconfig()) {
894                 syslog(LOG_ERR, "%s: %m", CONFIG);
895                 return;
896         }
897         for (sep = servtab; sep; sep = sep->se_next)
898                 sep->se_checked = 0;
899         while ((new = getconfigent())) {
900                 if (getpwnam(new->se_user) == NULL) {
901                         syslog(LOG_ERR,
902                                 "%s/%s: no such user '%s', service ignored",
903                                 new->se_service, new->se_proto, new->se_user);
904                         continue;
905                 }
906                 if (new->se_group && getgrnam(new->se_group) == NULL) {
907                         syslog(LOG_ERR,
908                                 "%s/%s: no such group '%s', service ignored",
909                                 new->se_service, new->se_proto, new->se_group);
910                         continue;
911                 }
912 #ifdef LOGIN_CAP
913                 if (login_getclass(new->se_class) == NULL) {
914                         /* error syslogged by getclass */
915                         syslog(LOG_ERR,
916                                 "%s/%s: %s: login class error, service ignored",
917                                 new->se_service, new->se_proto, new->se_class);
918                         continue;
919                 }
920 #endif
921                 for (sep = servtab; sep; sep = sep->se_next)
922                         if (strcmp(sep->se_service, new->se_service) == 0 &&
923                             strcmp(sep->se_proto, new->se_proto) == 0 &&
924                             sep->se_socktype == new->se_socktype &&
925                             sep->se_family == new->se_family)
926                                 break;
927                 if (sep != 0) {
928                         int i;
929
930 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
931                         omask = sigblock(SIGBLOCK);
932                         if (sep->se_nomapped != new->se_nomapped) {
933                                 sep->se_nomapped = new->se_nomapped;
934                                 sep->se_reset = 1;
935                         }
936                         /* copy over outstanding child pids */
937                         if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
938                                 new->se_numchild = sep->se_numchild;
939                                 if (new->se_numchild > new->se_maxchild)
940                                         new->se_numchild = new->se_maxchild;
941                                 memcpy(new->se_pids, sep->se_pids,
942                                     new->se_numchild * sizeof(*new->se_pids));
943                         }
944                         SWAP(sep->se_pids, new->se_pids);
945                         sep->se_maxchild = new->se_maxchild;
946                         sep->se_numchild = new->se_numchild;
947                         sep->se_maxcpm = new->se_maxcpm;
948                         sep->se_bi = new->se_bi;
949                         /* might need to turn on or off service now */
950                         if (sep->se_fd >= 0) {
951                               if (sep->se_maxchild > 0
952                                   && sep->se_numchild == sep->se_maxchild) {
953                                       if (FD_ISSET(sep->se_fd, &allsock))
954                                           disable(sep);
955                               } else {
956                                       if (!FD_ISSET(sep->se_fd, &allsock))
957                                           enable(sep);
958                               }
959                         }
960                         sep->se_accept = new->se_accept;
961                         SWAP(sep->se_user, new->se_user);
962                         SWAP(sep->se_group, new->se_group);
963 #ifdef LOGIN_CAP
964                         SWAP(sep->se_class, new->se_class);
965 #endif
966                         SWAP(sep->se_server, new->se_server);
967                         SWAP(sep->se_server_name, new->se_server_name);
968                         for (i = 0; i < MAXARGV; i++)
969                                 SWAP(sep->se_argv[i], new->se_argv[i]);
970 #ifdef IPSEC
971                         SWAP(sep->se_policy, new->se_policy);
972                         ipsecsetup(sep);
973 #endif
974                         sigsetmask(omask);
975                         freeconfig(new);
976                         if (debug)
977                                 print_service("REDO", sep);
978                 } else {
979                         sep = enter(new);
980                         if (debug)
981                                 print_service("ADD ", sep);
982                 }
983                 sep->se_checked = 1;
984                 if (ISMUX(sep)) {
985                         sep->se_fd = -1;
986                         continue;
987                 }
988                 switch (sep->se_family) {
989                 case AF_INET:
990                         if (no_v4bind != 0) {
991                                 sep->se_fd = -1;
992                                 continue;
993                         }
994                         break;
995 #ifdef INET6
996                 case AF_INET6:
997                         if (no_v6bind != 0) {
998                                 sep->se_fd = -1;
999                                 continue;
1000                         }
1001                         break;
1002 #endif
1003                 }
1004                 if (!sep->se_rpc) {
1005                         if (sep->se_family != AF_UNIX) {
1006                                 sp = getservbyname(sep->se_service, sep->se_proto);
1007                                 if (sp == 0) {
1008                                         syslog(LOG_ERR, "%s/%s: unknown service",
1009                                         sep->se_service, sep->se_proto);
1010                                         sep->se_checked = 0;
1011                                         continue;
1012                                 }
1013                         }
1014                         switch (sep->se_family) {
1015                         case AF_INET:
1016                                 if (sp->s_port != sep->se_ctrladdr4.sin_port) {
1017                                         sep->se_ctrladdr4.sin_port =
1018                                                 sp->s_port;
1019                                         sep->se_reset = 1;
1020                                 }
1021                                 break;
1022 #ifdef INET6
1023                         case AF_INET6:
1024                                 if (sp->s_port !=
1025                                     sep->se_ctrladdr6.sin6_port) {
1026                                         sep->se_ctrladdr6.sin6_port =
1027                                                 sp->s_port;
1028                                         sep->se_reset = 1;
1029                                 }
1030                                 break;
1031 #endif
1032                         }
1033                         if (sep->se_reset != 0 && sep->se_fd >= 0)
1034                                 close_sep(sep);
1035                 } else {
1036                         rpc = getrpcbyname(sep->se_service);
1037                         if (rpc == 0) {
1038                                 syslog(LOG_ERR, "%s/%s unknown RPC service",
1039                                         sep->se_service, sep->se_proto);
1040                                 if (sep->se_fd != -1)
1041                                         (void) close(sep->se_fd);
1042                                 sep->se_fd = -1;
1043                                         continue;
1044                         }
1045                         if (rpc->r_number != sep->se_rpc_prog) {
1046                                 if (sep->se_rpc_prog)
1047                                         unregisterrpc(sep);
1048                                 sep->se_rpc_prog = rpc->r_number;
1049                                 if (sep->se_fd != -1)
1050                                         (void) close(sep->se_fd);
1051                                 sep->se_fd = -1;
1052                         }
1053                 }
1054                 if (sep->se_fd == -1)
1055                         setup(sep);
1056         }
1057         endconfig();
1058         /*
1059          * Purge anything not looked at above.
1060          */
1061         omask = sigblock(SIGBLOCK);
1062         sepp = &servtab;
1063         while ((sep = *sepp)) {
1064                 if (sep->se_checked) {
1065                         sepp = &sep->se_next;
1066                         continue;
1067                 }
1068                 *sepp = sep->se_next;
1069                 if (sep->se_fd >= 0)
1070                         close_sep(sep);
1071                 if (debug)
1072                         print_service("FREE", sep);
1073                 if (sep->se_rpc && sep->se_rpc_prog > 0)
1074                         unregisterrpc(sep);
1075                 freeconfig(sep);
1076                 free(sep);
1077         }
1078         (void) sigsetmask(omask);
1079 }
1080
1081 void
1082 unregisterrpc(sep)
1083         struct servtab *sep;
1084 {
1085         u_int i;
1086         struct servtab *sepp;
1087         long omask;
1088
1089         omask = sigblock(SIGBLOCK);
1090         for (sepp = servtab; sepp; sepp = sepp->se_next) {
1091                 if (sepp == sep)
1092                         continue;
1093                 if (sep->se_checked == 0 ||
1094                     !sepp->se_rpc ||
1095                     sep->se_rpc_prog != sepp->se_rpc_prog)
1096                         continue;
1097                 return;
1098         }
1099         if (debug)
1100                 print_service("UNREG", sep);
1101         for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++)
1102                 pmap_unset(sep->se_rpc_prog, i);
1103         if (sep->se_fd != -1)
1104                 (void) close(sep->se_fd);
1105         sep->se_fd = -1;
1106         (void) sigsetmask(omask);
1107 }
1108
1109 void
1110 flag_retry(signo)
1111         int signo __unused;
1112 {
1113         flag_signal('A');
1114 }
1115
1116 void
1117 retry()
1118 {
1119         struct servtab *sep;
1120
1121         timingout = 0;
1122         for (sep = servtab; sep; sep = sep->se_next)
1123                 if (sep->se_fd == -1 && !ISMUX(sep))
1124                         setup(sep);
1125 }
1126
1127 void
1128 setup(sep)
1129         struct servtab *sep;
1130 {
1131         int on = 1;
1132
1133         if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1134                 if (debug)
1135                         warn("socket failed on %s/%s",
1136                                 sep->se_service, sep->se_proto);
1137                 syslog(LOG_ERR, "%s/%s: socket: %m",
1138                     sep->se_service, sep->se_proto);
1139                 return;
1140         }
1141 #define turnon(fd, opt) \
1142 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1143         if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1144             turnon(sep->se_fd, SO_DEBUG) < 0)
1145                 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1146         if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1147                 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1148 #ifdef SO_PRIVSTATE
1149         if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1150                 syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1151 #endif
1152         /* tftpd opens a new connection then needs more infos */
1153         if ((sep->se_family == AF_INET6) &&
1154             (strcmp(sep->se_proto, "udp") == 0) &&
1155             (sep->se_accept == 0) &&
1156             (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO,
1157                         (char *)&on, sizeof (on)) < 0))
1158                 syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
1159 #ifdef IPV6_BINDV6ONLY
1160         if (sep->se_family == AF_INET6) {
1161                 int flag = sep->se_nomapped ? 1 : 0;
1162                 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
1163                                (char *)&flag, sizeof (flag)) < 0)
1164                         syslog(LOG_ERR, "setsockopt (IPV6_BINDV6ONLY): %m");
1165         }
1166 #endif /* IPV6_BINDV6ONLY */
1167 #undef turnon
1168         if (sep->se_type == TTCP_TYPE)
1169                 if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1170                     (char *)&on, sizeof (on)) < 0)
1171                         syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1172 #ifdef IPV6_FAITH
1173         if (sep->se_type == FAITH_TYPE) {
1174                 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
1175                                 sizeof(on)) < 0) {
1176                         syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1177                 }
1178         }
1179 #endif
1180 #ifdef IPSEC
1181         ipsecsetup(sep);
1182 #endif
1183         if (sep->se_family == AF_UNIX) {
1184                 (void) unlink(sep->se_ctrladdr_un.sun_path);
1185                 umask(0777); /* Make socket with conservative permissions */
1186         }
1187         if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1188             sep->se_ctrladdr_size) < 0) {
1189                 if (debug)
1190                         warn("bind failed on %s/%s",
1191                                 sep->se_service, sep->se_proto);
1192                 syslog(LOG_ERR, "%s/%s: bind: %m",
1193                     sep->se_service, sep->se_proto);
1194                 (void) close(sep->se_fd);
1195                 sep->se_fd = -1;
1196                 if (!timingout) {
1197                         timingout = 1;
1198                         alarm(RETRYTIME);
1199                 }
1200                 if (sep->se_family == AF_UNIX)
1201                         umask(mask);
1202                 return;
1203         }
1204         if (sep->se_family == AF_UNIX) {
1205                 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1206                 if (chown(sep->se_service, sep->se_sockuid, sep->se_sockgid) < 0)
1207                         syslog(LOG_ERR, "chown socket: %m");
1208                 if (chmod(sep->se_service, sep->se_sockmode) < 0)
1209                         syslog(LOG_ERR, "chmod socket: %m");
1210                 umask(mask);
1211         }
1212         if (sep->se_rpc) {
1213                 u_int i;
1214                 socklen_t len = sep->se_ctrladdr_size;
1215
1216                 if (sep->se_family != AF_INET) {
1217                         syslog(LOG_ERR,
1218                                "%s/%s: unsupported address family for rpc",
1219                                sep->se_service, sep->se_proto);
1220                         (void) close(sep->se_fd);
1221                         sep->se_fd = -1;
1222                         return;
1223                 }
1224                 if (getsockname(sep->se_fd,
1225                                 (struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1226                         syslog(LOG_ERR, "%s/%s: getsockname: %m",
1227                                sep->se_service, sep->se_proto);
1228                         (void) close(sep->se_fd);
1229                         sep->se_fd = -1;
1230                         return;
1231                 }
1232                 if (debug)
1233                         print_service("REG ", sep);
1234                 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1235                         pmap_unset(sep->se_rpc_prog, i);
1236                         pmap_set(sep->se_rpc_prog, i,
1237                                  (sep->se_socktype == SOCK_DGRAM)
1238                                  ? IPPROTO_UDP : IPPROTO_TCP,
1239                                  ntohs(sep->se_ctrladdr4.sin_port));
1240                 }
1241         }
1242         if (sep->se_socktype == SOCK_STREAM)
1243                 listen(sep->se_fd, 64);
1244         enable(sep);
1245         if (debug) {
1246                 warnx("registered %s on %d",
1247                         sep->se_server, sep->se_fd);
1248         }
1249 }
1250
1251 #ifdef IPSEC
1252 void
1253 ipsecsetup(sep)
1254         struct servtab *sep;
1255 {
1256         char *buf;
1257         char *policy_in = NULL;
1258         char *policy_out = NULL;
1259         int level;
1260         int opt;
1261
1262         switch (sep->se_family) {
1263         case AF_INET:
1264                 level = IPPROTO_IP;
1265                 opt = IP_IPSEC_POLICY;
1266                 break;
1267 #ifdef INET6
1268         case AF_INET6:
1269                 level = IPPROTO_IPV6;
1270                 opt = IPV6_IPSEC_POLICY;
1271                 break;
1272 #endif
1273         default:
1274                 return;
1275         }
1276
1277         if (!sep->se_policy || sep->se_policy[0] == '\0') {
1278                 static char def_in[] = "in entrust", def_out[] = "out entrust";
1279                 policy_in = def_in;
1280                 policy_out = def_out;
1281         } else {
1282                 if (!strncmp("in", sep->se_policy, 2))
1283                         policy_in = sep->se_policy;
1284                 else if (!strncmp("out", sep->se_policy, 3))
1285                         policy_out = sep->se_policy;
1286                 else {
1287                         syslog(LOG_ERR, "invalid security policy \"%s\"",
1288                                 sep->se_policy);
1289                         return;
1290                 }
1291         }
1292
1293         if (policy_in != NULL) {
1294                 buf = ipsec_set_policy(policy_in, strlen(policy_in));
1295                 if (buf != NULL) {
1296                         if (setsockopt(sep->se_fd, level, opt,
1297                                         buf, ipsec_get_policylen(buf)) < 0 &&
1298                             debug != 0)
1299                                 warnx("%s/%s: ipsec initialization failed; %s",
1300                                       sep->se_service, sep->se_proto,
1301                                       policy_in);
1302                         free(buf);
1303                 } else
1304                         syslog(LOG_ERR, "invalid security policy \"%s\"",
1305                                 policy_in);
1306         }
1307         if (policy_out != NULL) {
1308                 buf = ipsec_set_policy(policy_out, strlen(policy_out));
1309                 if (buf != NULL) {
1310                         if (setsockopt(sep->se_fd, level, opt,
1311                                         buf, ipsec_get_policylen(buf)) < 0 &&
1312                             debug != 0)
1313                                 warnx("%s/%s: ipsec initialization failed; %s",
1314                                       sep->se_service, sep->se_proto,
1315                                       policy_out);
1316                         free(buf);
1317                 } else
1318                         syslog(LOG_ERR, "invalid security policy \"%s\"",
1319                                 policy_out);
1320         }
1321 }
1322 #endif
1323
1324 /*
1325  * Finish with a service and its socket.
1326  */
1327 void
1328 close_sep(sep)
1329         struct servtab *sep;
1330 {
1331         if (sep->se_fd >= 0) {
1332                 if (FD_ISSET(sep->se_fd, &allsock))
1333                         disable(sep);
1334                 (void) close(sep->se_fd);
1335                 sep->se_fd = -1;
1336         }
1337         sep->se_count = 0;
1338         sep->se_numchild = 0;   /* forget about any existing children */
1339 }
1340
1341 int
1342 matchservent(name1, name2, proto)
1343         const char *name1, *name2, *proto;
1344 {
1345         char **alias, *p;
1346         struct servent *se;
1347
1348         if (strcmp(proto, "unix") == 0) {
1349                 if ((p = strrchr(name1, '/')) != NULL)
1350                         name1 = p + 1;
1351                 if ((p = strrchr(name2, '/')) != NULL)
1352                         name2 = p + 1;
1353         }
1354         if (strcmp(name1, name2) == 0)
1355                 return(1);
1356         if ((se = getservbyname(name1, proto)) != NULL) {
1357                 if (strcmp(name2, se->s_name) == 0)
1358                         return(1);
1359                 for (alias = se->s_aliases; *alias; alias++)
1360                         if (strcmp(name2, *alias) == 0)
1361                                 return(1);
1362         }
1363         return(0);
1364 }
1365
1366 struct servtab *
1367 enter(cp)
1368         struct servtab *cp;
1369 {
1370         struct servtab *sep;
1371         long omask;
1372
1373         sep = (struct servtab *)malloc(sizeof (*sep));
1374         if (sep == (struct servtab *)0) {
1375                 syslog(LOG_ERR, "malloc: %m");
1376                 exit(EX_OSERR);
1377         }
1378         *sep = *cp;
1379         sep->se_fd = -1;
1380         omask = sigblock(SIGBLOCK);
1381         sep->se_next = servtab;
1382         servtab = sep;
1383         sigsetmask(omask);
1384         return (sep);
1385 }
1386
1387 void
1388 enable(sep)
1389         struct servtab *sep;
1390 {
1391         if (debug)
1392                 warnx(
1393                     "enabling %s, fd %d", sep->se_service, sep->se_fd);
1394 #ifdef SANITY_CHECK
1395         if (sep->se_fd < 0) {
1396                 syslog(LOG_ERR,
1397                     "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1398                 exit(EX_SOFTWARE);
1399         }
1400         if (ISMUX(sep)) {
1401                 syslog(LOG_ERR,
1402                     "%s: %s: is mux", __FUNCTION__, sep->se_service);
1403                 exit(EX_SOFTWARE);
1404         }
1405         if (FD_ISSET(sep->se_fd, &allsock)) {
1406                 syslog(LOG_ERR,
1407                     "%s: %s: not off", __FUNCTION__, sep->se_service);
1408                 exit(EX_SOFTWARE);
1409         }
1410         nsock++;
1411 #endif
1412         FD_SET(sep->se_fd, &allsock);
1413         if (sep->se_fd > maxsock)
1414                 maxsock = sep->se_fd;
1415 }
1416
1417 void
1418 disable(sep)
1419         struct servtab *sep;
1420 {
1421         if (debug)
1422                 warnx(
1423                     "disabling %s, fd %d", sep->se_service, sep->se_fd);
1424 #ifdef SANITY_CHECK
1425         if (sep->se_fd < 0) {
1426                 syslog(LOG_ERR,
1427                     "%s: %s: bad fd", __FUNCTION__, sep->se_service);
1428                 exit(EX_SOFTWARE);
1429         }
1430         if (ISMUX(sep)) {
1431                 syslog(LOG_ERR,
1432                     "%s: %s: is mux", __FUNCTION__, sep->se_service);
1433                 exit(EX_SOFTWARE);
1434         }
1435         if (!FD_ISSET(sep->se_fd, &allsock)) {
1436                 syslog(LOG_ERR,
1437                     "%s: %s: not on", __FUNCTION__, sep->se_service);
1438                 exit(EX_SOFTWARE);
1439         }
1440         if (nsock == 0) {
1441                 syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__);
1442                 exit(EX_SOFTWARE);
1443         }
1444         nsock--;
1445 #endif
1446         FD_CLR(sep->se_fd, &allsock);
1447         if (sep->se_fd == maxsock)
1448                 maxsock--;
1449 }
1450
1451 FILE    *fconfig = NULL;
1452 struct  servtab serv;
1453 char    line[LINE_MAX];
1454
1455 int
1456 setconfig()
1457 {
1458
1459         if (fconfig != NULL) {
1460                 fseek(fconfig, 0L, SEEK_SET);
1461                 return (1);
1462         }
1463         fconfig = fopen(CONFIG, "r");
1464         return (fconfig != NULL);
1465 }
1466
1467 void
1468 endconfig()
1469 {
1470         if (fconfig) {
1471                 (void) fclose(fconfig);
1472                 fconfig = NULL;
1473         }
1474 }
1475
1476 struct servtab *
1477 getconfigent()
1478 {
1479         struct servtab *sep = &serv;
1480         int argc;
1481         char *cp, *arg, *s;
1482         char *versp;
1483         static char TCPMUX_TOKEN[] = "tcpmux/";
1484 #define MUX_LEN         (sizeof(TCPMUX_TOKEN)-1)
1485 #ifdef IPSEC
1486         char *policy = NULL;
1487 #endif
1488         int v4bind = 0;
1489 #ifdef INET6
1490         int v6bind = 0;
1491 #endif
1492
1493 more:
1494         while ((cp = nextline(fconfig)) != NULL) {
1495 #ifdef IPSEC
1496                 /* lines starting with #@ is not a comment, but the policy */
1497                 if (cp[0] == '#' && cp[1] == '@') {
1498                         char *p;
1499                         for (p = cp + 2; p && *p && isspace(*p); p++)
1500                                 ;
1501                         if (*p == '\0') {
1502                                 if (policy)
1503                                         free(policy);
1504                                 policy = NULL;
1505                         } else if (ipsec_get_policylen(p) >= 0) {
1506                                 if (policy)
1507                                         free(policy);
1508                                 policy = newstr(p);
1509                         } else {
1510                                 syslog(LOG_ERR,
1511                                         "%s: invalid ipsec policy \"%s\"",
1512                                         CONFIG, p);
1513                                 exit(EX_CONFIG);
1514                         }
1515                 }
1516 #endif
1517                 if (*cp == '#' || *cp == '\0')
1518                         continue;
1519                 break;
1520         }
1521         if (cp == NULL)
1522                 return ((struct servtab *)0);
1523         /*
1524          * clear the static buffer, since some fields (se_ctrladdr,
1525          * for example) don't get initialized here.
1526          */
1527         memset(sep, 0, sizeof *sep);
1528         arg = skip(&cp);
1529         if (cp == NULL) {
1530                 /* got an empty line containing just blanks/tabs. */
1531                 goto more;
1532         }
1533         if (arg[0] == ':') { /* :user:group:perm: */
1534                 char *user, *group, *perm;
1535                 struct passwd *pw;
1536                 struct group *gr;
1537                 user = arg+1;
1538                 if ((group = strchr(user, ':')) == NULL) {
1539                         syslog(LOG_ERR, "no group after user '%s'", user);
1540                         goto more;
1541                 }
1542                 *group++ = '\0';
1543                 if ((perm = strchr(group, ':')) == NULL) {
1544                         syslog(LOG_ERR, "no mode after group '%s'", group);
1545                         goto more;
1546                 }
1547                 *perm++ = '\0';
1548                 if ((pw = getpwnam(user)) == NULL) {
1549                         syslog(LOG_ERR, "no such user '%s'", user);
1550                         goto more;
1551                 }
1552                 sep->se_sockuid = pw->pw_uid;
1553                 if ((gr = getgrnam(group)) == NULL) {
1554                         syslog(LOG_ERR, "no such user '%s'", group);
1555                         goto more;
1556                 }
1557                 sep->se_sockgid = gr->gr_gid;
1558                 sep->se_sockmode = strtol(perm, &arg, 8);
1559                 if (*arg != ':') {
1560                         syslog(LOG_ERR, "bad mode '%s'", perm);
1561                         goto more;
1562                 }
1563                 *arg++ = '\0';
1564         } else {
1565                 sep->se_sockuid = euid;
1566                 sep->se_sockgid = egid;
1567                 sep->se_sockmode = 0200;
1568         }
1569         if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1570                 char *c = arg + MUX_LEN;
1571                 if (*c == '+') {
1572                         sep->se_type = MUXPLUS_TYPE;
1573                         c++;
1574                 } else
1575                         sep->se_type = MUX_TYPE;
1576                 sep->se_service = newstr(c);
1577         } else {
1578                 sep->se_service = newstr(arg);
1579                 sep->se_type = NORM_TYPE;
1580         }
1581         arg = sskip(&cp);
1582         if (strcmp(arg, "stream") == 0)
1583                 sep->se_socktype = SOCK_STREAM;
1584         else if (strcmp(arg, "dgram") == 0)
1585                 sep->se_socktype = SOCK_DGRAM;
1586         else if (strcmp(arg, "rdm") == 0)
1587                 sep->se_socktype = SOCK_RDM;
1588         else if (strcmp(arg, "seqpacket") == 0)
1589                 sep->se_socktype = SOCK_SEQPACKET;
1590         else if (strcmp(arg, "raw") == 0)
1591                 sep->se_socktype = SOCK_RAW;
1592         else
1593                 sep->se_socktype = -1;
1594
1595         arg = sskip(&cp);
1596         if (strncmp(arg, "tcp", 3) == 0) {
1597                 sep->se_proto = newstr(strsep(&arg, "/"));
1598                 if (arg != NULL) {
1599                         if (strcmp(arg, "ttcp") == 0)
1600                                 sep->se_type = TTCP_TYPE;
1601                         else if (strcmp(arg, "faith") == 0)
1602                                 sep->se_type = FAITH_TYPE;
1603                 }
1604         } else {
1605                 if (sep->se_type == NORM_TYPE &&
1606                     strncmp(arg, "faith/", 6) == 0) {
1607                         arg += 6;
1608                         sep->se_type = FAITH_TYPE;
1609                 }
1610                 sep->se_proto = newstr(arg);
1611         }
1612         if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1613                 if (no_v4bind != 0) {
1614                         syslog(LOG_INFO, "IPv4 bind is ignored for %s",
1615                                sep->se_service);
1616                         freeconfig(sep);
1617                         goto more;
1618                 }
1619                 memmove(sep->se_proto, sep->se_proto + 4,
1620                     strlen(sep->se_proto) + 1 - 4);
1621                 sep->se_rpc = 1;
1622                 sep->se_rpc_prog = sep->se_rpc_lowvers =
1623                         sep->se_rpc_lowvers = 0;
1624                 memcpy(&sep->se_ctrladdr4, bind_sa4,
1625                        sizeof(sep->se_ctrladdr4));
1626                 if ((versp = rindex(sep->se_service, '/'))) {
1627                         *versp++ = '\0';
1628                         switch (sscanf(versp, "%d-%d",
1629                                        &sep->se_rpc_lowvers,
1630                                        &sep->se_rpc_highvers)) {
1631                         case 2:
1632                                 break;
1633                         case 1:
1634                                 sep->se_rpc_highvers =
1635                                         sep->se_rpc_lowvers;
1636                                 break;
1637                         default:
1638                                 syslog(LOG_ERR,
1639                                         "bad RPC version specifier; %s",
1640                                         sep->se_service);
1641                                 freeconfig(sep);
1642                                 goto more;
1643                         }
1644                 }
1645                 else {
1646                         sep->se_rpc_lowvers =
1647                                 sep->se_rpc_highvers = 1;
1648                 }
1649         }
1650         sep->se_nomapped = 0;
1651         while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
1652 #ifdef INET6
1653                 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
1654                         if (no_v6bind != 0) {
1655                                 syslog(LOG_INFO, "IPv6 bind is ignored for %s",
1656                                        sep->se_service);
1657                                 freeconfig(sep);
1658                                 goto more;
1659                         }
1660                         sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1661                         v6bind = 1;
1662                         continue;
1663                 }
1664 #endif
1665                 if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
1666                         sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1667                         v4bind = 1;
1668                         continue;
1669                 }
1670                 /* illegal version num */
1671                 syslog(LOG_ERR, "bad IP version for %s", sep->se_proto);
1672                 freeconfig(sep);
1673                 goto more;
1674         }
1675         if (strcmp(sep->se_proto, "unix") == 0) {
1676                 sep->se_family = AF_UNIX;
1677         } else
1678 #ifdef INET6
1679         if (v6bind != 0) {
1680                 sep->se_family = AF_INET6;
1681                 if (v4bind == 0 || no_v4bind != 0)
1682                         sep->se_nomapped = 1;
1683         } else
1684 #endif
1685         { /* default to v4 bind if not v6 bind */
1686                 if (no_v4bind != 0) {
1687                         syslog(LOG_INFO, "IPv4 bind is ignored for %s",
1688                                sep->se_service);
1689                         freeconfig(sep);
1690                         goto more;
1691                 }
1692                 sep->se_family = AF_INET;
1693         }
1694         /* init ctladdr */
1695         switch(sep->se_family) {
1696         case AF_INET:
1697                 memcpy(&sep->se_ctrladdr4, bind_sa4,
1698                        sizeof(sep->se_ctrladdr4));
1699                 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4);
1700                 break;
1701 #ifdef INET6
1702         case AF_INET6:
1703                 memcpy(&sep->se_ctrladdr6, bind_sa6,
1704                        sizeof(sep->se_ctrladdr6));
1705                 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6);
1706                 break;
1707 #endif
1708         case AF_UNIX:
1709                 if (strlen(sep->se_service) >= sizeof(sep->se_ctrladdr_un.sun_path)) {
1710                         syslog(LOG_ERR, 
1711                             "domain socket pathname too long for service %s",
1712                             sep->se_service);
1713                         goto more;
1714                 }
1715                 memset(&sep->se_ctrladdr, 0, sizeof(sep->se_ctrladdr));
1716                 sep->se_ctrladdr_un.sun_family = sep->se_family;
1717                 sep->se_ctrladdr_un.sun_len = strlen(sep->se_service);
1718                 strcpy(sep->se_ctrladdr_un.sun_path, sep->se_service);
1719                 sep->se_ctrladdr_size = SUN_LEN(&sep->se_ctrladdr_un);
1720         }
1721         arg = sskip(&cp);
1722         if (!strncmp(arg, "wait", 4))
1723                 sep->se_accept = 0;
1724         else if (!strncmp(arg, "nowait", 6))
1725                 sep->se_accept = 1;
1726         else {
1727                 syslog(LOG_ERR,
1728                         "%s: bad wait/nowait for service %s",
1729                         CONFIG, sep->se_service);
1730                 goto more;
1731         }
1732         sep->se_maxchild = -1;
1733         sep->se_maxcpm = -1;
1734         if ((s = strchr(arg, '/')) != NULL) {
1735                 char *eptr;
1736                 u_long val;
1737
1738                 val = strtoul(s + 1, &eptr, 10);
1739                 if (eptr == s + 1 || val > MAX_MAXCHLD) {
1740                         syslog(LOG_ERR,
1741                                 "%s: bad max-child for service %s",
1742                                 CONFIG, sep->se_service);
1743                         goto more;
1744                 }
1745                 if (debug)
1746                         if (!sep->se_accept && val != 1)
1747                                 warnx("maxchild=%lu for wait service %s"
1748                                     " not recommended", val, sep->se_service);
1749                 sep->se_maxchild = val;
1750                 if (*eptr == '/')
1751                         sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1752                 /*
1753                  * explicitly do not check for \0 for future expansion /
1754                  * backwards compatibility
1755                  */
1756         }
1757         if (ISMUX(sep)) {
1758                 /*
1759                  * Silently enforce "nowait" mode for TCPMUX services
1760                  * since they don't have an assigned port to listen on.
1761                  */
1762                 sep->se_accept = 1;
1763                 if (strcmp(sep->se_proto, "tcp")) {
1764                         syslog(LOG_ERR,
1765                                 "%s: bad protocol for tcpmux service %s",
1766                                 CONFIG, sep->se_service);
1767                         goto more;
1768                 }
1769                 if (sep->se_socktype != SOCK_STREAM) {
1770                         syslog(LOG_ERR,
1771                                 "%s: bad socket type for tcpmux service %s",
1772                                 CONFIG, sep->se_service);
1773                         goto more;
1774                 }
1775         }
1776         sep->se_user = newstr(sskip(&cp));
1777 #ifdef LOGIN_CAP
1778         if ((s = strrchr(sep->se_user, '/')) != NULL) {
1779                 *s = '\0';
1780                 sep->se_class = newstr(s + 1);
1781         } else
1782                 sep->se_class = newstr(RESOURCE_RC);
1783 #endif
1784         if ((s = strrchr(sep->se_user, ':')) != NULL) {
1785                 *s = '\0';
1786                 sep->se_group = newstr(s + 1);
1787         } else
1788                 sep->se_group = NULL;
1789         sep->se_server = newstr(sskip(&cp));
1790         if ((sep->se_server_name = rindex(sep->se_server, '/')))
1791                 sep->se_server_name++;
1792         if (strcmp(sep->se_server, "internal") == 0) {
1793                 struct biltin *bi;
1794
1795                 for (bi = biltins; bi->bi_service; bi++)
1796                         if (bi->bi_socktype == sep->se_socktype &&
1797                             matchservent(bi->bi_service, sep->se_service,
1798                             sep->se_proto))
1799                                 break;
1800                 if (bi->bi_service == 0) {
1801                         syslog(LOG_ERR, "internal service %s unknown",
1802                                 sep->se_service);
1803                         goto more;
1804                 }
1805                 sep->se_accept = 1;     /* force accept mode for built-ins */
1806                 sep->se_bi = bi;
1807         } else
1808                 sep->se_bi = NULL;
1809         if (sep->se_maxcpm < 0)
1810                 sep->se_maxcpm = maxcpm;
1811         if (sep->se_maxchild < 0) {     /* apply default max-children */
1812                 if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1813                         sep->se_maxchild = sep->se_bi->bi_maxchild;
1814                 else if (sep->se_accept) 
1815                         sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1816                 else
1817                         sep->se_maxchild = 1;
1818         }
1819         if (sep->se_maxchild > 0) {
1820                 sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1821                 if (sep->se_pids == NULL) {
1822                         syslog(LOG_ERR, "malloc: %m");
1823                         exit(EX_OSERR);
1824                 }
1825         }
1826         argc = 0;
1827         for (arg = skip(&cp); cp; arg = skip(&cp))
1828                 if (argc < MAXARGV) {
1829                         sep->se_argv[argc++] = newstr(arg);
1830                 } else {
1831                         syslog(LOG_ERR,
1832                                 "%s: too many arguments for service %s",
1833                                 CONFIG, sep->se_service);
1834                         goto more;
1835                 }
1836         while (argc <= MAXARGV)
1837                 sep->se_argv[argc++] = NULL;
1838 #ifdef IPSEC
1839         sep->se_policy = policy ? newstr(policy) : NULL;
1840 #endif
1841         return (sep);
1842 }
1843
1844 void
1845 freeconfig(cp)
1846         struct servtab *cp;
1847 {
1848         int i;
1849
1850         if (cp->se_service)
1851                 free(cp->se_service);
1852         if (cp->se_proto)
1853                 free(cp->se_proto);
1854         if (cp->se_user)
1855                 free(cp->se_user);
1856         if (cp->se_group)
1857                 free(cp->se_group);
1858 #ifdef LOGIN_CAP
1859         if (cp->se_class)
1860                 free(cp->se_class);
1861 #endif
1862         if (cp->se_server)
1863                 free(cp->se_server);
1864         if (cp->se_pids)
1865                 free(cp->se_pids);
1866         for (i = 0; i < MAXARGV; i++)
1867                 if (cp->se_argv[i])
1868                         free(cp->se_argv[i]);
1869 #ifdef IPSEC
1870         if (cp->se_policy)
1871                 free(cp->se_policy);
1872 #endif
1873 }
1874
1875
1876 /*
1877  * Safe skip - if skip returns null, log a syntax error in the
1878  * configuration file and exit.
1879  */
1880 char *
1881 sskip(cpp)
1882         char **cpp;
1883 {
1884         char *cp;
1885
1886         cp = skip(cpp);
1887         if (cp == NULL) {
1888                 syslog(LOG_ERR, "%s: syntax error", CONFIG);
1889                 exit(EX_DATAERR);
1890         }
1891         return (cp);
1892 }
1893
1894 char *
1895 skip(cpp)
1896         char **cpp;
1897 {
1898         char *cp = *cpp;
1899         char *start;
1900         char quote = '\0';
1901
1902 again:
1903         while (*cp == ' ' || *cp == '\t')
1904                 cp++;
1905         if (*cp == '\0') {
1906                 int c;
1907
1908                 c = getc(fconfig);
1909                 (void) ungetc(c, fconfig);
1910                 if (c == ' ' || c == '\t')
1911                         if ((cp = nextline(fconfig)))
1912                                 goto again;
1913                 *cpp = (char *)0;
1914                 return ((char *)0);
1915         }
1916         if (*cp == '"' || *cp == '\'')
1917                 quote = *cp++;
1918         start = cp;
1919         if (quote)
1920                 while (*cp && *cp != quote)
1921                         cp++;
1922         else
1923                 while (*cp && *cp != ' ' && *cp != '\t')
1924                         cp++;
1925         if (*cp != '\0')
1926                 *cp++ = '\0';
1927         *cpp = cp;
1928         return (start);
1929 }
1930
1931 char *
1932 nextline(fd)
1933         FILE *fd;
1934 {
1935         char *cp;
1936
1937         if (fgets(line, sizeof (line), fd) == NULL)
1938                 return ((char *)0);
1939         cp = strchr(line, '\n');
1940         if (cp)
1941                 *cp = '\0';
1942         return (line);
1943 }
1944
1945 char *
1946 newstr(cp)
1947         const char *cp;
1948 {
1949         char *cr;
1950
1951         if ((cr = strdup(cp != NULL ? cp : "")))
1952                 return (cr);
1953         syslog(LOG_ERR, "strdup: %m");
1954         exit(EX_OSERR);
1955 }
1956
1957 void
1958 inetd_setproctitle(a, s)
1959         const char *a;
1960         int s;
1961 {
1962         socklen_t size;
1963         struct sockaddr_storage ss;
1964         char buf[80], pbuf[INET6_ADDRSTRLEN];
1965
1966         size = sizeof(ss);
1967         if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1968                 getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
1969                             NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
1970                 (void) sprintf(buf, "%s [%s]", a, pbuf);
1971         } else
1972                 (void) sprintf(buf, "%s", a);
1973         setproctitle("%s", buf);
1974 }
1975
1976 int
1977 check_loop(sa, sep)
1978         const struct sockaddr *sa;
1979         const struct servtab *sep;
1980 {
1981         struct servtab *se2;
1982         char pname[INET6_ADDRSTRLEN];
1983
1984         for (se2 = servtab; se2; se2 = se2->se_next) {
1985                 if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
1986                         continue;
1987
1988                 switch (se2->se_family) {
1989                 case AF_INET:
1990                         if (((const struct sockaddr_in *)sa)->sin_port ==
1991                             se2->se_ctrladdr4.sin_port)
1992                                 goto isloop;
1993                         continue;
1994 #ifdef INET6
1995                 case AF_INET6:
1996                         if (((const struct sockaddr_in *)sa)->sin_port ==
1997                             se2->se_ctrladdr4.sin_port)
1998                                 goto isloop;
1999                         continue;
2000 #endif
2001                 default:
2002                         continue;
2003                 }
2004         isloop:
2005                 getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
2006                             NI_NUMERICHOST|NI_WITHSCOPEID);
2007                 syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
2008                        sep->se_service, sep->se_proto,
2009                        se2->se_service, se2->se_proto,
2010                        pname);
2011                 return 1;
2012         }
2013         return 0;
2014 }
2015
2016 /*
2017  * print_service:
2018  *      Dump relevant information to stderr
2019  */
2020 void
2021 print_service(action, sep)
2022         const char *action;
2023         const struct servtab *sep;
2024 {
2025         fprintf(stderr,
2026             "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2027 #ifdef LOGIN_CAP
2028             "class=%s"
2029 #endif
2030             " builtin=%p server=%s"
2031 #ifdef IPSEC
2032             " policy=\"%s\""
2033 #endif
2034             "\n",
2035             action, sep->se_service, sep->se_proto,
2036             sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
2037 #ifdef LOGIN_CAP
2038             sep->se_class,
2039 #endif
2040             (void *) sep->se_bi, sep->se_server
2041 #ifdef IPSEC
2042             , (sep->se_policy ? sep->se_policy : "")
2043 #endif
2044             );
2045 }
2046
2047 #define CPMHSIZE        256
2048 #define CPMHMASK        (CPMHSIZE-1)
2049 #define CHTGRAN         10
2050 #define CHTSIZE         6
2051
2052 typedef struct CTime {
2053         unsigned long   ct_Ticks;
2054         int             ct_Count;
2055 } CTime;
2056
2057 typedef struct CHash {
2058         union {
2059                 struct in_addr  c4_Addr;
2060                 struct in6_addr c6_Addr;
2061         } cu_Addr;
2062 #define ch_Addr4        cu_Addr.c4_Addr
2063 #define ch_Addr6        cu_Addr.c6_Addr
2064         int             ch_Family;
2065         time_t          ch_LTime;
2066         char            *ch_Service;
2067         CTime           ch_Times[CHTSIZE];
2068 } CHash;
2069
2070 CHash   CHashAry[CPMHSIZE];
2071
2072 int
2073 cpmip(sep, ctrl)
2074         const struct servtab *sep;
2075         int ctrl;
2076 {
2077         struct sockaddr_storage rss;
2078         socklen_t rssLen = sizeof(rss);
2079         int r = 0;
2080
2081         /*
2082          * If getpeername() fails, just let it through (if logging is
2083          * enabled the condition is caught elsewhere)
2084          */
2085
2086         if (sep->se_maxcpm > 0 && 
2087             getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
2088                 time_t t = time(NULL);
2089                 int hv = 0xABC3D20F;
2090                 int i;
2091                 int cnt = 0;
2092                 CHash *chBest = NULL;
2093                 unsigned int ticks = t / CHTGRAN;
2094                 struct sockaddr_in *sin4;
2095 #ifdef INET6
2096                 struct sockaddr_in6 *sin6;
2097 #endif
2098
2099                 sin4 = (struct sockaddr_in *)&rss;
2100 #ifdef INET6
2101                 sin6 = (struct sockaddr_in6 *)&rss;
2102 #endif
2103                 {
2104                         char *p;
2105                         int addrlen;
2106
2107                         switch (rss.ss_family) {
2108                         case AF_INET:
2109                                 p = (char *)&sin4->sin_addr;
2110                                 addrlen = sizeof(struct in_addr);
2111                                 break;
2112 #ifdef INET6
2113                         case AF_INET6:
2114                                 p = (char *)&sin6->sin6_addr;
2115                                 addrlen = sizeof(struct in6_addr);
2116                                 break;
2117 #endif
2118                         default:
2119                                 /* should not happen */
2120                                 return -1;
2121                         }
2122
2123                         for (i = 0; i < addrlen; ++i, ++p) {
2124                                 hv = (hv << 5) ^ (hv >> 23) ^ *p;
2125                         }
2126                         hv = (hv ^ (hv >> 16));
2127                 }
2128                 for (i = 0; i < 5; ++i) {
2129                         CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2130
2131                         if (rss.ss_family == AF_INET &&
2132                             ch->ch_Family == AF_INET &&
2133                             sin4->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
2134                             ch->ch_Service && strcmp(sep->se_service,
2135                             ch->ch_Service) == 0) {
2136                                 chBest = ch;
2137                                 break;
2138                         }
2139 #ifdef INET6
2140                         if (rss.ss_family == AF_INET6 &&
2141                             ch->ch_Family == AF_INET6 &&
2142                             IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2143                                                &ch->ch_Addr6) != 0 &&
2144                             ch->ch_Service && strcmp(sep->se_service,
2145                             ch->ch_Service) == 0) {
2146                                 chBest = ch;
2147                                 break;
2148                         }
2149 #endif
2150                         if (chBest == NULL || ch->ch_LTime == 0 || 
2151                             ch->ch_LTime < chBest->ch_LTime) {
2152                                 chBest = ch;
2153                         }
2154                 }
2155                 if ((rss.ss_family == AF_INET &&
2156                      (chBest->ch_Family != AF_INET ||
2157                       sin4->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
2158                     chBest->ch_Service == NULL ||
2159                     strcmp(sep->se_service, chBest->ch_Service) != 0) {
2160                         chBest->ch_Family = sin4->sin_family;
2161                         chBest->ch_Addr4 = sin4->sin_addr;
2162                         if (chBest->ch_Service)
2163                                 free(chBest->ch_Service);
2164                         chBest->ch_Service = strdup(sep->se_service);
2165                         bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2166                 } 
2167 #ifdef INET6
2168                 if ((rss.ss_family == AF_INET6 &&
2169                      (chBest->ch_Family != AF_INET6 ||
2170                       IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2171                                          &chBest->ch_Addr6) == 0)) ||
2172                     chBest->ch_Service == NULL ||
2173                     strcmp(sep->se_service, chBest->ch_Service) != 0) {
2174                         chBest->ch_Family = sin6->sin6_family;
2175                         chBest->ch_Addr6 = sin6->sin6_addr;
2176                         if (chBest->ch_Service)
2177                                 free(chBest->ch_Service);
2178                         chBest->ch_Service = strdup(sep->se_service);
2179                         bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2180                 }
2181 #endif
2182                 chBest->ch_LTime = t;
2183                 {
2184                         CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2185                         if (ct->ct_Ticks != ticks) {
2186                                 ct->ct_Ticks = ticks;
2187                                 ct->ct_Count = 0;
2188                         }
2189                         ++ct->ct_Count;
2190                 }
2191                 for (i = 0; i < CHTSIZE; ++i) {
2192                         CTime *ct = &chBest->ch_Times[i];
2193                         if (ct->ct_Ticks <= ticks &&
2194                             ct->ct_Ticks >= ticks - CHTSIZE) {
2195                                 cnt += ct->ct_Count;
2196                         }
2197                 }
2198                 if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
2199                         char pname[INET6_ADDRSTRLEN];
2200
2201                         getnameinfo((struct sockaddr *)&rss,
2202                                     ((struct sockaddr *)&rss)->sa_len,
2203                                     pname, sizeof(pname), NULL, 0,
2204                                     NI_NUMERICHOST|NI_WITHSCOPEID);
2205                         r = -1;
2206                         syslog(LOG_ERR,
2207                             "%s from %s exceeded counts/min (limit %d/min)",
2208                             sep->se_service, pname,
2209                             sep->se_maxcpm);
2210                 }
2211         }
2212         return(r);
2213 }