2 * Copyright (c) 1983, 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 * @(#) Copyright (c) 1983, 1991, 1993, 1994 The Regents of the University of California. All rights reserved.
34 * @(#)from: inetd.c 8.4 (Berkeley) 4/13/94
35 * $FreeBSD: src/usr.sbin/inetd/inetd.c,v 1.80.2.11 2003/04/05 13:39:18 dwmalone Exp $
36 * $DragonFly: src/usr.sbin/inetd/inetd.c,v 1.11 2008/05/23 23:40:59 swildner Exp $
40 * Inetd - Internet super-server
42 * This program invokes all internet services as needed. Connection-oriented
43 * services are invoked each time a connection is made, by creating a process.
44 * This process is passed the connection as file descriptor 0 and is expected
45 * to do a getpeername to find out the source host and port.
47 * Datagram oriented services are invoked when a datagram
48 * arrives; a process is created and passed a pending message
49 * on file descriptor 0. Datagram servers may either connect
50 * to their peer, freeing up the original socket for inetd
51 * to receive further messages on, or ``take over the socket'',
52 * processing all arriving datagrams and, eventually, timing
53 * out. The first type of server is said to be ``multi-threaded'';
54 * the second type of server ``single-threaded''.
56 * Inetd uses a configuration file which is read at startup
57 * and, possibly, at some later time in response to a hangup signal.
58 * The configuration file is ``free format'' with fields given in the
59 * order shown below. Continuation lines for an entry must begin with
60 * a space or tab. All fields must be present in each entry.
62 * service name must be in /etc/services
63 * or name a tcpmux service
64 * or specify a unix domain socket
65 * socket type stream/dgram/raw/rdm/seqpacket
66 * protocol tcp[4][6][/faith,ttcp], udp[4][6], unix
67 * wait/nowait single-threaded/multi-threaded
68 * user user to run daemon as
69 * server program full path name
70 * server program arguments maximum of MAXARGS (20)
72 * TCP services without official port numbers are handled with the
73 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
74 * requests. When a connection is made from a foreign host, the service
75 * requested is passed to tcpmux, which looks it up in the servtab list
76 * and returns the proper entry for the service. Tcpmux returns a
77 * negative reply if the service doesn't exist, otherwise the invoked
78 * server is expected to return the positive reply if the service type in
79 * inetd.conf file has the prefix "tcpmux/". If the service type has the
80 * prefix "tcpmux/+", tcpmux will return the positive reply for the
81 * process; this is for compatibility with older server code, and also
82 * allows you to invoke programs that use stdin/stdout without putting any
83 * special server code in them. Services that use tcpmux are "nowait"
84 * because they do not have a well-known port and hence cannot listen
88 * service name/version must be in /etc/rpc
89 * socket type stream/dgram/raw/rdm/seqpacket
90 * protocol rpc/tcp, rpc/udp
91 * wait/nowait single-threaded/multi-threaded
92 * user user to run daemon as
93 * server program full path name
94 * server program arguments maximum of MAXARGS
96 * Comment lines are indicated by a `#' in column 1.
99 * Comment lines that start with "#@" denote IPsec policy string, as described
100 * in ipsec_set_policy(3). This will affect all the following items in
101 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
102 * there's no IPsec policy.
105 #include <sys/param.h>
106 #include <sys/ioctl.h>
107 #include <sys/wait.h>
108 #include <sys/time.h>
109 #include <sys/resource.h>
110 #include <sys/stat.h>
113 #include <netinet/in.h>
114 #include <netinet/tcp.h>
115 #include <arpa/inet.h>
117 #include <rpc/pmap_clnt.h>
134 #include <sysexits.h>
138 #include "pathnames.h"
141 #include <netinet6/ipsec.h>
142 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
147 /* wrapper for KAME-special getnameinfo() */
148 #ifndef NI_WITHSCOPEID
149 #define NI_WITHSCOPEID 0
152 #ifndef LIBWRAP_ALLOW_FACILITY
153 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
155 #ifndef LIBWRAP_ALLOW_SEVERITY
156 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
158 #ifndef LIBWRAP_DENY_FACILITY
159 # define LIBWRAP_DENY_FACILITY LOG_AUTH
161 #ifndef LIBWRAP_DENY_SEVERITY
162 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
165 #define ISWRAP(sep) \
166 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
167 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
168 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
169 || (sep)->se_socktype == SOCK_DGRAM))
172 #include <login_cap.h>
175 #define RESOURCE_RC "daemon"
180 #define MAXCHILD -1 /* maximum number of this service
185 #define MAXCPM -1 /* rate limit invocations from a
186 single remote address,
191 #define MAXPERIP -1 /* maximum number of this service
192 from a single remote address,
197 #define TOOMANY 256 /* don't start more than TOOMANY */
199 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
200 #define RETRYTIME (60*10) /* retry after bind or server fail */
201 #define MAX_MAXCHLD 32767 /* max allowable max children */
203 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
205 void close_sep(struct servtab
*);
206 void flag_signal(int);
207 void flag_config(int);
209 int cpmip(const struct servtab
*, int);
210 void endconfig(void);
211 struct servtab
*enter(struct servtab
*);
212 void freeconfig(struct servtab
*);
213 struct servtab
*getconfigent(void);
214 int matchservent(const char *, const char *, const char *);
215 char *nextline(FILE *);
216 void addchild(struct servtab
*, int);
217 void flag_reapchild(int);
218 void reapchild(void);
219 void enable(struct servtab
*);
220 void disable(struct servtab
*);
221 void flag_retry(int);
224 void setup(struct servtab
*);
226 void ipsecsetup(struct servtab
*);
228 void unregisterrpc(struct servtab
*sep
);
229 static struct conninfo
*search_conn(struct servtab
*sep
, int ctrl
);
230 static int room_conn(struct servtab
*sep
, struct conninfo
*conn
);
231 static void addchild_conn(struct conninfo
*conn
, pid_t pid
);
232 static void reapchild_conn(pid_t pid
);
233 static void free_conn(struct conninfo
*conn
);
234 static void resize_conn(struct servtab
*sep
, int maxperip
);
235 static void free_connlist(struct servtab
*sep
);
236 static void free_proc(struct procinfo
*);
237 static struct procinfo
*search_proc(pid_t pid
, int add
);
238 static int hashval(char *p
, int len
);
246 int maxsock
; /* highest-numbered descriptor */
250 int toomany
= TOOMANY
;
251 int maxchild
= MAXCHILD
;
253 int maxperip
= MAXPERIP
;
256 char *hostname
= NULL
;
257 struct sockaddr_in
*bind_sa4
;
260 struct sockaddr_in6
*bind_sa6
;
271 struct servtab
*servtab
;
273 extern struct biltin biltins
[];
275 #define NUMINT (sizeof(intab) / sizeof(struct inent))
276 const char *CONFIG
= _PATH_INETDCONF
;
277 const char *pid_file
= _PATH_INETDPID
;
279 static LIST_HEAD(, procinfo
) proctable
[PERIPSIZE
];
282 getvalue(const char *arg
, int *value
, const char *whine
)
287 tmp
= strtol(arg
, &p
, 0);
289 syslog(LOG_ERR
, whine
, arg
);
290 return 1; /* failure */
293 return 0; /* success */
297 whichaf(struct request_info
*req
)
301 sa
= (struct sockaddr
*)req
->client
->sin
;
304 if (sa
->sa_family
== AF_INET6
&&
305 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)sa
)->sin6_addr
))
307 return sa
->sa_family
;
311 main(int argc
, char **argv
)
316 struct sigaction sa
, saalrm
, sachld
, sahup
, sapipe
;
321 login_cap_t
*lc
= NULL
;
323 struct request_info req
;
325 char *service
= NULL
;
327 struct sockaddr peer_un
;
328 struct sockaddr_in peer_un4
;
329 struct sockaddr_in6 peer_un6
;
330 struct sockaddr_storage peer_max
;
332 #define peer p_un.peer_un
333 #define peer4 p_un.peer_un4
334 #define peer6 p_un.peer_un6
335 #define peermax p_un.peer_max
337 struct addrinfo hints
, *res
;
338 const char *servname
;
340 struct conninfo
*conn
;
342 openlog("inetd", LOG_PID
| LOG_NOWAIT
| LOG_PERROR
, LOG_DAEMON
);
344 while ((ch
= getopt(argc
, argv
, "dlwWR:a:c:C:p:s:")) != -1)
354 getvalue(optarg
, &toomany
,
355 "-R %s: bad value for service invocation rate");
358 getvalue(optarg
, &maxchild
,
359 "-c %s: bad value for maximum children");
362 getvalue(optarg
, &maxcpm
,
363 "-C %s: bad value for maximum children/minute");
372 getvalue(optarg
, &maxperip
,
373 "-s %s: bad value for maximum children per source address");
384 "usage: inetd [-dlwW] [-a address] [-R rate]"
385 " [-c maximum] [-C rate]"
386 " [-p pidfile] [conf-file]");
390 * Initialize Bind Addrs.
391 * When hostname is NULL, wild card bind addrs are obtained from
392 * getaddrinfo(). But getaddrinfo() requires at least one of
393 * hostname or servname is non NULL.
394 * So when hostname is NULL, set dummy value to servname.
396 servname
= (hostname
== NULL
) ? "discard" /* dummy */ : NULL
;
398 bzero(&hints
, sizeof(struct addrinfo
));
399 hints
.ai_flags
= AI_PASSIVE
;
400 hints
.ai_family
= AF_UNSPEC
;
401 error
= getaddrinfo(hostname
, servname
, &hints
, &res
);
403 syslog(LOG_ERR
, "-a %s: %s", hostname
, gai_strerror(error
));
404 if (error
== EAI_SYSTEM
)
405 syslog(LOG_ERR
, "%s", strerror(errno
));
409 if (res
->ai_addr
== NULL
) {
410 syslog(LOG_ERR
, "-a %s: getaddrinfo failed", hostname
);
413 switch (res
->ai_addr
->sa_family
) {
417 bind_sa4
= (struct sockaddr_in
*)res
->ai_addr
;
418 /* init port num in case servname is dummy */
419 bind_sa4
->sin_port
= 0;
426 bind_sa6
= (struct sockaddr_in6
*)res
->ai_addr
;
427 /* init port num in case servname is dummy */
428 bind_sa6
->sin6_port
= 0;
439 } while ((res
= res
->ai_next
) != NULL
);
445 syslog(LOG_ERR
, "-a %s: unknown address family", hostname
);
451 umask(mask
= umask(0777));
460 if (daemon(0, 0) < 0) {
461 syslog(LOG_WARNING
, "daemon(0,0) failed: %m");
463 /* From now on we don't want syslog messages going to stderr. */
465 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
467 * In case somebody has started inetd manually, we need to
468 * clear the logname, so that old servers run as root do not
469 * get the user's logname..
471 if (setlogin("") < 0) {
472 syslog(LOG_WARNING
, "cannot clear logname: %m");
473 /* no big deal if it fails.. */
476 fp
= fopen(pid_file
, "w");
478 fprintf(fp
, "%ld\n", (long)pid
);
481 syslog(LOG_WARNING
, "%s: %m", pid_file
);
484 for (i
= 0; i
< PERIPSIZE
; ++i
)
485 LIST_INIT(&proctable
[i
]);
487 sigemptyset(&sa
.sa_mask
);
488 sigaddset(&sa
.sa_mask
, SIGALRM
);
489 sigaddset(&sa
.sa_mask
, SIGCHLD
);
490 sigaddset(&sa
.sa_mask
, SIGHUP
);
491 sa
.sa_handler
= flag_retry
;
492 sigaction(SIGALRM
, &sa
, &saalrm
);
494 sa
.sa_handler
= flag_config
;
495 sigaction(SIGHUP
, &sa
, &sahup
);
496 sa
.sa_handler
= flag_reapchild
;
497 sigaction(SIGCHLD
, &sa
, &sachld
);
498 sa
.sa_handler
= SIG_IGN
;
499 sigaction(SIGPIPE
, &sa
, &sapipe
);
502 /* space for daemons to overwrite environment for ps */
503 #define DUMMYSIZE 100
504 char dummy
[DUMMYSIZE
];
506 memset(dummy
, 'x', DUMMYSIZE
- 1);
507 dummy
[DUMMYSIZE
- 1] = '\0';
508 if (setenv("inetd_dummy", dummy
, 1) == -1)
509 syslog(LOG_WARNING
, "setenv: cannot set inetd_dummy=%s: %m", dummy
);
513 if (pipe(signalpipe
) != 0) {
514 syslog(LOG_ERR
, "pipe: %m");
517 if (fcntl(signalpipe
[0], F_SETFD
, FD_CLOEXEC
) < 0 ||
518 fcntl(signalpipe
[1], F_SETFD
, FD_CLOEXEC
) < 0) {
519 syslog(LOG_ERR
, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
522 FD_SET(signalpipe
[0], &allsock
);
526 if (signalpipe
[0] > maxsock
)
527 maxsock
= signalpipe
[0];
528 if (signalpipe
[1] > maxsock
)
529 maxsock
= signalpipe
[1];
537 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
542 if ((n
= select(maxsock
+ 1, &readable
, NULL
, NULL
, NULL
)) <= 0) {
543 if (n
< 0 && errno
!= EINTR
) {
544 syslog(LOG_WARNING
, "select: %m");
549 /* handle any queued signal flags */
550 if (FD_ISSET(signalpipe
[0], &readable
)) {
552 if (ioctl(signalpipe
[0], FIONREAD
, &nsig
) != 0) {
553 syslog(LOG_ERR
, "ioctl: %m");
556 while (--nsig
>= 0) {
558 if (read(signalpipe
[0], &c
, 1) != 1) {
559 syslog(LOG_ERR
, "read: %m");
563 warnx("handling signal flag %c", c
);
565 case 'A': /* sigalrm */
568 case 'C': /* sigchld */
571 case 'H': /* sighup */
577 for (sep
= servtab
; n
&& sep
; sep
= sep
->se_next
)
578 if (sep
->se_fd
!= -1 && FD_ISSET(sep
->se_fd
, &readable
)) {
581 warnx("someone wants %s", sep
->se_service
);
582 dofork
= !sep
->se_bi
|| sep
->se_bi
->bi_fork
|| ISWRAP(sep
);
584 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
) {
586 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
587 syslog(LOG_ERR
, "ioctl (FIONBIO, 1): %m");
588 ctrl
= accept(sep
->se_fd
, NULL
, NULL
);
590 warnx("accept, ctrl %d", ctrl
);
594 "accept (for %s): %m",
596 if (sep
->se_accept
&&
597 sep
->se_socktype
== SOCK_STREAM
)
602 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
603 syslog(LOG_ERR
, "ioctl1(FIONBIO, 0): %m");
604 if (ioctl(ctrl
, FIONBIO
, &i
) < 0)
605 syslog(LOG_ERR
, "ioctl2(FIONBIO, 0): %m");
606 if (cpmip(sep
, ctrl
) < 0) {
611 (conn
= search_conn(sep
, ctrl
)) != NULL
&&
612 !room_conn(sep
, conn
)) {
618 if (dolog
&& !ISWRAP(sep
)) {
619 char pname
[INET6_ADDRSTRLEN
] = "unknown";
622 if (getpeername(ctrl
, (struct sockaddr
*)
625 if (recvfrom(ctrl
, buf
, sizeof(buf
),
627 (struct sockaddr
*)&peermax
,
629 getnameinfo((struct sockaddr
*)&peermax
,
631 pname
, sizeof(pname
),
637 getnameinfo((struct sockaddr
*)&peermax
,
639 pname
, sizeof(pname
),
644 syslog(LOG_INFO
,"%s from %s", sep
->se_service
, pname
);
649 * Fork for all external services, builtins which need to
650 * fork and anything we're wrapping (as wrapping might
651 * block or use hosts_options(5) twist).
654 if (sep
->se_count
++ == 0)
655 gettimeofday(&sep
->se_time
, NULL
);
656 else if (toomany
> 0 && sep
->se_count
>= toomany
) {
659 gettimeofday(&now
, NULL
);
660 if (now
.tv_sec
- sep
->se_time
.tv_sec
>
666 "%s/%s server failing (looping), service terminated",
667 sep
->se_service
, sep
->se_proto
);
668 if (sep
->se_accept
&&
669 sep
->se_socktype
== SOCK_STREAM
)
684 syslog(LOG_ERR
, "fork: %m");
685 if (sep
->se_accept
&&
686 sep
->se_socktype
== SOCK_STREAM
)
694 addchild_conn(conn
, pid
);
700 sigaction(SIGALRM
, &saalrm
, NULL
);
701 sigaction(SIGCHLD
, &sachld
, NULL
);
702 sigaction(SIGHUP
, &sahup
, NULL
);
703 /* SIGPIPE reset before exec */
706 * Call tcpmux to find the real service to exec.
709 sep
->se_bi
->bi_fn
== (bi_fn_t
*) tcpmux
) {
717 inetd_setproctitle("wrapping", ctrl
);
718 service
= sep
->se_server_name
?
719 sep
->se_server_name
: sep
->se_service
;
720 request_init(&req
, RQ_DAEMON
, service
, RQ_FILE
, ctrl
, NULL
);
722 deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
723 allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
724 denied
= !hosts_access(&req
);
726 syslog(deny_severity
,
727 "refused connection from %.500s, service %s (%s%s)",
728 eval_client(&req
), service
, sep
->se_proto
,
729 (whichaf(&req
) == AF_INET6
) ? "6" : "");
730 if (sep
->se_socktype
!= SOCK_STREAM
)
731 recv(ctrl
, buf
, sizeof (buf
), 0);
738 syslog(allow_severity
,
739 "connection from %.500s, service %s (%s%s)",
740 eval_client(&req
), service
, sep
->se_proto
,
741 (whichaf(&req
) == AF_INET6
) ? "6" : "");
745 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
749 getpid(), sep
->se_server
);
750 /* Clear close-on-exec. */
751 if (fcntl(ctrl
, F_SETFD
, 0) < 0) {
753 "%s/%s: fcntl (F_SETFD, 0): %m",
754 sep
->se_service
, sep
->se_proto
);
763 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
765 "%s/%s: %s: no such user",
766 sep
->se_service
, sep
->se_proto
,
768 if (sep
->se_socktype
!= SOCK_STREAM
)
769 recv(0, buf
, sizeof (buf
), 0);
773 if ( sep
->se_group
!= NULL
774 && (grp
= getgrnam(sep
->se_group
)) == NULL
777 "%s/%s: %s: no such group",
778 sep
->se_service
, sep
->se_proto
,
780 if (sep
->se_socktype
!= SOCK_STREAM
)
781 recv(0, buf
, sizeof (buf
), 0);
785 pwd
->pw_gid
= grp
->gr_gid
;
787 if ((lc
= login_getclass(sep
->se_class
)) == NULL
) {
788 /* error syslogged by getclass */
790 "%s/%s: %s: login class error",
791 sep
->se_service
, sep
->se_proto
,
793 if (sep
->se_socktype
!= SOCK_STREAM
)
794 recv(0, buf
, sizeof (buf
), 0);
800 "%s: can't setsid(): %m",
802 /* _exit(EX_OSERR); not fatal yet */
805 if (setusercontext(lc
, pwd
, pwd
->pw_uid
,
806 LOGIN_SETALL
) != 0) {
808 "%s: can't setusercontext(..%s..): %m",
809 sep
->se_service
, sep
->se_user
);
815 if (setlogin(sep
->se_user
) < 0) {
817 "%s: can't setlogin(%s): %m",
818 sep
->se_service
, sep
->se_user
);
819 /* _exit(EX_OSERR); not yet */
821 if (setgid(pwd
->pw_gid
) < 0) {
823 "%s: can't set gid %d: %m",
824 sep
->se_service
, pwd
->pw_gid
);
827 initgroups(pwd
->pw_name
,
829 if (setuid(pwd
->pw_uid
) < 0) {
831 "%s: can't set uid %d: %m",
832 sep
->se_service
, pwd
->pw_uid
);
837 sigaction(SIGPIPE
, &sapipe
, NULL
);
838 execv(sep
->se_server
, sep
->se_argv
);
840 "cannot execute %s: %m", sep
->se_server
);
841 if (sep
->se_socktype
!= SOCK_STREAM
)
842 recv(0, buf
, sizeof (buf
), 0);
847 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
)
854 * Add a signal flag to the signal flag queue for later handling
862 if (write(signalpipe
[1], &ch
, 1) != 1) {
863 syslog(LOG_ERR
, "write: %m");
869 * Record a new child pid for this service. If we've reached the
870 * limit on children, then stop accepting incoming requests.
874 addchild(struct servtab
*sep
, pid_t pid
)
876 if (sep
->se_maxchild
<= 0)
879 if (sep
->se_numchild
>= sep
->se_maxchild
) {
880 syslog(LOG_ERR
, "%s: %d >= %d",
881 __func__
, sep
->se_numchild
, sep
->se_maxchild
);
885 sep
->se_pids
[sep
->se_numchild
++] = pid
;
886 if (sep
->se_numchild
== sep
->se_maxchild
)
891 * Some child process has exited. See if it's on somebody's list.
895 flag_reapchild(int signo __unused
)
908 pid
= wait3(&status
, WNOHANG
, NULL
);
912 warnx("%d reaped, %s %u", pid
,
913 WIFEXITED(status
) ? "status" : "signal",
914 WIFEXITED(status
) ? WEXITSTATUS(status
)
916 for (sep
= servtab
; sep
; sep
= sep
->se_next
) {
917 for (k
= 0; k
< sep
->se_numchild
; k
++)
918 if (sep
->se_pids
[k
] == pid
)
920 if (k
== sep
->se_numchild
)
922 if (sep
->se_numchild
== sep
->se_maxchild
)
924 sep
->se_pids
[k
] = sep
->se_pids
[--sep
->se_numchild
];
925 if (WIFSIGNALED(status
) || WEXITSTATUS(status
))
927 "%s[%d]: exited, %s %u",
929 WIFEXITED(status
) ? "status" : "signal",
930 WIFEXITED(status
) ? WEXITSTATUS(status
)
939 flag_config(int signo __unused
)
947 struct servtab
*sep
, *new, **sepp
;
950 login_cap_t
*lc
= NULL
;
955 syslog(LOG_ERR
, "%s: %m", CONFIG
);
958 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
960 while ((new = getconfigent())) {
961 if (getpwnam(new->se_user
) == NULL
) {
963 "%s/%s: no such user '%s', service ignored",
964 new->se_service
, new->se_proto
, new->se_user
);
967 if (new->se_group
&& getgrnam(new->se_group
) == NULL
) {
969 "%s/%s: no such group '%s', service ignored",
970 new->se_service
, new->se_proto
, new->se_group
);
974 if ((lc
= login_getclass(new->se_class
)) == NULL
) {
975 /* error syslogged by getclass */
977 "%s/%s: %s: login class error, service ignored",
978 new->se_service
, new->se_proto
, new->se_class
);
983 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
984 if (strcmp(sep
->se_service
, new->se_service
) == 0 &&
985 strcmp(sep
->se_proto
, new->se_proto
) == 0 &&
986 sep
->se_socktype
== new->se_socktype
&&
987 sep
->se_family
== new->se_family
)
992 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
993 omask
= sigblock(SIGBLOCK
);
994 if (sep
->se_nomapped
!= new->se_nomapped
) {
995 sep
->se_nomapped
= new->se_nomapped
;
998 /* copy over outstanding child pids */
999 if (sep
->se_maxchild
> 0 && new->se_maxchild
> 0) {
1000 new->se_numchild
= sep
->se_numchild
;
1001 if (new->se_numchild
> new->se_maxchild
)
1002 new->se_numchild
= new->se_maxchild
;
1003 memcpy(new->se_pids
, sep
->se_pids
,
1004 new->se_numchild
* sizeof(*new->se_pids
));
1006 SWAP(sep
->se_pids
, new->se_pids
);
1007 sep
->se_maxchild
= new->se_maxchild
;
1008 sep
->se_numchild
= new->se_numchild
;
1009 sep
->se_maxcpm
= new->se_maxcpm
;
1010 resize_conn(sep
, new->se_maxperip
);
1011 sep
->se_maxperip
= new->se_maxperip
;
1012 sep
->se_bi
= new->se_bi
;
1013 /* might need to turn on or off service now */
1014 if (sep
->se_fd
>= 0) {
1015 if (sep
->se_maxchild
> 0
1016 && sep
->se_numchild
== sep
->se_maxchild
) {
1017 if (FD_ISSET(sep
->se_fd
, &allsock
))
1020 if (!FD_ISSET(sep
->se_fd
, &allsock
))
1024 sep
->se_accept
= new->se_accept
;
1025 SWAP(sep
->se_user
, new->se_user
);
1026 SWAP(sep
->se_group
, new->se_group
);
1028 SWAP(sep
->se_class
, new->se_class
);
1030 SWAP(sep
->se_server
, new->se_server
);
1031 SWAP(sep
->se_server_name
, new->se_server_name
);
1032 for (i
= 0; i
< MAXARGV
; i
++)
1033 SWAP(sep
->se_argv
[i
], new->se_argv
[i
]);
1035 SWAP(sep
->se_policy
, new->se_policy
);
1041 print_service("REDO", sep
);
1045 print_service("ADD ", sep
);
1047 sep
->se_checked
= 1;
1052 switch (sep
->se_family
) {
1054 if (no_v4bind
!= 0) {
1061 if (no_v6bind
!= 0) {
1069 if (sep
->se_family
!= AF_UNIX
) {
1070 sp
= getservbyname(sep
->se_service
, sep
->se_proto
);
1072 syslog(LOG_ERR
, "%s/%s: unknown service",
1073 sep
->se_service
, sep
->se_proto
);
1074 sep
->se_checked
= 0;
1078 switch (sep
->se_family
) {
1080 if (sp
->s_port
!= sep
->se_ctrladdr4
.sin_port
) {
1081 sep
->se_ctrladdr4
.sin_port
=
1089 sep
->se_ctrladdr6
.sin6_port
) {
1090 sep
->se_ctrladdr6
.sin6_port
=
1097 if (sep
->se_reset
!= 0 && sep
->se_fd
>= 0)
1100 rpc
= getrpcbyname(sep
->se_service
);
1102 syslog(LOG_ERR
, "%s/%s unknown RPC service",
1103 sep
->se_service
, sep
->se_proto
);
1104 if (sep
->se_fd
!= -1)
1109 if (rpc
->r_number
!= sep
->se_rpc_prog
) {
1110 if (sep
->se_rpc_prog
)
1112 sep
->se_rpc_prog
= rpc
->r_number
;
1113 if (sep
->se_fd
!= -1)
1118 if (sep
->se_fd
== -1)
1123 * Purge anything not looked at above.
1125 omask
= sigblock(SIGBLOCK
);
1127 while ((sep
= *sepp
)) {
1128 if (sep
->se_checked
) {
1129 sepp
= &sep
->se_next
;
1132 *sepp
= sep
->se_next
;
1133 if (sep
->se_fd
>= 0)
1136 print_service("FREE", sep
);
1137 if (sep
->se_rpc
&& sep
->se_rpc_prog
> 0)
1146 unregisterrpc(struct servtab
*sep
)
1149 struct servtab
*sepp
;
1152 omask
= sigblock(SIGBLOCK
);
1153 for (sepp
= servtab
; sepp
; sepp
= sepp
->se_next
) {
1156 if (sep
->se_checked
== 0 ||
1158 sep
->se_rpc_prog
!= sepp
->se_rpc_prog
)
1163 print_service("UNREG", sep
);
1164 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++)
1165 pmap_unset(sep
->se_rpc_prog
, i
);
1166 if (sep
->se_fd
!= -1)
1173 flag_retry(int signo __unused
)
1181 struct servtab
*sep
;
1184 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
1185 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1190 setup(struct servtab
*sep
)
1194 if ((sep
->se_fd
= socket(sep
->se_family
, sep
->se_socktype
, 0)) < 0) {
1196 warn("socket failed on %s/%s",
1197 sep
->se_service
, sep
->se_proto
);
1198 syslog(LOG_ERR
, "%s/%s: socket: %m",
1199 sep
->se_service
, sep
->se_proto
);
1202 /* Set all listening sockets to close-on-exec. */
1203 if (fcntl(sep
->se_fd
, F_SETFD
, FD_CLOEXEC
) < 0) {
1204 syslog(LOG_ERR
, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m",
1205 sep
->se_service
, sep
->se_proto
);
1209 #define turnon(fd, opt) \
1210 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1211 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1212 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1213 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1214 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1215 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1217 if (turnon(sep
->se_fd
, SO_PRIVSTATE
) < 0)
1218 syslog(LOG_ERR
, "setsockopt (SO_PRIVSTATE): %m");
1220 /* tftpd opens a new connection then needs more infos */
1221 if ((sep
->se_family
== AF_INET6
) &&
1222 (strcmp(sep
->se_proto
, "udp") == 0) &&
1223 (sep
->se_accept
== 0) &&
1224 (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_PKTINFO
,
1225 (char *)&on
, sizeof (on
)) < 0))
1226 syslog(LOG_ERR
, "setsockopt (IPV6_RECVPKTINFO): %m");
1227 if (sep
->se_family
== AF_INET6
) {
1228 int flag
= sep
->se_nomapped
? 1 : 0;
1229 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1230 (char *)&flag
, sizeof (flag
)) < 0)
1231 syslog(LOG_ERR
, "setsockopt (IPV6_V6ONLY): %m");
1234 if (sep
->se_type
== TTCP_TYPE
)
1235 if (setsockopt(sep
->se_fd
, IPPROTO_TCP
, TCP_NOPUSH
,
1236 (char *)&on
, sizeof (on
)) < 0)
1237 syslog(LOG_ERR
, "setsockopt (TCP_NOPUSH): %m");
1239 if (sep
->se_type
== FAITH_TYPE
) {
1240 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_FAITH
, &on
,
1242 syslog(LOG_ERR
, "setsockopt (IPV6_FAITH): %m");
1249 if (sep
->se_family
== AF_UNIX
) {
1250 unlink(sep
->se_ctrladdr_un
.sun_path
);
1251 umask(0777); /* Make socket with conservative permissions */
1253 if (bind(sep
->se_fd
, (struct sockaddr
*)&sep
->se_ctrladdr
,
1254 sep
->se_ctrladdr_size
) < 0) {
1256 warn("bind failed on %s/%s",
1257 sep
->se_service
, sep
->se_proto
);
1258 syslog(LOG_ERR
, "%s/%s: bind: %m",
1259 sep
->se_service
, sep
->se_proto
);
1266 if (sep
->se_family
== AF_UNIX
)
1270 if (sep
->se_family
== AF_UNIX
) {
1271 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1272 if (chown(sep
->se_service
, sep
->se_sockuid
, sep
->se_sockgid
) < 0)
1273 syslog(LOG_ERR
, "chown socket: %m");
1274 if (chmod(sep
->se_service
, sep
->se_sockmode
) < 0)
1275 syslog(LOG_ERR
, "chmod socket: %m");
1280 socklen_t len
= sep
->se_ctrladdr_size
;
1282 if (sep
->se_family
!= AF_INET
) {
1284 "%s/%s: unsupported address family for rpc",
1285 sep
->se_service
, sep
->se_proto
);
1290 if (getsockname(sep
->se_fd
,
1291 (struct sockaddr
*)&sep
->se_ctrladdr
, &len
) < 0){
1292 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1293 sep
->se_service
, sep
->se_proto
);
1299 print_service("REG ", sep
);
1300 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++) {
1301 pmap_unset(sep
->se_rpc_prog
, i
);
1302 pmap_set(sep
->se_rpc_prog
, i
,
1303 (sep
->se_socktype
== SOCK_DGRAM
)
1304 ? IPPROTO_UDP
: IPPROTO_TCP
,
1305 ntohs(sep
->se_ctrladdr4
.sin_port
));
1308 if (sep
->se_socktype
== SOCK_STREAM
)
1309 listen(sep
->se_fd
, 64);
1312 warnx("registered %s on %d",
1313 sep
->se_server
, sep
->se_fd
);
1319 ipsecsetup(struct servtab
*sep
)
1322 char *policy_in
= NULL
;
1323 char *policy_out
= NULL
;
1327 switch (sep
->se_family
) {
1330 opt
= IP_IPSEC_POLICY
;
1334 level
= IPPROTO_IPV6
;
1335 opt
= IPV6_IPSEC_POLICY
;
1342 if (!sep
->se_policy
|| sep
->se_policy
[0] == '\0') {
1343 static char def_in
[] = "in entrust", def_out
[] = "out entrust";
1345 policy_out
= def_out
;
1347 if (!strncmp("in", sep
->se_policy
, 2))
1348 policy_in
= sep
->se_policy
;
1349 else if (!strncmp("out", sep
->se_policy
, 3))
1350 policy_out
= sep
->se_policy
;
1352 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1358 if (policy_in
!= NULL
) {
1359 buf
= ipsec_set_policy(policy_in
, strlen(policy_in
));
1361 if (setsockopt(sep
->se_fd
, level
, opt
,
1362 buf
, ipsec_get_policylen(buf
)) < 0 &&
1364 warnx("%s/%s: ipsec initialization failed; %s",
1365 sep
->se_service
, sep
->se_proto
,
1369 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1372 if (policy_out
!= NULL
) {
1373 buf
= ipsec_set_policy(policy_out
, strlen(policy_out
));
1375 if (setsockopt(sep
->se_fd
, level
, opt
,
1376 buf
, ipsec_get_policylen(buf
)) < 0 &&
1378 warnx("%s/%s: ipsec initialization failed; %s",
1379 sep
->se_service
, sep
->se_proto
,
1383 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1390 * Finish with a service and its socket.
1393 close_sep(struct servtab
*sep
)
1395 if (sep
->se_fd
>= 0) {
1396 if (FD_ISSET(sep
->se_fd
, &allsock
))
1402 sep
->se_numchild
= 0; /* forget about any existing children */
1406 matchservent(const char *name1
, const char *name2
, const char *proto
)
1411 if (strcmp(proto
, "unix") == 0) {
1412 if ((p
= strrchr(name1
, '/')) != NULL
)
1414 if ((p
= strrchr(name2
, '/')) != NULL
)
1417 if (strcmp(name1
, name2
) == 0)
1419 if ((se
= getservbyname(name1
, proto
)) != NULL
) {
1420 if (strcmp(name2
, se
->s_name
) == 0)
1422 for (alias
= se
->s_aliases
; *alias
; alias
++)
1423 if (strcmp(name2
, *alias
) == 0)
1430 enter(struct servtab
*cp
)
1432 struct servtab
*sep
;
1435 sep
= (struct servtab
*)malloc(sizeof (*sep
));
1437 syslog(LOG_ERR
, "malloc: %m");
1442 omask
= sigblock(SIGBLOCK
);
1443 sep
->se_next
= servtab
;
1450 enable(struct servtab
*sep
)
1454 "enabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1456 if (sep
->se_fd
< 0) {
1458 "%s: %s: bad fd", __func__
, sep
->se_service
);
1463 "%s: %s: is mux", __func__
, sep
->se_service
);
1466 if (FD_ISSET(sep
->se_fd
, &allsock
)) {
1468 "%s: %s: not off", __func__
, sep
->se_service
);
1473 FD_SET(sep
->se_fd
, &allsock
);
1474 if (sep
->se_fd
> maxsock
)
1475 maxsock
= sep
->se_fd
;
1479 disable(struct servtab
*sep
)
1483 "disabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1485 if (sep
->se_fd
< 0) {
1487 "%s: %s: bad fd", __func__
, sep
->se_service
);
1492 "%s: %s: is mux", __func__
, sep
->se_service
);
1495 if (!FD_ISSET(sep
->se_fd
, &allsock
)) {
1497 "%s: %s: not on", __func__
, sep
->se_service
);
1501 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
1506 FD_CLR(sep
->se_fd
, &allsock
);
1507 if (sep
->se_fd
== maxsock
)
1511 FILE *fconfig
= NULL
;
1512 struct servtab serv
;
1513 char line
[LINE_MAX
];
1519 if (fconfig
!= NULL
) {
1520 fseek(fconfig
, 0L, SEEK_SET
);
1523 fconfig
= fopen(CONFIG
, "r");
1524 return (fconfig
!= NULL
);
1539 struct servtab
*sep
= &serv
;
1543 static char TCPMUX_TOKEN
[] = "tcpmux/";
1544 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1546 char *policy
= NULL
;
1555 while ((cp
= nextline(fconfig
)) != NULL
) {
1557 /* lines starting with #@ is not a comment, but the policy */
1558 if (cp
[0] == '#' && cp
[1] == '@') {
1560 for (p
= cp
+ 2; p
&& *p
&& isspace(*p
); p
++)
1566 } else if (ipsec_get_policylen(p
) >= 0) {
1572 "%s: invalid ipsec policy \"%s\"",
1578 if (*cp
== '#' || *cp
== '\0')
1585 * clear the static buffer, since some fields (se_ctrladdr,
1586 * for example) don't get initialized here.
1588 memset(sep
, 0, sizeof *sep
);
1591 /* got an empty line containing just blanks/tabs. */
1594 if (arg
[0] == ':') { /* :user:group:perm: */
1595 char *user
, *group
, *perm
;
1599 if ((group
= strchr(user
, ':')) == NULL
) {
1600 syslog(LOG_ERR
, "no group after user '%s'", user
);
1604 if ((perm
= strchr(group
, ':')) == NULL
) {
1605 syslog(LOG_ERR
, "no mode after group '%s'", group
);
1609 if ((pw
= getpwnam(user
)) == NULL
) {
1610 syslog(LOG_ERR
, "no such user '%s'", user
);
1613 sep
->se_sockuid
= pw
->pw_uid
;
1614 if ((gr
= getgrnam(group
)) == NULL
) {
1615 syslog(LOG_ERR
, "no such user '%s'", group
);
1618 sep
->se_sockgid
= gr
->gr_gid
;
1619 sep
->se_sockmode
= strtol(perm
, &arg
, 8);
1621 syslog(LOG_ERR
, "bad mode '%s'", perm
);
1626 sep
->se_sockuid
= euid
;
1627 sep
->se_sockgid
= egid
;
1628 sep
->se_sockmode
= 0200;
1630 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1631 char *c
= arg
+ MUX_LEN
;
1633 sep
->se_type
= MUXPLUS_TYPE
;
1636 sep
->se_type
= MUX_TYPE
;
1637 sep
->se_service
= newstr(c
);
1639 sep
->se_service
= newstr(arg
);
1640 sep
->se_type
= NORM_TYPE
;
1643 if (strcmp(arg
, "stream") == 0)
1644 sep
->se_socktype
= SOCK_STREAM
;
1645 else if (strcmp(arg
, "dgram") == 0)
1646 sep
->se_socktype
= SOCK_DGRAM
;
1647 else if (strcmp(arg
, "rdm") == 0)
1648 sep
->se_socktype
= SOCK_RDM
;
1649 else if (strcmp(arg
, "seqpacket") == 0)
1650 sep
->se_socktype
= SOCK_SEQPACKET
;
1651 else if (strcmp(arg
, "raw") == 0)
1652 sep
->se_socktype
= SOCK_RAW
;
1654 sep
->se_socktype
= -1;
1657 if (strncmp(arg
, "tcp", 3) == 0) {
1658 sep
->se_proto
= newstr(strsep(&arg
, "/"));
1660 if (strcmp(arg
, "ttcp") == 0)
1661 sep
->se_type
= TTCP_TYPE
;
1662 else if (strcmp(arg
, "faith") == 0)
1663 sep
->se_type
= FAITH_TYPE
;
1666 if (sep
->se_type
== NORM_TYPE
&&
1667 strncmp(arg
, "faith/", 6) == 0) {
1669 sep
->se_type
= FAITH_TYPE
;
1671 sep
->se_proto
= newstr(arg
);
1673 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1674 if (no_v4bind
!= 0) {
1675 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1680 memmove(sep
->se_proto
, sep
->se_proto
+ 4,
1681 strlen(sep
->se_proto
) + 1 - 4);
1683 sep
->se_rpc_prog
= sep
->se_rpc_lowvers
=
1684 sep
->se_rpc_lowvers
= 0;
1685 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1686 sizeof(sep
->se_ctrladdr4
));
1687 if ((versp
= strrchr(sep
->se_service
, '/'))) {
1689 switch (sscanf(versp
, "%u-%u",
1690 &sep
->se_rpc_lowvers
,
1691 &sep
->se_rpc_highvers
)) {
1695 sep
->se_rpc_highvers
=
1696 sep
->se_rpc_lowvers
;
1700 "bad RPC version specifier; %s",
1707 sep
->se_rpc_lowvers
=
1708 sep
->se_rpc_highvers
= 1;
1711 sep
->se_nomapped
= 0;
1712 while (isdigit(sep
->se_proto
[strlen(sep
->se_proto
) - 1])) {
1714 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '6') {
1715 if (no_v6bind
!= 0) {
1716 syslog(LOG_NOTICE
, "IPv6 bind is ignored for %s",
1721 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1726 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '4') {
1727 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1731 /* illegal version num */
1732 syslog(LOG_ERR
, "bad IP version for %s", sep
->se_proto
);
1736 if (strcmp(sep
->se_proto
, "unix") == 0) {
1737 sep
->se_family
= AF_UNIX
;
1741 sep
->se_family
= AF_INET6
;
1742 if (v4bind
== 0 || no_v4bind
!= 0)
1743 sep
->se_nomapped
= 1;
1746 { /* default to v4 bind if not v6 bind */
1747 if (no_v4bind
!= 0) {
1748 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1753 sep
->se_family
= AF_INET
;
1756 switch(sep
->se_family
) {
1758 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1759 sizeof(sep
->se_ctrladdr4
));
1760 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr4
);
1764 memcpy(&sep
->se_ctrladdr6
, bind_sa6
,
1765 sizeof(sep
->se_ctrladdr6
));
1766 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr6
);
1770 if (strlen(sep
->se_service
) >= sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
1772 "domain socket pathname too long for service %s",
1776 memset(&sep
->se_ctrladdr
, 0, sizeof(sep
->se_ctrladdr
));
1777 sep
->se_ctrladdr_un
.sun_family
= sep
->se_family
;
1778 sep
->se_ctrladdr_un
.sun_len
= strlen(sep
->se_service
);
1779 strcpy(sep
->se_ctrladdr_un
.sun_path
, sep
->se_service
);
1780 sep
->se_ctrladdr_size
= SUN_LEN(&sep
->se_ctrladdr_un
);
1783 if (!strncmp(arg
, "wait", 4))
1785 else if (!strncmp(arg
, "nowait", 6))
1789 "%s: bad wait/nowait for service %s",
1790 CONFIG
, sep
->se_service
);
1793 sep
->se_maxchild
= -1;
1794 sep
->se_maxcpm
= -1;
1795 sep
->se_maxperip
= -1;
1796 if ((s
= strchr(arg
, '/')) != NULL
) {
1800 val
= strtoul(s
+ 1, &eptr
, 10);
1801 if (eptr
== s
+ 1 || val
> MAX_MAXCHLD
) {
1803 "%s: bad max-child for service %s",
1804 CONFIG
, sep
->se_service
);
1808 if (!sep
->se_accept
&& val
!= 1)
1809 warnx("maxchild=%lu for wait service %s"
1810 " not recommended", val
, sep
->se_service
);
1811 sep
->se_maxchild
= val
;
1813 sep
->se_maxcpm
= strtol(eptr
+ 1, &eptr
, 10);
1815 sep
->se_maxperip
= strtol(eptr
+ 1, &eptr
, 10);
1817 * explicitly do not check for \0 for future expansion /
1818 * backwards compatibility
1823 * Silently enforce "nowait" mode for TCPMUX services
1824 * since they don't have an assigned port to listen on.
1827 if (strcmp(sep
->se_proto
, "tcp")) {
1829 "%s: bad protocol for tcpmux service %s",
1830 CONFIG
, sep
->se_service
);
1833 if (sep
->se_socktype
!= SOCK_STREAM
) {
1835 "%s: bad socket type for tcpmux service %s",
1836 CONFIG
, sep
->se_service
);
1840 sep
->se_user
= newstr(sskip(&cp
));
1842 if ((s
= strrchr(sep
->se_user
, '/')) != NULL
) {
1844 sep
->se_class
= newstr(s
+ 1);
1846 sep
->se_class
= newstr(RESOURCE_RC
);
1848 if ((s
= strrchr(sep
->se_user
, ':')) != NULL
) {
1850 sep
->se_group
= newstr(s
+ 1);
1852 sep
->se_group
= NULL
;
1853 sep
->se_server
= newstr(sskip(&cp
));
1854 if ((sep
->se_server_name
= strrchr(sep
->se_server
, '/')))
1855 sep
->se_server_name
++;
1856 if (strcmp(sep
->se_server
, "internal") == 0) {
1859 for (bi
= biltins
; bi
->bi_service
; bi
++)
1860 if (bi
->bi_socktype
== sep
->se_socktype
&&
1861 matchservent(bi
->bi_service
, sep
->se_service
,
1864 if (bi
->bi_service
== 0) {
1865 syslog(LOG_ERR
, "internal service %s unknown",
1869 sep
->se_accept
= 1; /* force accept mode for built-ins */
1873 if (sep
->se_maxperip
< 0)
1874 sep
->se_maxperip
= maxperip
;
1875 if (sep
->se_maxcpm
< 0)
1876 sep
->se_maxcpm
= maxcpm
;
1877 if (sep
->se_maxchild
< 0) { /* apply default max-children */
1878 if (sep
->se_bi
&& sep
->se_bi
->bi_maxchild
>= 0)
1879 sep
->se_maxchild
= sep
->se_bi
->bi_maxchild
;
1880 else if (sep
->se_accept
)
1881 sep
->se_maxchild
= maxchild
> 0 ? maxchild
: 0;
1883 sep
->se_maxchild
= 1;
1885 if (sep
->se_maxchild
> 0) {
1886 sep
->se_pids
= malloc(sep
->se_maxchild
* sizeof(*sep
->se_pids
));
1887 if (sep
->se_pids
== NULL
) {
1888 syslog(LOG_ERR
, "malloc: %m");
1893 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
))
1894 if (argc
< MAXARGV
) {
1895 sep
->se_argv
[argc
++] = newstr(arg
);
1898 "%s: too many arguments for service %s",
1899 CONFIG
, sep
->se_service
);
1902 while (argc
<= MAXARGV
)
1903 sep
->se_argv
[argc
++] = NULL
;
1904 for (i
= 0; i
< PERIPSIZE
; ++i
)
1905 LIST_INIT(&sep
->se_conn
[i
]);
1907 sep
->se_policy
= policy
? newstr(policy
) : NULL
;
1913 freeconfig(struct servtab
*cp
)
1918 free(cp
->se_service
);
1930 free(cp
->se_server
);
1933 for (i
= 0; i
< MAXARGV
; i
++)
1935 free(cp
->se_argv
[i
]);
1939 free(cp
->se_policy
);
1945 * Safe skip - if skip returns null, log a syntax error in the
1946 * configuration file and exit.
1955 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
1969 while (*cp
== ' ' || *cp
== '\t')
1976 if (c
== ' ' || c
== '\t')
1977 if ((cp
= nextline(fconfig
)))
1982 if (*cp
== '"' || *cp
== '\'')
1986 while (*cp
&& *cp
!= quote
)
1989 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
2002 if (fgets(line
, sizeof (line
), fd
) == NULL
)
2004 cp
= strchr(line
, '\n');
2011 newstr(const char *cp
)
2015 if ((cr
= strdup(cp
!= NULL
? cp
: "")))
2017 syslog(LOG_ERR
, "strdup: %m");
2022 inetd_setproctitle(const char *a
, int s
)
2025 struct sockaddr_storage ss
;
2026 char buf
[80], pbuf
[INET6_ADDRSTRLEN
];
2029 if (getpeername(s
, (struct sockaddr
*)&ss
, &size
) == 0) {
2030 getnameinfo((struct sockaddr
*)&ss
, size
, pbuf
, sizeof(pbuf
),
2031 NULL
, 0, NI_NUMERICHOST
|NI_WITHSCOPEID
);
2032 sprintf(buf
, "%s [%s]", a
, pbuf
);
2034 sprintf(buf
, "%s", a
);
2035 setproctitle("%s", buf
);
2039 check_loop(const struct sockaddr
*sa
, const struct servtab
*sep
)
2041 struct servtab
*se2
;
2042 char pname
[INET6_ADDRSTRLEN
];
2044 for (se2
= servtab
; se2
; se2
= se2
->se_next
) {
2045 if (!se2
->se_bi
|| se2
->se_socktype
!= SOCK_DGRAM
)
2048 switch (se2
->se_family
) {
2050 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2051 se2
->se_ctrladdr4
.sin_port
)
2056 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2057 se2
->se_ctrladdr4
.sin_port
)
2065 getnameinfo(sa
, sa
->sa_len
, pname
, sizeof(pname
), NULL
, 0,
2066 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2067 syslog(LOG_WARNING
, "%s/%s:%s/%s loop request REFUSED from %s",
2068 sep
->se_service
, sep
->se_proto
,
2069 se2
->se_service
, se2
->se_proto
,
2078 * Dump relevant information to stderr
2081 print_service(const char *action
, const struct servtab
*sep
)
2084 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2088 " builtin=%p server=%s"
2093 action
, sep
->se_service
, sep
->se_proto
,
2094 sep
->se_accept
, sep
->se_maxchild
, sep
->se_user
, sep
->se_group
,
2098 (void *) sep
->se_bi
, sep
->se_server
2100 , (sep
->se_policy
? sep
->se_policy
: "")
2105 #define CPMHSIZE 256
2106 #define CPMHMASK (CPMHSIZE-1)
2110 typedef struct CTime
{
2111 unsigned long ct_Ticks
;
2115 typedef struct CHash
{
2117 struct in_addr c4_Addr
;
2118 struct in6_addr c6_Addr
;
2120 #define ch_Addr4 cu_Addr.c4_Addr
2121 #define ch_Addr6 cu_Addr.c6_Addr
2125 CTime ch_Times
[CHTSIZE
];
2128 CHash CHashAry
[CPMHSIZE
];
2131 cpmip(const struct servtab
*sep
, int ctrl
)
2133 struct sockaddr_storage rss
;
2134 socklen_t rssLen
= sizeof(rss
);
2138 * If getpeername() fails, just let it through (if logging is
2139 * enabled the condition is caught elsewhere)
2142 if (sep
->se_maxcpm
> 0 &&
2143 getpeername(ctrl
, (struct sockaddr
*)&rss
, &rssLen
) == 0 ) {
2144 time_t t
= time(NULL
);
2145 int hv
= 0xABC3D20F;
2148 CHash
*chBest
= NULL
;
2149 unsigned int ticks
= t
/ CHTGRAN
;
2150 struct sockaddr_in
*sin4
;
2152 struct sockaddr_in6
*sin6
;
2155 sin4
= (struct sockaddr_in
*)&rss
;
2157 sin6
= (struct sockaddr_in6
*)&rss
;
2163 switch (rss
.ss_family
) {
2165 p
= (char *)&sin4
->sin_addr
;
2166 addrlen
= sizeof(struct in_addr
);
2170 p
= (char *)&sin6
->sin6_addr
;
2171 addrlen
= sizeof(struct in6_addr
);
2175 /* should not happen */
2179 for (i
= 0; i
< addrlen
; ++i
, ++p
) {
2180 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2182 hv
= (hv
^ (hv
>> 16));
2184 for (i
= 0; i
< 5; ++i
) {
2185 CHash
*ch
= &CHashAry
[(hv
+ i
) & CPMHMASK
];
2187 if (rss
.ss_family
== AF_INET
&&
2188 ch
->ch_Family
== AF_INET
&&
2189 sin4
->sin_addr
.s_addr
== ch
->ch_Addr4
.s_addr
&&
2190 ch
->ch_Service
&& strcmp(sep
->se_service
,
2191 ch
->ch_Service
) == 0) {
2196 if (rss
.ss_family
== AF_INET6
&&
2197 ch
->ch_Family
== AF_INET6
&&
2198 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2199 &ch
->ch_Addr6
) != 0 &&
2200 ch
->ch_Service
&& strcmp(sep
->se_service
,
2201 ch
->ch_Service
) == 0) {
2206 if (chBest
== NULL
|| ch
->ch_LTime
== 0 ||
2207 ch
->ch_LTime
< chBest
->ch_LTime
) {
2211 if ((rss
.ss_family
== AF_INET
&&
2212 (chBest
->ch_Family
!= AF_INET
||
2213 sin4
->sin_addr
.s_addr
!= chBest
->ch_Addr4
.s_addr
)) ||
2214 chBest
->ch_Service
== NULL
||
2215 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2216 chBest
->ch_Family
= sin4
->sin_family
;
2217 chBest
->ch_Addr4
= sin4
->sin_addr
;
2218 if (chBest
->ch_Service
)
2219 free(chBest
->ch_Service
);
2220 chBest
->ch_Service
= strdup(sep
->se_service
);
2221 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2224 if ((rss
.ss_family
== AF_INET6
&&
2225 (chBest
->ch_Family
!= AF_INET6
||
2226 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2227 &chBest
->ch_Addr6
) == 0)) ||
2228 chBest
->ch_Service
== NULL
||
2229 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2230 chBest
->ch_Family
= sin6
->sin6_family
;
2231 chBest
->ch_Addr6
= sin6
->sin6_addr
;
2232 if (chBest
->ch_Service
)
2233 free(chBest
->ch_Service
);
2234 chBest
->ch_Service
= strdup(sep
->se_service
);
2235 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2238 chBest
->ch_LTime
= t
;
2240 CTime
*ct
= &chBest
->ch_Times
[ticks
% CHTSIZE
];
2241 if (ct
->ct_Ticks
!= ticks
) {
2242 ct
->ct_Ticks
= ticks
;
2247 for (i
= 0; i
< CHTSIZE
; ++i
) {
2248 CTime
*ct
= &chBest
->ch_Times
[i
];
2249 if (ct
->ct_Ticks
<= ticks
&&
2250 ct
->ct_Ticks
>= ticks
- CHTSIZE
) {
2251 cnt
+= ct
->ct_Count
;
2254 if (cnt
* (CHTSIZE
* CHTGRAN
) / 60 > sep
->se_maxcpm
) {
2255 char pname
[INET6_ADDRSTRLEN
];
2257 getnameinfo((struct sockaddr
*)&rss
,
2258 ((struct sockaddr
*)&rss
)->sa_len
,
2259 pname
, sizeof(pname
), NULL
, 0,
2260 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2263 "%s from %s exceeded counts/min (limit %d/min)",
2264 sep
->se_service
, pname
,
2271 static struct conninfo
*
2272 search_conn(struct servtab
*sep
, int ctrl
)
2274 struct sockaddr_storage ss
;
2275 socklen_t sslen
= sizeof(ss
);
2276 struct conninfo
*conn
;
2278 char pname
[NI_MAXHOST
], pname2
[NI_MAXHOST
];
2280 if (sep
->se_maxperip
<= 0)
2284 * If getpeername() fails, just let it through (if logging is
2285 * enabled the condition is caught elsewhere)
2287 if (getpeername(ctrl
, (struct sockaddr
*)&ss
, &sslen
) != 0)
2290 switch (ss
.ss_family
) {
2292 hv
= hashval((char *)&((struct sockaddr_in
*)&ss
)->sin_addr
,
2293 sizeof(struct in_addr
));
2297 hv
= hashval((char *)&((struct sockaddr_in6
*)&ss
)->sin6_addr
,
2298 sizeof(struct in6_addr
));
2303 * Since we only support AF_INET and AF_INET6, just
2304 * let other than AF_INET and AF_INET6 through.
2309 if (getnameinfo((struct sockaddr
*)&ss
, sslen
, pname
, sizeof(pname
),
2310 NULL
, 0, NI_NUMERICHOST
| NI_WITHSCOPEID
) != 0)
2313 LIST_FOREACH(conn
, &sep
->se_conn
[hv
], co_link
) {
2314 if (getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2315 conn
->co_addr
.ss_len
, pname2
, sizeof(pname2
), NULL
, 0,
2316 NI_NUMERICHOST
| NI_WITHSCOPEID
) == 0 &&
2317 strcmp(pname
, pname2
) == 0)
2322 if ((conn
= malloc(sizeof(struct conninfo
))) == NULL
) {
2323 syslog(LOG_ERR
, "malloc: %m");
2326 conn
->co_proc
= malloc(sep
->se_maxperip
* sizeof(*conn
->co_proc
));
2327 if (conn
->co_proc
== NULL
) {
2328 syslog(LOG_ERR
, "malloc: %m");
2331 memcpy(&conn
->co_addr
, (struct sockaddr
*)&ss
, sslen
);
2332 conn
->co_numchild
= 0;
2333 LIST_INSERT_HEAD(&sep
->se_conn
[hv
], conn
, co_link
);
2337 * Since a child process is not invoked yet, we cannot
2338 * determine a pid of a child. So, co_proc and co_numchild
2339 * should be filled leter.
2346 room_conn(struct servtab
*sep
, struct conninfo
*conn
)
2348 char pname
[NI_MAXHOST
];
2350 if (conn
->co_numchild
>= sep
->se_maxperip
) {
2351 getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2352 conn
->co_addr
.ss_len
, pname
, sizeof(pname
), NULL
, 0,
2353 NI_NUMERICHOST
| NI_WITHSCOPEID
);
2354 syslog(LOG_ERR
, "%s from %s exceeded counts (limit %d)",
2355 sep
->se_service
, pname
, sep
->se_maxperip
);
2362 addchild_conn(struct conninfo
*conn
, pid_t pid
)
2364 struct procinfo
*proc
;
2369 if ((proc
= search_proc(pid
, 1)) != NULL
) {
2370 if (proc
->pr_conn
!= NULL
) {
2372 "addchild_conn: child already on process list");
2375 proc
->pr_conn
= conn
;
2378 conn
->co_proc
[conn
->co_numchild
++] = proc
;
2382 reapchild_conn(pid_t pid
)
2384 struct procinfo
*proc
;
2385 struct conninfo
*conn
;
2388 if ((proc
= search_proc(pid
, 0)) == NULL
)
2390 if ((conn
= proc
->pr_conn
) == NULL
)
2392 for (i
= 0; i
< conn
->co_numchild
; ++i
)
2393 if (conn
->co_proc
[i
] == proc
) {
2394 conn
->co_proc
[i
] = conn
->co_proc
[--conn
->co_numchild
];
2402 resize_conn(struct servtab
*sep
, int maxpip
)
2404 struct conninfo
*conn
;
2407 if (sep
->se_maxperip
<= 0)
2413 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2414 LIST_FOREACH(conn
, &sep
->se_conn
[i
], co_link
) {
2415 for (j
= maxpip
; j
< conn
->co_numchild
; ++j
)
2416 free_proc(conn
->co_proc
[j
]);
2417 conn
->co_proc
= realloc(conn
->co_proc
,
2418 maxpip
* sizeof(*conn
->co_proc
));
2419 if (conn
->co_proc
== NULL
) {
2420 syslog(LOG_ERR
, "realloc: %m");
2423 if (conn
->co_numchild
> maxpip
)
2424 conn
->co_numchild
= maxpip
;
2430 free_connlist(struct servtab
*sep
)
2432 struct conninfo
*conn
;
2435 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2436 while ((conn
= LIST_FIRST(&sep
->se_conn
[i
])) != NULL
) {
2437 for (j
= 0; j
< conn
->co_numchild
; ++j
)
2438 free_proc(conn
->co_proc
[j
]);
2439 conn
->co_numchild
= 0;
2446 free_conn(struct conninfo
*conn
)
2450 if (conn
->co_numchild
<= 0) {
2451 LIST_REMOVE(conn
, co_link
);
2452 free(conn
->co_proc
);
2457 static struct procinfo
*
2458 search_proc(pid_t pid
, int add
)
2460 struct procinfo
*proc
;
2463 hv
= hashval((char *)&pid
, sizeof(pid
));
2464 LIST_FOREACH(proc
, &proctable
[hv
], pr_link
) {
2465 if (proc
->pr_pid
== pid
)
2468 if (proc
== NULL
&& add
) {
2469 if ((proc
= malloc(sizeof(struct procinfo
))) == NULL
) {
2470 syslog(LOG_ERR
, "malloc: %m");
2474 proc
->pr_conn
= NULL
;
2475 LIST_INSERT_HEAD(&proctable
[hv
], proc
, pr_link
);
2481 free_proc(struct procinfo
*proc
)
2485 LIST_REMOVE(proc
, pr_link
);
2490 hashval(char *p
, int len
)
2492 int i
, hv
= 0xABC3D20F;
2494 for (i
= 0; i
< len
; ++i
, ++p
)
2495 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2496 hv
= (hv
^ (hv
>> 16)) & (PERIPSIZE
- 1);