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 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 static const char copyright
[] =
32 "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
33 The Regents of the University of California. All rights reserved.\n";
38 static char sccsid
[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94";
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
46 * Inetd - Internet super-server
48 * This program invokes all internet services as needed. Connection-oriented
49 * services are invoked each time a connection is made, by creating a process.
50 * This process is passed the connection as file descriptor 0 and is expected
51 * to do a getpeername to find out the source host and port.
53 * Datagram oriented services are invoked when a datagram
54 * arrives; a process is created and passed a pending message
55 * on file descriptor 0. Datagram servers may either connect
56 * to their peer, freeing up the original socket for inetd
57 * to receive further messages on, or ``take over the socket'',
58 * processing all arriving datagrams and, eventually, timing
59 * out. The first type of server is said to be ``multi-threaded'';
60 * the second type of server ``single-threaded''.
62 * Inetd uses a configuration file which is read at startup
63 * and, possibly, at some later time in response to a hangup signal.
64 * The configuration file is ``free format'' with fields given in the
65 * order shown below. Continuation lines for an entry must begin with
66 * a space or tab. All fields must be present in each entry.
68 * service name must be in /etc/services
69 * or name a tcpmux service
70 * or specify a unix domain socket
71 * socket type stream/dgram/raw/rdm/seqpacket
72 * protocol tcp[4][6], udp[4][6], unix
73 * wait/nowait single-threaded/multi-threaded
74 * user[:group][/login-class] user/group/login-class to run daemon as
75 * server program full path name
76 * server program arguments maximum of MAXARGS (20)
78 * TCP services without official port numbers are handled with the
79 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
80 * requests. When a connection is made from a foreign host, the service
81 * requested is passed to tcpmux, which looks it up in the servtab list
82 * and returns the proper entry for the service. Tcpmux returns a
83 * negative reply if the service doesn't exist, otherwise the invoked
84 * server is expected to return the positive reply if the service type in
85 * inetd.conf file has the prefix "tcpmux/". If the service type has the
86 * prefix "tcpmux/+", tcpmux will return the positive reply for the
87 * process; this is for compatibility with older server code, and also
88 * allows you to invoke programs that use stdin/stdout without putting any
89 * special server code in them. Services that use tcpmux are "nowait"
90 * because they do not have a well-known port and hence cannot listen
94 * service name/version must be in /etc/rpc
95 * socket type stream/dgram/raw/rdm/seqpacket
96 * protocol rpc/tcp[4][6], rpc/udp[4][6]
97 * wait/nowait single-threaded/multi-threaded
98 * user[:group][/login-class] user/group/login-class to run daemon as
99 * server program full path name
100 * server program arguments maximum of MAXARGS
102 * Comment lines are indicated by a `#' in column 1.
105 * Comment lines that start with "#@" denote IPsec policy string, as described
106 * in ipsec_set_policy(3). This will affect all the following items in
107 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
108 * there's no IPsec policy.
111 #include <sys/param.h>
112 #include <sys/ioctl.h>
113 #include <sys/mman.h>
114 #include <sys/wait.h>
115 #include <sys/time.h>
116 #include <sys/resource.h>
117 #include <sys/stat.h>
120 #include <netinet/in.h>
121 #include <netinet/tcp.h>
122 #include <arpa/inet.h>
124 #include <rpc/pmap_clnt.h>
139 #include <sysexits.h>
145 #include "pathnames.h"
148 #include <netipsec/ipsec.h>
149 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
154 #ifndef LIBWRAP_ALLOW_FACILITY
155 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
157 #ifndef LIBWRAP_ALLOW_SEVERITY
158 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
160 #ifndef LIBWRAP_DENY_FACILITY
161 # define LIBWRAP_DENY_FACILITY LOG_AUTH
163 #ifndef LIBWRAP_DENY_SEVERITY
164 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
167 #define ISWRAP(sep) \
168 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
169 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
170 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
171 || (sep)->se_socktype == SOCK_DGRAM))
174 #include <login_cap.h>
177 #define RESOURCE_RC "daemon"
182 #define MAXCHILD -1 /* maximum number of this service
187 #define MAXCPM -1 /* rate limit invocations from a
188 single remote address,
193 #define MAXPERIP -1 /* maximum number of this service
194 from a single remote address,
199 #define TOOMANY 256 /* don't start more than TOOMANY */
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 */
205 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
207 void close_sep(struct servtab
*);
208 void flag_signal(int);
209 void flag_config(int);
211 int cpmip(const struct servtab
*, int);
212 void endconfig(void);
213 struct servtab
*enter(struct servtab
*);
214 void freeconfig(struct servtab
*);
215 struct servtab
*getconfigent(void);
216 int matchservent(const char *, const char *, const char *);
217 char *nextline(FILE *);
218 void addchild(struct servtab
*, int);
219 void flag_reapchild(int);
220 void reapchild(void);
221 void enable(struct servtab
*);
222 void disable(struct servtab
*);
223 void flag_retry(int);
226 void setup(struct servtab
*);
228 void ipsecsetup(struct servtab
*);
230 void unregisterrpc(register struct servtab
*sep
);
231 static struct conninfo
*search_conn(struct servtab
*sep
, int ctrl
);
232 static int room_conn(struct servtab
*sep
, struct conninfo
*conn
);
233 static void addchild_conn(struct conninfo
*conn
, pid_t pid
);
234 static void reapchild_conn(pid_t pid
);
235 static void free_conn(struct conninfo
*conn
);
236 static void resize_conn(struct servtab
*sep
, int maxperip
);
237 static void free_connlist(struct servtab
*sep
);
238 static void free_proc(struct procinfo
*);
239 static struct procinfo
*search_proc(pid_t pid
, int add
);
240 static int hashval(char *p
, int len
);
248 int maxsock
; /* highest-numbered descriptor */
252 int toomany
= TOOMANY
;
253 int maxchild
= MAXCHILD
;
255 int maxperip
= MAXPERIP
;
258 char *hostname
= NULL
;
259 struct sockaddr_in
*bind_sa4
;
262 struct sockaddr_in6
*bind_sa6
;
273 struct servtab
*servtab
;
275 extern struct biltin biltins
[];
277 const char *CONFIG
= _PATH_INETDCONF
;
278 const char *pid_file
= _PATH_INETDPID
;
279 struct pidfh
*pfh
= NULL
;
281 struct netconfig
*udpconf
, *tcpconf
, *udp6conf
, *tcp6conf
;
283 static LIST_HEAD(, procinfo
) proctable
[PERIPSIZE
];
286 getvalue(const char *arg
, int *value
, const char *whine
)
291 tmp
= strtol(arg
, &p
, 0);
293 syslog(LOG_ERR
, whine
, arg
);
294 return 1; /* failure */
297 return 0; /* success */
301 whichaf(struct request_info
*req
)
305 sa
= (struct sockaddr
*)req
->client
->sin
;
308 if (sa
->sa_family
== AF_INET6
&&
309 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)sa
)->sin6_addr
))
311 return sa
->sa_family
;
315 main(int argc
, char **argv
)
320 struct sigaction sa
, saalrm
, sachld
, sahup
, sapipe
;
325 login_cap_t
*lc
= NULL
;
327 struct request_info req
;
329 char *service
= NULL
;
330 struct sockaddr_storage peer
;
332 struct addrinfo hints
, *res
;
333 const char *servname
;
335 struct conninfo
*conn
;
337 openlog("inetd", LOG_PID
| LOG_NOWAIT
| LOG_PERROR
, LOG_DAEMON
);
339 while ((ch
= getopt(argc
, argv
, "dlwWR:a:c:C:p:s:")) != -1)
349 getvalue(optarg
, &toomany
,
350 "-R %s: bad value for service invocation rate");
353 getvalue(optarg
, &maxchild
,
354 "-c %s: bad value for maximum children");
357 getvalue(optarg
, &maxcpm
,
358 "-C %s: bad value for maximum children/minute");
367 getvalue(optarg
, &maxperip
,
368 "-s %s: bad value for maximum children per source address");
379 "usage: inetd [-dlwW] [-a address] [-R rate]"
380 " [-c maximum] [-C rate]"
381 " [-p pidfile] [conf-file]");
385 * Initialize Bind Addrs.
386 * When hostname is NULL, wild card bind addrs are obtained from
387 * getaddrinfo(). But getaddrinfo() requires at least one of
388 * hostname or servname is non NULL.
389 * So when hostname is NULL, set dummy value to servname.
390 * Since getaddrinfo() doesn't accept numeric servname, and
391 * we doesn't use ai_socktype of struct addrinfo returned
392 * from getaddrinfo(), we set dummy value to ai_socktype.
394 servname
= (hostname
== NULL
) ? "0" /* dummy */ : NULL
;
396 bzero(&hints
, sizeof(struct addrinfo
));
397 hints
.ai_flags
= AI_PASSIVE
;
398 hints
.ai_family
= AF_UNSPEC
;
399 hints
.ai_socktype
= SOCK_STREAM
; /* dummy */
400 error
= getaddrinfo(hostname
, servname
, &hints
, &res
);
402 syslog(LOG_ERR
, "-a %s: %s", hostname
, gai_strerror(error
));
403 if (error
== EAI_SYSTEM
)
404 syslog(LOG_ERR
, "%s", strerror(errno
));
408 if (res
->ai_addr
== NULL
) {
409 syslog(LOG_ERR
, "-a %s: getaddrinfo failed", hostname
);
412 switch (res
->ai_addr
->sa_family
) {
416 bind_sa4
= (struct sockaddr_in
*)res
->ai_addr
;
417 /* init port num in case servname is dummy */
418 bind_sa4
->sin_port
= 0;
425 bind_sa6
= (struct sockaddr_in6
*)res
->ai_addr
;
426 /* init port num in case servname is dummy */
427 bind_sa6
->sin6_port
= 0;
438 } while ((res
= res
->ai_next
) != NULL
);
444 syslog(LOG_ERR
, "-a %s: unknown address family", hostname
);
450 umask(mask
= umask(0777));
457 if (access(CONFIG
, R_OK
) < 0)
458 syslog(LOG_ERR
, "Accessing %s: %m, continuing anyway.", CONFIG
);
462 pfh
= pidfile_open(pid_file
, 0600, &otherpid
);
464 if (errno
== EEXIST
) {
465 syslog(LOG_ERR
, "%s already running, pid: %d",
466 getprogname(), otherpid
);
469 syslog(LOG_WARNING
, "pidfile_open() failed: %m");
472 if (daemon(0, 0) < 0) {
473 syslog(LOG_WARNING
, "daemon(0,0) failed: %m");
475 /* From now on we don't want syslog messages going to stderr. */
477 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
479 * In case somebody has started inetd manually, we need to
480 * clear the logname, so that old servers run as root do not
481 * get the user's logname..
483 if (setlogin("") < 0) {
484 syslog(LOG_WARNING
, "cannot clear logname: %m");
485 /* no big deal if it fails.. */
487 if (pfh
!= NULL
&& pidfile_write(pfh
) == -1) {
488 syslog(LOG_WARNING
, "pidfile_write(): %m");
492 if (madvise(NULL
, 0, MADV_PROTECT
) != 0)
493 syslog(LOG_WARNING
, "madvise() failed: %s", strerror(errno
));
495 for (i
= 0; i
< PERIPSIZE
; ++i
)
496 LIST_INIT(&proctable
[i
]);
499 udpconf
= getnetconfigent("udp");
500 tcpconf
= getnetconfigent("tcp");
501 if (udpconf
== NULL
|| tcpconf
== NULL
) {
502 syslog(LOG_ERR
, "unknown rpc/udp or rpc/tcp");
508 udp6conf
= getnetconfigent("udp6");
509 tcp6conf
= getnetconfigent("tcp6");
510 if (udp6conf
== NULL
|| tcp6conf
== NULL
) {
511 syslog(LOG_ERR
, "unknown rpc/udp6 or rpc/tcp6");
518 sigemptyset(&sa
.sa_mask
);
519 sigaddset(&sa
.sa_mask
, SIGALRM
);
520 sigaddset(&sa
.sa_mask
, SIGCHLD
);
521 sigaddset(&sa
.sa_mask
, SIGHUP
);
522 sa
.sa_handler
= flag_retry
;
523 sigaction(SIGALRM
, &sa
, &saalrm
);
525 sa
.sa_handler
= flag_config
;
526 sigaction(SIGHUP
, &sa
, &sahup
);
527 sa
.sa_handler
= flag_reapchild
;
528 sigaction(SIGCHLD
, &sa
, &sachld
);
529 sa
.sa_handler
= SIG_IGN
;
530 sigaction(SIGPIPE
, &sa
, &sapipe
);
533 /* space for daemons to overwrite environment for ps */
534 #define DUMMYSIZE 100
535 char dummy
[DUMMYSIZE
];
537 (void)memset(dummy
, 'x', DUMMYSIZE
- 1);
538 dummy
[DUMMYSIZE
- 1] = '\0';
539 (void)setenv("inetd_dummy", dummy
, 1);
542 if (pipe2(signalpipe
, O_CLOEXEC
) != 0) {
543 syslog(LOG_ERR
, "pipe: %m");
546 FD_SET(signalpipe
[0], &allsock
);
550 if (signalpipe
[0] > maxsock
)
551 maxsock
= signalpipe
[0];
552 if (signalpipe
[1] > maxsock
)
553 maxsock
= signalpipe
[1];
561 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
566 if ((n
= select(maxsock
+ 1, &readable
, (fd_set
*)0,
567 (fd_set
*)0, (struct timeval
*)0)) <= 0) {
568 if (n
< 0 && errno
!= EINTR
) {
569 syslog(LOG_WARNING
, "select: %m");
574 /* handle any queued signal flags */
575 if (FD_ISSET(signalpipe
[0], &readable
)) {
577 if (ioctl(signalpipe
[0], FIONREAD
, &nsig
) != 0) {
578 syslog(LOG_ERR
, "ioctl: %m");
581 while (--nsig
>= 0) {
583 if (read(signalpipe
[0], &c
, 1) != 1) {
584 syslog(LOG_ERR
, "read: %m");
588 warnx("handling signal flag %c", c
);
590 case 'A': /* sigalrm */
593 case 'C': /* sigchld */
596 case 'H': /* sighup */
602 for (sep
= servtab
; n
&& sep
; sep
= sep
->se_next
)
603 if (sep
->se_fd
!= -1 && FD_ISSET(sep
->se_fd
, &readable
)) {
606 warnx("someone wants %s", sep
->se_service
);
607 dofork
= !sep
->se_bi
|| sep
->se_bi
->bi_fork
|| ISWRAP(sep
);
609 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
) {
611 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
612 syslog(LOG_ERR
, "ioctl (FIONBIO, 1): %m");
613 ctrl
= accept(sep
->se_fd
, (struct sockaddr
*)0,
616 warnx("accept, ctrl %d", ctrl
);
620 "accept (for %s): %m",
622 if (sep
->se_accept
&&
623 sep
->se_socktype
== SOCK_STREAM
)
628 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
629 syslog(LOG_ERR
, "ioctl1(FIONBIO, 0): %m");
630 if (ioctl(ctrl
, FIONBIO
, &i
) < 0)
631 syslog(LOG_ERR
, "ioctl2(FIONBIO, 0): %m");
632 if (cpmip(sep
, ctrl
) < 0) {
637 (conn
= search_conn(sep
, ctrl
)) != NULL
&&
638 !room_conn(sep
, conn
)) {
644 if (dolog
&& !ISWRAP(sep
)) {
645 char pname
[NI_MAXHOST
] = "unknown";
648 if (getpeername(ctrl
, (struct sockaddr
*)
651 if (recvfrom(ctrl
, buf
, sizeof(buf
),
653 (struct sockaddr
*)&peer
,
655 getnameinfo((struct sockaddr
*)&peer
,
657 pname
, sizeof(pname
),
658 NULL
, 0, NI_NUMERICHOST
);
661 getnameinfo((struct sockaddr
*)&peer
,
663 pname
, sizeof(pname
),
664 NULL
, 0, NI_NUMERICHOST
);
666 syslog(LOG_INFO
,"%s from %s", sep
->se_service
, pname
);
668 (void) sigblock(SIGBLOCK
);
671 * Fork for all external services, builtins which need to
672 * fork and anything we're wrapping (as wrapping might
673 * block or use hosts_options(5) twist).
676 if (sep
->se_count
++ == 0)
677 (void)clock_gettime(CLOCK_MONOTONIC_FAST
, &sep
->se_time
);
678 else if (toomany
> 0 && sep
->se_count
>= toomany
) {
681 (void)clock_gettime(CLOCK_MONOTONIC_FAST
, &now
);
682 if (now
.tv_sec
- sep
->se_time
.tv_sec
>
688 "%s/%s server failing (looping), service terminated",
689 sep
->se_service
, sep
->se_proto
);
690 if (sep
->se_accept
&&
691 sep
->se_socktype
== SOCK_STREAM
)
706 syslog(LOG_ERR
, "fork: %m");
707 if (sep
->se_accept
&&
708 sep
->se_socktype
== SOCK_STREAM
)
716 addchild_conn(conn
, pid
);
723 sigaction(SIGALRM
, &saalrm
, (struct sigaction
*)0);
724 sigaction(SIGCHLD
, &sachld
, (struct sigaction
*)0);
725 sigaction(SIGHUP
, &sahup
, (struct sigaction
*)0);
726 /* SIGPIPE reset before exec */
729 * Call tcpmux to find the real service to exec.
732 sep
->se_bi
->bi_fn
== (bi_fn_t
*) tcpmux
) {
740 inetd_setproctitle("wrapping", ctrl
);
741 service
= sep
->se_server_name
?
742 sep
->se_server_name
: sep
->se_service
;
743 request_init(&req
, RQ_DAEMON
, service
, RQ_FILE
, ctrl
, 0);
745 deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
746 allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
747 denied
= !hosts_access(&req
);
749 syslog(deny_severity
,
750 "refused connection from %.500s, service %s (%s%s)",
751 eval_client(&req
), service
, sep
->se_proto
,
752 (whichaf(&req
) == AF_INET6
) ? "6" : "");
753 if (sep
->se_socktype
!= SOCK_STREAM
)
754 recv(ctrl
, buf
, sizeof (buf
), 0);
761 syslog(allow_severity
,
762 "connection from %.500s, service %s (%s%s)",
763 eval_client(&req
), service
, sep
->se_proto
,
764 (whichaf(&req
) == AF_INET6
) ? "6" : "");
768 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
772 getpid(), sep
->se_server
);
773 /* Clear close-on-exec. */
774 if (fcntl(ctrl
, F_SETFD
, 0) < 0) {
776 "%s/%s: fcntl (F_SETFD, 0): %m",
777 sep
->se_service
, sep
->se_proto
);
786 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
788 "%s/%s: %s: no such user",
789 sep
->se_service
, sep
->se_proto
,
791 if (sep
->se_socktype
!= SOCK_STREAM
)
792 recv(0, buf
, sizeof (buf
), 0);
796 if ( sep
->se_group
!= NULL
797 && (grp
= getgrnam(sep
->se_group
)) == NULL
800 "%s/%s: %s: no such group",
801 sep
->se_service
, sep
->se_proto
,
803 if (sep
->se_socktype
!= SOCK_STREAM
)
804 recv(0, buf
, sizeof (buf
), 0);
808 pwd
->pw_gid
= grp
->gr_gid
;
810 if ((lc
= login_getclass(sep
->se_class
)) == NULL
) {
811 /* error syslogged by getclass */
813 "%s/%s: %s: login class error",
814 sep
->se_service
, sep
->se_proto
,
816 if (sep
->se_socktype
!= SOCK_STREAM
)
817 recv(0, buf
, sizeof (buf
), 0);
823 "%s: can't setsid(): %m",
825 /* _exit(EX_OSERR); not fatal yet */
828 if (setusercontext(lc
, pwd
, pwd
->pw_uid
,
829 LOGIN_SETALL
& ~LOGIN_SETMAC
)
832 "%s: can't setusercontext(..%s..): %m",
833 sep
->se_service
, sep
->se_user
);
839 if (setlogin(sep
->se_user
) < 0) {
841 "%s: can't setlogin(%s): %m",
842 sep
->se_service
, sep
->se_user
);
843 /* _exit(EX_OSERR); not yet */
845 if (setgid(pwd
->pw_gid
) < 0) {
847 "%s: can't set gid %d: %m",
848 sep
->se_service
, pwd
->pw_gid
);
851 (void) initgroups(pwd
->pw_name
,
853 if (setuid(pwd
->pw_uid
) < 0) {
855 "%s: can't set uid %d: %m",
856 sep
->se_service
, pwd
->pw_uid
);
861 sigaction(SIGPIPE
, &sapipe
,
862 (struct sigaction
*)0);
863 execv(sep
->se_server
, sep
->se_argv
);
865 "cannot execute %s: %m", sep
->se_server
);
866 if (sep
->se_socktype
!= SOCK_STREAM
)
867 recv(0, buf
, sizeof (buf
), 0);
872 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
)
879 * Add a signal flag to the signal flag queue for later handling
887 if (write(signalpipe
[1], &ch
, 1) != 1) {
888 syslog(LOG_ERR
, "write: %m");
894 * Record a new child pid for this service. If we've reached the
895 * limit on children, then stop accepting incoming requests.
899 addchild(struct servtab
*sep
, pid_t pid
)
901 if (sep
->se_maxchild
<= 0)
904 if (sep
->se_numchild
>= sep
->se_maxchild
) {
905 syslog(LOG_ERR
, "%s: %d >= %d",
906 __func__
, sep
->se_numchild
, sep
->se_maxchild
);
910 sep
->se_pids
[sep
->se_numchild
++] = pid
;
911 if (sep
->se_numchild
== sep
->se_maxchild
)
916 * Some child process has exited. See if it's on somebody's list.
920 flag_reapchild(int signo __unused
)
933 pid
= wait3(&status
, WNOHANG
, (struct rusage
*)0);
937 warnx("%d reaped, %s %u", pid
,
938 WIFEXITED(status
) ? "status" : "signal",
939 WIFEXITED(status
) ? WEXITSTATUS(status
)
941 for (sep
= servtab
; sep
; sep
= sep
->se_next
) {
942 for (k
= 0; k
< sep
->se_numchild
; k
++)
943 if (sep
->se_pids
[k
] == pid
)
945 if (k
== sep
->se_numchild
)
947 if (sep
->se_numchild
== sep
->se_maxchild
)
949 sep
->se_pids
[k
] = sep
->se_pids
[--sep
->se_numchild
];
950 if (WIFSIGNALED(status
) || WEXITSTATUS(status
))
952 "%s[%d]: exited, %s %u",
954 WIFEXITED(status
) ? "status" : "signal",
955 WIFEXITED(status
) ? WEXITSTATUS(status
)
964 flag_config(int signo __unused
)
972 struct servtab
*sep
, *new, **sepp
;
976 login_cap_t
*lc
= NULL
;
980 syslog(LOG_ERR
, "%s: %m", CONFIG
);
983 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
985 while ((new = getconfigent())) {
986 if (getpwnam(new->se_user
) == NULL
) {
988 "%s/%s: no such user '%s', service ignored",
989 new->se_service
, new->se_proto
, new->se_user
);
992 if (new->se_group
&& getgrnam(new->se_group
) == NULL
) {
994 "%s/%s: no such group '%s', service ignored",
995 new->se_service
, new->se_proto
, new->se_group
);
999 if ((lc
= login_getclass(new->se_class
)) == NULL
) {
1000 /* error syslogged by getclass */
1002 "%s/%s: %s: login class error, service ignored",
1003 new->se_service
, new->se_proto
, new->se_class
);
1008 new_nomapped
= new->se_nomapped
;
1009 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
1010 if (strcmp(sep
->se_service
, new->se_service
) == 0 &&
1011 strcmp(sep
->se_proto
, new->se_proto
) == 0 &&
1012 sep
->se_rpc
== new->se_rpc
&&
1013 sep
->se_socktype
== new->se_socktype
&&
1014 sep
->se_family
== new->se_family
)
1019 #define SWAP(t,a, b) { t c = a; a = b; b = c; }
1020 omask
= sigblock(SIGBLOCK
);
1021 if (sep
->se_nomapped
!= new->se_nomapped
) {
1022 /* for rpc keep old nommaped till unregister */
1024 sep
->se_nomapped
= new->se_nomapped
;
1027 /* copy over outstanding child pids */
1028 if (sep
->se_maxchild
> 0 && new->se_maxchild
> 0) {
1029 new->se_numchild
= sep
->se_numchild
;
1030 if (new->se_numchild
> new->se_maxchild
)
1031 new->se_numchild
= new->se_maxchild
;
1032 memcpy(new->se_pids
, sep
->se_pids
,
1033 new->se_numchild
* sizeof(*new->se_pids
));
1035 SWAP(pid_t
*, sep
->se_pids
, new->se_pids
);
1036 sep
->se_maxchild
= new->se_maxchild
;
1037 sep
->se_numchild
= new->se_numchild
;
1038 sep
->se_maxcpm
= new->se_maxcpm
;
1039 resize_conn(sep
, new->se_maxperip
);
1040 sep
->se_maxperip
= new->se_maxperip
;
1041 sep
->se_bi
= new->se_bi
;
1042 /* might need to turn on or off service now */
1043 if (sep
->se_fd
>= 0) {
1044 if (sep
->se_maxchild
> 0
1045 && sep
->se_numchild
== sep
->se_maxchild
) {
1046 if (FD_ISSET(sep
->se_fd
, &allsock
))
1049 if (!FD_ISSET(sep
->se_fd
, &allsock
))
1053 sep
->se_accept
= new->se_accept
;
1054 SWAP(char *, sep
->se_user
, new->se_user
);
1055 SWAP(char *, sep
->se_group
, new->se_group
);
1057 SWAP(char *, sep
->se_class
, new->se_class
);
1059 SWAP(char *, sep
->se_server
, new->se_server
);
1060 SWAP(char *, sep
->se_server_name
, new->se_server_name
);
1061 for (i
= 0; i
< MAXARGV
; i
++)
1062 SWAP(char *, sep
->se_argv
[i
], new->se_argv
[i
]);
1064 SWAP(char *, sep
->se_policy
, new->se_policy
);
1070 print_service("REDO", sep
);
1074 print_service("ADD ", sep
);
1076 sep
->se_checked
= 1;
1081 switch (sep
->se_family
) {
1098 if (sep
->se_family
!= AF_UNIX
) {
1099 sp
= getservbyname(sep
->se_service
, sep
->se_proto
);
1101 syslog(LOG_ERR
, "%s/%s: unknown service",
1102 sep
->se_service
, sep
->se_proto
);
1103 sep
->se_checked
= 0;
1107 switch (sep
->se_family
) {
1109 if (sp
->s_port
!= sep
->se_ctrladdr4
.sin_port
) {
1110 sep
->se_ctrladdr4
.sin_port
=
1118 sep
->se_ctrladdr6
.sin6_port
) {
1119 sep
->se_ctrladdr6
.sin6_port
=
1126 if (sep
->se_reset
!= 0 && sep
->se_fd
>= 0)
1129 rpc
= getrpcbyname(sep
->se_service
);
1131 syslog(LOG_ERR
, "%s/%s unknown RPC service",
1132 sep
->se_service
, sep
->se_proto
);
1133 if (sep
->se_fd
!= -1)
1134 (void) close(sep
->se_fd
);
1138 if (sep
->se_reset
!= 0 ||
1139 rpc
->r_number
!= sep
->se_rpc_prog
) {
1140 if (sep
->se_rpc_prog
)
1142 sep
->se_rpc_prog
= rpc
->r_number
;
1143 if (sep
->se_fd
!= -1)
1144 (void) close(sep
->se_fd
);
1147 sep
->se_nomapped
= new_nomapped
;
1150 if (sep
->se_fd
== -1)
1155 * Purge anything not looked at above.
1157 omask
= sigblock(SIGBLOCK
);
1159 while ((sep
= *sepp
)) {
1160 if (sep
->se_checked
) {
1161 sepp
= &sep
->se_next
;
1164 *sepp
= sep
->se_next
;
1165 if (sep
->se_fd
>= 0)
1168 print_service("FREE", sep
);
1169 if (sep
->se_rpc
&& sep
->se_rpc_prog
> 0)
1174 (void) sigsetmask(omask
);
1178 unregisterrpc(struct servtab
*sep
)
1181 struct servtab
*sepp
;
1183 struct netconfig
*netid4
, *netid6
;
1185 omask
= sigblock(SIGBLOCK
);
1186 netid4
= sep
->se_socktype
== SOCK_DGRAM
? udpconf
: tcpconf
;
1187 netid6
= sep
->se_socktype
== SOCK_DGRAM
? udp6conf
: tcp6conf
;
1188 if (sep
->se_family
== AF_INET
)
1190 else if (sep
->se_nomapped
)
1193 * Conflict if same prog and protocol - In that case one should look
1194 * to versions, but it is not interesting: having separate servers for
1195 * different versions does not work well.
1196 * Therefore one do not unregister if there is a conflict.
1197 * There is also transport conflict if destroying INET when INET46
1198 * exists, or destroying INET46 when INET exists
1200 for (sepp
= servtab
; sepp
; sepp
= sepp
->se_next
) {
1203 if (sepp
->se_checked
== 0 ||
1205 strcmp(sep
->se_proto
, sepp
->se_proto
) != 0 ||
1206 sep
->se_rpc_prog
!= sepp
->se_rpc_prog
)
1208 if (sepp
->se_family
== AF_INET
)
1210 if (sepp
->se_family
== AF_INET6
) {
1212 if (!sep
->se_nomapped
)
1215 if (netid4
== NULL
&& netid6
== NULL
)
1219 print_service("UNREG", sep
);
1220 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++) {
1222 rpcb_unset(sep
->se_rpc_prog
, i
, netid4
);
1224 rpcb_unset(sep
->se_rpc_prog
, i
, netid6
);
1226 if (sep
->se_fd
!= -1)
1227 (void) close(sep
->se_fd
);
1229 (void) sigsetmask(omask
);
1233 flag_retry(int signo __unused
)
1241 struct servtab
*sep
;
1244 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
1245 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1250 setup(struct servtab
*sep
)
1254 /* Set all listening sockets to close-on-exec. */
1255 if ((sep
->se_fd
= socket(sep
->se_family
,
1256 sep
->se_socktype
| SOCK_CLOEXEC
, 0)) < 0) {
1258 warn("socket failed on %s/%s",
1259 sep
->se_service
, sep
->se_proto
);
1260 syslog(LOG_ERR
, "%s/%s: socket: %m",
1261 sep
->se_service
, sep
->se_proto
);
1264 #define turnon(fd, opt) \
1265 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1266 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1267 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1268 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1269 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1270 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1272 if (turnon(sep
->se_fd
, SO_PRIVSTATE
) < 0)
1273 syslog(LOG_ERR
, "setsockopt (SO_PRIVSTATE): %m");
1275 /* tftpd opens a new connection then needs more infos */
1276 if ((sep
->se_family
== AF_INET6
) &&
1277 (strcmp(sep
->se_proto
, "udp") == 0) &&
1278 (sep
->se_accept
== 0) &&
1279 (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
,
1280 (char *)&on
, sizeof (on
)) < 0))
1281 syslog(LOG_ERR
, "setsockopt (IPV6_RECVPKTINFO): %m");
1282 if (sep
->se_family
== AF_INET6
) {
1283 int flag
= sep
->se_nomapped
? 1 : 0;
1284 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1285 (char *)&flag
, sizeof (flag
)) < 0)
1286 syslog(LOG_ERR
, "setsockopt (IPV6_V6ONLY): %m");
1292 if (sep
->se_family
== AF_UNIX
) {
1293 (void) unlink(sep
->se_ctrladdr_un
.sun_path
);
1294 umask(0777); /* Make socket with conservative permissions */
1296 if (bind(sep
->se_fd
, (struct sockaddr
*)&sep
->se_ctrladdr
,
1297 sep
->se_ctrladdr_size
) < 0) {
1299 warn("bind failed on %s/%s",
1300 sep
->se_service
, sep
->se_proto
);
1301 syslog(LOG_ERR
, "%s/%s: bind: %m",
1302 sep
->se_service
, sep
->se_proto
);
1303 (void) close(sep
->se_fd
);
1309 if (sep
->se_family
== AF_UNIX
)
1313 if (sep
->se_family
== AF_UNIX
) {
1314 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1315 if (chown(sep
->se_service
, sep
->se_sockuid
, sep
->se_sockgid
) < 0)
1316 syslog(LOG_ERR
, "chown socket: %m");
1317 if (chmod(sep
->se_service
, sep
->se_sockmode
) < 0)
1318 syslog(LOG_ERR
, "chmod socket: %m");
1323 socklen_t len
= sep
->se_ctrladdr_size
;
1324 struct netconfig
*netid
, *netid2
= NULL
;
1325 struct sockaddr_in sock
;
1326 struct netbuf nbuf
, nbuf2
;
1328 if (getsockname(sep
->se_fd
,
1329 (struct sockaddr
*)&sep
->se_ctrladdr
, &len
) < 0){
1330 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1331 sep
->se_service
, sep
->se_proto
);
1332 (void) close(sep
->se_fd
);
1336 nbuf
.buf
= &sep
->se_ctrladdr
;
1337 nbuf
.len
= sep
->se_ctrladdr
.sa_len
;
1338 if (sep
->se_family
== AF_INET
)
1339 netid
= sep
->se_socktype
==SOCK_DGRAM
? udpconf
:tcpconf
;
1341 netid
= sep
->se_socktype
==SOCK_DGRAM
? udp6conf
:tcp6conf
;
1342 if (!sep
->se_nomapped
) { /* INET and INET6 */
1343 netid2
= netid
==udp6conf
? udpconf
:tcpconf
;
1344 memset(&sock
, 0, sizeof sock
); /* ADDR_ANY */
1346 nbuf2
.len
= sock
.sin_len
= sizeof sock
;
1347 sock
.sin_family
= AF_INET
;
1348 sock
.sin_port
= sep
->se_ctrladdr6
.sin6_port
;
1352 print_service("REG ", sep
);
1353 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++) {
1354 rpcb_unset(sep
->se_rpc_prog
, i
, netid
);
1355 rpcb_set(sep
->se_rpc_prog
, i
, netid
, &nbuf
);
1357 rpcb_unset(sep
->se_rpc_prog
, i
, netid2
);
1358 rpcb_set(sep
->se_rpc_prog
, i
, netid2
, &nbuf2
);
1362 if (sep
->se_socktype
== SOCK_STREAM
)
1363 listen(sep
->se_fd
, -1);
1366 warnx("registered %s on %d",
1367 sep
->se_server
, sep
->se_fd
);
1373 ipsecsetup(struct servtab
*sep
)
1376 char *policy_in
= NULL
;
1377 char *policy_out
= NULL
;
1381 switch (sep
->se_family
) {
1384 opt
= IP_IPSEC_POLICY
;
1388 level
= IPPROTO_IPV6
;
1389 opt
= IPV6_IPSEC_POLICY
;
1396 if (!sep
->se_policy
|| sep
->se_policy
[0] == '\0') {
1397 static char def_in
[] = "in entrust", def_out
[] = "out entrust";
1399 policy_out
= def_out
;
1401 if (!strncmp("in", sep
->se_policy
, 2))
1402 policy_in
= sep
->se_policy
;
1403 else if (!strncmp("out", sep
->se_policy
, 3))
1404 policy_out
= sep
->se_policy
;
1406 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1412 if (policy_in
!= NULL
) {
1413 buf
= ipsec_set_policy(policy_in
, strlen(policy_in
));
1415 if (setsockopt(sep
->se_fd
, level
, opt
,
1416 buf
, ipsec_get_policylen(buf
)) < 0 &&
1418 warnx("%s/%s: ipsec initialization failed; %s",
1419 sep
->se_service
, sep
->se_proto
,
1423 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1426 if (policy_out
!= NULL
) {
1427 buf
= ipsec_set_policy(policy_out
, strlen(policy_out
));
1429 if (setsockopt(sep
->se_fd
, level
, opt
,
1430 buf
, ipsec_get_policylen(buf
)) < 0 &&
1432 warnx("%s/%s: ipsec initialization failed; %s",
1433 sep
->se_service
, sep
->se_proto
,
1437 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1444 * Finish with a service and its socket.
1447 close_sep(struct servtab
*sep
)
1449 if (sep
->se_fd
>= 0) {
1450 if (FD_ISSET(sep
->se_fd
, &allsock
))
1452 (void) close(sep
->se_fd
);
1456 sep
->se_numchild
= 0; /* forget about any existing children */
1460 matchservent(const char *name1
, const char *name2
, const char *proto
)
1465 if (strcmp(proto
, "unix") == 0) {
1466 if ((p
= strrchr(name1
, '/')) != NULL
)
1468 if ((p
= strrchr(name2
, '/')) != NULL
)
1471 if (strcmp(name1
, name2
) == 0)
1473 if ((se
= getservbyname(name1
, proto
)) != NULL
) {
1474 if (strcmp(name2
, se
->s_name
) == 0)
1476 for (alias
= se
->s_aliases
; *alias
; alias
++)
1477 if (strcmp(name2
, *alias
) == 0)
1484 enter(struct servtab
*cp
)
1486 struct servtab
*sep
;
1489 sep
= (struct servtab
*)malloc(sizeof (*sep
));
1490 if (sep
== (struct servtab
*)0) {
1491 syslog(LOG_ERR
, "malloc: %m");
1496 omask
= sigblock(SIGBLOCK
);
1497 sep
->se_next
= servtab
;
1504 enable(struct servtab
*sep
)
1508 "enabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1510 if (sep
->se_fd
< 0) {
1512 "%s: %s: bad fd", __func__
, sep
->se_service
);
1517 "%s: %s: is mux", __func__
, sep
->se_service
);
1520 if (FD_ISSET(sep
->se_fd
, &allsock
)) {
1522 "%s: %s: not off", __func__
, sep
->se_service
);
1527 FD_SET(sep
->se_fd
, &allsock
);
1528 if (sep
->se_fd
> maxsock
)
1529 maxsock
= sep
->se_fd
;
1533 disable(struct servtab
*sep
)
1537 "disabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1539 if (sep
->se_fd
< 0) {
1541 "%s: %s: bad fd", __func__
, sep
->se_service
);
1546 "%s: %s: is mux", __func__
, sep
->se_service
);
1549 if (!FD_ISSET(sep
->se_fd
, &allsock
)) {
1551 "%s: %s: not on", __func__
, sep
->se_service
);
1555 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
1560 FD_CLR(sep
->se_fd
, &allsock
);
1561 if (sep
->se_fd
== maxsock
)
1565 FILE *fconfig
= NULL
;
1566 struct servtab serv
;
1567 char line
[LINE_MAX
];
1573 if (fconfig
!= NULL
) {
1574 fseek(fconfig
, 0L, SEEK_SET
);
1577 fconfig
= fopen(CONFIG
, "r");
1578 return (fconfig
!= NULL
);
1585 (void) fclose(fconfig
);
1593 struct servtab
*sep
= &serv
;
1597 static char TCPMUX_TOKEN
[] = "tcpmux/";
1598 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1616 while ((cp
= nextline(fconfig
)) != NULL
) {
1618 /* lines starting with #@ is not a comment, but the policy */
1619 if (cp
[0] == '#' && cp
[1] == '@') {
1621 for (p
= cp
+ 2; p
&& *p
&& isspace(*p
); p
++)
1627 } else if (ipsec_get_policylen(p
) >= 0) {
1633 "%s: invalid ipsec policy \"%s\"",
1639 if (*cp
== '#' || *cp
== '\0')
1644 return ((struct servtab
*)0);
1646 * clear the static buffer, since some fields (se_ctrladdr,
1647 * for example) don't get initialized here.
1649 memset(sep
, 0, sizeof *sep
);
1652 /* got an empty line containing just blanks/tabs. */
1655 if (arg
[0] == ':') { /* :user:group:perm: */
1656 char *user
, *group
, *perm
;
1660 if ((group
= strchr(user
, ':')) == NULL
) {
1661 syslog(LOG_ERR
, "no group after user '%s'", user
);
1665 if ((perm
= strchr(group
, ':')) == NULL
) {
1666 syslog(LOG_ERR
, "no mode after group '%s'", group
);
1670 if ((pw
= getpwnam(user
)) == NULL
) {
1671 syslog(LOG_ERR
, "no such user '%s'", user
);
1674 sep
->se_sockuid
= pw
->pw_uid
;
1675 if ((gr
= getgrnam(group
)) == NULL
) {
1676 syslog(LOG_ERR
, "no such user '%s'", group
);
1679 sep
->se_sockgid
= gr
->gr_gid
;
1680 sep
->se_sockmode
= strtol(perm
, &arg
, 8);
1682 syslog(LOG_ERR
, "bad mode '%s'", perm
);
1687 sep
->se_sockuid
= euid
;
1688 sep
->se_sockgid
= egid
;
1689 sep
->se_sockmode
= 0200;
1691 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1692 char *c
= arg
+ MUX_LEN
;
1694 sep
->se_type
= MUXPLUS_TYPE
;
1697 sep
->se_type
= MUX_TYPE
;
1698 sep
->se_service
= newstr(c
);
1700 sep
->se_service
= newstr(arg
);
1701 sep
->se_type
= NORM_TYPE
;
1704 if (strcmp(arg
, "stream") == 0)
1705 sep
->se_socktype
= SOCK_STREAM
;
1706 else if (strcmp(arg
, "dgram") == 0)
1707 sep
->se_socktype
= SOCK_DGRAM
;
1708 else if (strcmp(arg
, "rdm") == 0)
1709 sep
->se_socktype
= SOCK_RDM
;
1710 else if (strcmp(arg
, "seqpacket") == 0)
1711 sep
->se_socktype
= SOCK_SEQPACKET
;
1712 else if (strcmp(arg
, "raw") == 0)
1713 sep
->se_socktype
= SOCK_RAW
;
1715 sep
->se_socktype
= -1;
1718 if (strncmp(arg
, "tcp", 3) == 0) {
1719 sep
->se_proto
= newstr(strsep(&arg
, "/"));
1720 if (arg
!= NULL
&& (strcmp(arg
, "faith") == 0)) {
1721 syslog(LOG_ERR
, "faith has been deprecated");
1725 if (sep
->se_type
== NORM_TYPE
&&
1726 strncmp(arg
, "faith/", 6) == 0) {
1727 syslog(LOG_ERR
, "faith has been deprecated");
1730 sep
->se_proto
= newstr(arg
);
1732 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1733 memmove(sep
->se_proto
, sep
->se_proto
+ 4,
1734 strlen(sep
->se_proto
) + 1 - 4);
1736 sep
->se_rpc_prog
= sep
->se_rpc_lowvers
=
1737 sep
->se_rpc_highvers
= 0;
1738 if ((versp
= strrchr(sep
->se_service
, '/'))) {
1740 switch (sscanf(versp
, "%u-%u",
1741 &sep
->se_rpc_lowvers
,
1742 &sep
->se_rpc_highvers
)) {
1746 sep
->se_rpc_highvers
=
1747 sep
->se_rpc_lowvers
;
1751 "bad RPC version specifier; %s",
1758 sep
->se_rpc_lowvers
=
1759 sep
->se_rpc_highvers
= 1;
1762 sep
->se_nomapped
= 0;
1763 if (strcmp(sep
->se_proto
, "unix") == 0) {
1764 sep
->se_family
= AF_UNIX
;
1766 while (isdigit(sep
->se_proto
[strlen(sep
->se_proto
) - 1])) {
1768 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '6') {
1769 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1774 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '4') {
1775 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1779 /* illegal version num */
1780 syslog(LOG_ERR
, "bad IP version for %s", sep
->se_proto
);
1785 if (v6bind
&& !v6bind_ok
) {
1786 syslog(LOG_INFO
, "IPv6 bind is ignored for %s",
1788 if (v4bind
&& v4bind_ok
)
1796 sep
->se_family
= AF_INET6
;
1797 if (!v4bind
|| !v4bind_ok
)
1798 sep
->se_nomapped
= 1;
1801 { /* default to v4 bind if not v6 bind */
1803 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1808 sep
->se_family
= AF_INET
;
1812 switch(sep
->se_family
) {
1814 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1815 sizeof(sep
->se_ctrladdr4
));
1816 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr4
);
1820 memcpy(&sep
->se_ctrladdr6
, bind_sa6
,
1821 sizeof(sep
->se_ctrladdr6
));
1822 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr6
);
1826 if (strlen(sep
->se_service
) >= sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
1828 "domain socket pathname too long for service %s",
1832 memset(&sep
->se_ctrladdr
, 0, sizeof(sep
->se_ctrladdr
));
1833 sep
->se_ctrladdr_un
.sun_family
= sep
->se_family
;
1834 sep
->se_ctrladdr_un
.sun_len
= strlen(sep
->se_service
);
1835 strcpy(sep
->se_ctrladdr_un
.sun_path
, sep
->se_service
);
1836 sep
->se_ctrladdr_size
= SUN_LEN(&sep
->se_ctrladdr_un
);
1839 if (!strncmp(arg
, "wait", 4))
1841 else if (!strncmp(arg
, "nowait", 6))
1845 "%s: bad wait/nowait for service %s",
1846 CONFIG
, sep
->se_service
);
1849 sep
->se_maxchild
= -1;
1850 sep
->se_maxcpm
= -1;
1851 sep
->se_maxperip
= -1;
1852 if ((s
= strchr(arg
, '/')) != NULL
) {
1856 val
= strtoul(s
+ 1, &eptr
, 10);
1857 if (eptr
== s
+ 1 || val
> MAX_MAXCHLD
) {
1859 "%s: bad max-child for service %s",
1860 CONFIG
, sep
->se_service
);
1864 if (!sep
->se_accept
&& val
!= 1)
1865 warnx("maxchild=%lu for wait service %s"
1866 " not recommended", val
, sep
->se_service
);
1867 sep
->se_maxchild
= val
;
1869 sep
->se_maxcpm
= strtol(eptr
+ 1, &eptr
, 10);
1871 sep
->se_maxperip
= strtol(eptr
+ 1, &eptr
, 10);
1873 * explicitly do not check for \0 for future expansion /
1874 * backwards compatibility
1879 * Silently enforce "nowait" mode for TCPMUX services
1880 * since they don't have an assigned port to listen on.
1883 if (strcmp(sep
->se_proto
, "tcp")) {
1885 "%s: bad protocol for tcpmux service %s",
1886 CONFIG
, sep
->se_service
);
1889 if (sep
->se_socktype
!= SOCK_STREAM
) {
1891 "%s: bad socket type for tcpmux service %s",
1892 CONFIG
, sep
->se_service
);
1896 sep
->se_user
= newstr(sskip(&cp
));
1898 if ((s
= strrchr(sep
->se_user
, '/')) != NULL
) {
1900 sep
->se_class
= newstr(s
+ 1);
1902 sep
->se_class
= newstr(RESOURCE_RC
);
1904 if ((s
= strrchr(sep
->se_user
, ':')) != NULL
) {
1906 sep
->se_group
= newstr(s
+ 1);
1908 sep
->se_group
= NULL
;
1909 sep
->se_server
= newstr(sskip(&cp
));
1910 if ((sep
->se_server_name
= strrchr(sep
->se_server
, '/')))
1911 sep
->se_server_name
++;
1912 if (strcmp(sep
->se_server
, "internal") == 0) {
1915 for (bi
= biltins
; bi
->bi_service
; bi
++)
1916 if (bi
->bi_socktype
== sep
->se_socktype
&&
1917 matchservent(bi
->bi_service
, sep
->se_service
,
1920 if (bi
->bi_service
== 0) {
1921 syslog(LOG_ERR
, "internal service %s unknown",
1925 sep
->se_accept
= 1; /* force accept mode for built-ins */
1929 if (sep
->se_maxperip
< 0)
1930 sep
->se_maxperip
= maxperip
;
1931 if (sep
->se_maxcpm
< 0)
1932 sep
->se_maxcpm
= maxcpm
;
1933 if (sep
->se_maxchild
< 0) { /* apply default max-children */
1934 if (sep
->se_bi
&& sep
->se_bi
->bi_maxchild
>= 0)
1935 sep
->se_maxchild
= sep
->se_bi
->bi_maxchild
;
1936 else if (sep
->se_accept
)
1937 sep
->se_maxchild
= MAX(maxchild
, 0);
1939 sep
->se_maxchild
= 1;
1941 if (sep
->se_maxchild
> 0) {
1942 sep
->se_pids
= malloc(sep
->se_maxchild
* sizeof(*sep
->se_pids
));
1943 if (sep
->se_pids
== NULL
) {
1944 syslog(LOG_ERR
, "malloc: %m");
1949 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
))
1950 if (argc
< MAXARGV
) {
1951 sep
->se_argv
[argc
++] = newstr(arg
);
1954 "%s: too many arguments for service %s",
1955 CONFIG
, sep
->se_service
);
1958 while (argc
<= MAXARGV
)
1959 sep
->se_argv
[argc
++] = NULL
;
1960 for (i
= 0; i
< PERIPSIZE
; ++i
)
1961 LIST_INIT(&sep
->se_conn
[i
]);
1963 sep
->se_policy
= policy
? newstr(policy
) : NULL
;
1969 freeconfig(struct servtab
*cp
)
1974 free(cp
->se_service
);
1986 free(cp
->se_server
);
1989 for (i
= 0; i
< MAXARGV
; i
++)
1991 free(cp
->se_argv
[i
]);
1995 free(cp
->se_policy
);
2001 * Safe skip - if skip returns null, log a syntax error in the
2002 * configuration file and exit.
2011 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
2025 while (*cp
== ' ' || *cp
== '\t')
2031 (void) ungetc(c
, fconfig
);
2032 if (c
== ' ' || c
== '\t')
2033 if ((cp
= nextline(fconfig
)))
2038 if (*cp
== '"' || *cp
== '\'')
2042 while (*cp
&& *cp
!= quote
)
2045 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
2058 if (fgets(line
, sizeof (line
), fd
) == NULL
)
2060 cp
= strchr(line
, '\n');
2067 newstr(const char *cp
)
2071 if ((cr
= strdup(cp
!= NULL
? cp
: "")))
2073 syslog(LOG_ERR
, "strdup: %m");
2078 inetd_setproctitle(const char *a
, int s
)
2081 struct sockaddr_storage ss
;
2082 char buf
[80], pbuf
[NI_MAXHOST
];
2085 if (getpeername(s
, (struct sockaddr
*)&ss
, &size
) == 0) {
2086 getnameinfo((struct sockaddr
*)&ss
, size
, pbuf
, sizeof(pbuf
),
2087 NULL
, 0, NI_NUMERICHOST
);
2088 (void) sprintf(buf
, "%s [%s]", a
, pbuf
);
2090 (void) sprintf(buf
, "%s", a
);
2091 setproctitle("%s", buf
);
2095 check_loop(const struct sockaddr
*sa
, const struct servtab
*sep
)
2097 struct servtab
*se2
;
2098 char pname
[NI_MAXHOST
];
2100 for (se2
= servtab
; se2
; se2
= se2
->se_next
) {
2101 if (!se2
->se_bi
|| se2
->se_socktype
!= SOCK_DGRAM
)
2104 switch (se2
->se_family
) {
2106 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2107 se2
->se_ctrladdr4
.sin_port
)
2112 if (((const struct sockaddr_in6
*)sa
)->sin6_port
==
2113 se2
->se_ctrladdr6
.sin6_port
)
2121 getnameinfo(sa
, sa
->sa_len
, pname
, sizeof(pname
), NULL
, 0,
2123 syslog(LOG_WARNING
, "%s/%s:%s/%s loop request REFUSED from %s",
2124 sep
->se_service
, sep
->se_proto
,
2125 se2
->se_service
, se2
->se_proto
,
2134 * Dump relevant information to stderr
2137 print_service(const char *action
, const struct servtab
*sep
)
2140 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2144 " builtin=%p server=%s"
2149 action
, sep
->se_service
, sep
->se_proto
,
2150 sep
->se_accept
, sep
->se_maxchild
, sep
->se_user
, sep
->se_group
,
2154 (void *) sep
->se_bi
, sep
->se_server
2156 , (sep
->se_policy
? sep
->se_policy
: "")
2161 #define CPMHSIZE 256
2162 #define CPMHMASK (CPMHSIZE-1)
2166 typedef struct CTime
{
2167 unsigned long ct_Ticks
;
2171 typedef struct CHash
{
2173 struct in_addr c4_Addr
;
2174 struct in6_addr c6_Addr
;
2176 #define ch_Addr4 cu_Addr.c4_Addr
2177 #define ch_Addr6 cu_Addr.c6_Addr
2181 CTime ch_Times
[CHTSIZE
];
2184 CHash CHashAry
[CPMHSIZE
];
2187 cpmip(const struct servtab
*sep
, int ctrl
)
2189 struct sockaddr_storage rss
;
2190 socklen_t rssLen
= sizeof(rss
);
2194 * If getpeername() fails, just let it through (if logging is
2195 * enabled the condition is caught elsewhere)
2198 if (sep
->se_maxcpm
> 0 &&
2199 (sep
->se_family
== AF_INET
|| sep
->se_family
== AF_INET6
) &&
2200 getpeername(ctrl
, (struct sockaddr
*)&rss
, &rssLen
) == 0 ) {
2201 time_t t
= time(NULL
);
2202 int hv
= 0xABC3D20F;
2205 CHash
*chBest
= NULL
;
2206 unsigned int ticks
= t
/ CHTGRAN
;
2207 struct sockaddr_in
*sin4
;
2209 struct sockaddr_in6
*sin6
;
2212 sin4
= (struct sockaddr_in
*)&rss
;
2214 sin6
= (struct sockaddr_in6
*)&rss
;
2220 switch (rss
.ss_family
) {
2222 p
= (char *)&sin4
->sin_addr
;
2223 addrlen
= sizeof(struct in_addr
);
2227 p
= (char *)&sin6
->sin6_addr
;
2228 addrlen
= sizeof(struct in6_addr
);
2232 /* should not happen */
2236 for (i
= 0; i
< addrlen
; ++i
, ++p
) {
2237 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2239 hv
= (hv
^ (hv
>> 16));
2241 for (i
= 0; i
< 5; ++i
) {
2242 CHash
*ch
= &CHashAry
[(hv
+ i
) & CPMHMASK
];
2244 if (rss
.ss_family
== AF_INET
&&
2245 ch
->ch_Family
== AF_INET
&&
2246 sin4
->sin_addr
.s_addr
== ch
->ch_Addr4
.s_addr
&&
2247 ch
->ch_Service
&& strcmp(sep
->se_service
,
2248 ch
->ch_Service
) == 0) {
2253 if (rss
.ss_family
== AF_INET6
&&
2254 ch
->ch_Family
== AF_INET6
&&
2255 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2256 &ch
->ch_Addr6
) != 0 &&
2257 ch
->ch_Service
&& strcmp(sep
->se_service
,
2258 ch
->ch_Service
) == 0) {
2263 if (chBest
== NULL
|| ch
->ch_LTime
== 0 ||
2264 ch
->ch_LTime
< chBest
->ch_LTime
) {
2268 if ((rss
.ss_family
== AF_INET
&&
2269 (chBest
->ch_Family
!= AF_INET
||
2270 sin4
->sin_addr
.s_addr
!= chBest
->ch_Addr4
.s_addr
)) ||
2271 chBest
->ch_Service
== NULL
||
2272 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2273 chBest
->ch_Family
= sin4
->sin_family
;
2274 chBest
->ch_Addr4
= sin4
->sin_addr
;
2275 if (chBest
->ch_Service
)
2276 free(chBest
->ch_Service
);
2277 chBest
->ch_Service
= strdup(sep
->se_service
);
2278 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2281 if ((rss
.ss_family
== AF_INET6
&&
2282 (chBest
->ch_Family
!= AF_INET6
||
2283 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2284 &chBest
->ch_Addr6
) == 0)) ||
2285 chBest
->ch_Service
== NULL
||
2286 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2287 chBest
->ch_Family
= sin6
->sin6_family
;
2288 chBest
->ch_Addr6
= sin6
->sin6_addr
;
2289 if (chBest
->ch_Service
)
2290 free(chBest
->ch_Service
);
2291 chBest
->ch_Service
= strdup(sep
->se_service
);
2292 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2295 chBest
->ch_LTime
= t
;
2297 CTime
*ct
= &chBest
->ch_Times
[ticks
% CHTSIZE
];
2298 if (ct
->ct_Ticks
!= ticks
) {
2299 ct
->ct_Ticks
= ticks
;
2304 for (i
= 0; i
< CHTSIZE
; ++i
) {
2305 CTime
*ct
= &chBest
->ch_Times
[i
];
2306 if (ct
->ct_Ticks
<= ticks
&&
2307 ct
->ct_Ticks
>= ticks
- CHTSIZE
) {
2308 cnt
+= ct
->ct_Count
;
2311 if ((cnt
* 60) / (CHTSIZE
* CHTGRAN
) > sep
->se_maxcpm
) {
2312 char pname
[NI_MAXHOST
];
2314 getnameinfo((struct sockaddr
*)&rss
,
2315 ((struct sockaddr
*)&rss
)->sa_len
,
2316 pname
, sizeof(pname
), NULL
, 0,
2320 "%s from %s exceeded counts/min (limit %d/min)",
2321 sep
->se_service
, pname
,
2328 static struct conninfo
*
2329 search_conn(struct servtab
*sep
, int ctrl
)
2331 struct sockaddr_storage ss
;
2332 socklen_t sslen
= sizeof(ss
);
2333 struct conninfo
*conn
;
2335 char pname
[NI_MAXHOST
], pname2
[NI_MAXHOST
];
2337 if (sep
->se_maxperip
<= 0)
2341 * If getpeername() fails, just let it through (if logging is
2342 * enabled the condition is caught elsewhere)
2344 if (getpeername(ctrl
, (struct sockaddr
*)&ss
, &sslen
) != 0)
2347 switch (ss
.ss_family
) {
2349 hv
= hashval((char *)&((struct sockaddr_in
*)&ss
)->sin_addr
,
2350 sizeof(struct in_addr
));
2354 hv
= hashval((char *)&((struct sockaddr_in6
*)&ss
)->sin6_addr
,
2355 sizeof(struct in6_addr
));
2360 * Since we only support AF_INET and AF_INET6, just
2361 * let other than AF_INET and AF_INET6 through.
2366 if (getnameinfo((struct sockaddr
*)&ss
, sslen
, pname
, sizeof(pname
),
2367 NULL
, 0, NI_NUMERICHOST
) != 0)
2370 LIST_FOREACH(conn
, &sep
->se_conn
[hv
], co_link
) {
2371 if (getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2372 conn
->co_addr
.ss_len
, pname2
, sizeof(pname2
), NULL
, 0,
2373 NI_NUMERICHOST
) == 0 &&
2374 strcmp(pname
, pname2
) == 0)
2379 if ((conn
= malloc(sizeof(struct conninfo
))) == NULL
) {
2380 syslog(LOG_ERR
, "malloc: %m");
2383 conn
->co_proc
= malloc(sep
->se_maxperip
* sizeof(*conn
->co_proc
));
2384 if (conn
->co_proc
== NULL
) {
2385 syslog(LOG_ERR
, "malloc: %m");
2388 memcpy(&conn
->co_addr
, (struct sockaddr
*)&ss
, sslen
);
2389 conn
->co_numchild
= 0;
2390 LIST_INSERT_HEAD(&sep
->se_conn
[hv
], conn
, co_link
);
2394 * Since a child process is not invoked yet, we cannot
2395 * determine a pid of a child. So, co_proc and co_numchild
2396 * should be filled leter.
2403 room_conn(struct servtab
*sep
, struct conninfo
*conn
)
2405 char pname
[NI_MAXHOST
];
2407 if (conn
->co_numchild
>= sep
->se_maxperip
) {
2408 getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2409 conn
->co_addr
.ss_len
, pname
, sizeof(pname
), NULL
, 0,
2411 syslog(LOG_ERR
, "%s from %s exceeded counts (limit %d)",
2412 sep
->se_service
, pname
, sep
->se_maxperip
);
2419 addchild_conn(struct conninfo
*conn
, pid_t pid
)
2421 struct procinfo
*proc
;
2426 if ((proc
= search_proc(pid
, 1)) != NULL
) {
2427 if (proc
->pr_conn
!= NULL
) {
2429 "addchild_conn: child already on process list");
2432 proc
->pr_conn
= conn
;
2435 conn
->co_proc
[conn
->co_numchild
++] = proc
;
2439 reapchild_conn(pid_t pid
)
2441 struct procinfo
*proc
;
2442 struct conninfo
*conn
;
2445 if ((proc
= search_proc(pid
, 0)) == NULL
)
2447 if ((conn
= proc
->pr_conn
) == NULL
)
2449 for (i
= 0; i
< conn
->co_numchild
; ++i
)
2450 if (conn
->co_proc
[i
] == proc
) {
2451 conn
->co_proc
[i
] = conn
->co_proc
[--conn
->co_numchild
];
2459 resize_conn(struct servtab
*sep
, int maxpip
)
2461 struct conninfo
*conn
;
2464 if (sep
->se_maxperip
<= 0)
2470 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2471 LIST_FOREACH(conn
, &sep
->se_conn
[i
], co_link
) {
2472 for (j
= maxpip
; j
< conn
->co_numchild
; ++j
)
2473 free_proc(conn
->co_proc
[j
]);
2474 conn
->co_proc
= realloc(conn
->co_proc
,
2475 maxpip
* sizeof(*conn
->co_proc
));
2476 if (conn
->co_proc
== NULL
) {
2477 syslog(LOG_ERR
, "realloc: %m");
2480 if (conn
->co_numchild
> maxpip
)
2481 conn
->co_numchild
= maxpip
;
2487 free_connlist(struct servtab
*sep
)
2489 struct conninfo
*conn
;
2492 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2493 while ((conn
= LIST_FIRST(&sep
->se_conn
[i
])) != NULL
) {
2494 for (j
= 0; j
< conn
->co_numchild
; ++j
)
2495 free_proc(conn
->co_proc
[j
]);
2496 conn
->co_numchild
= 0;
2503 free_conn(struct conninfo
*conn
)
2507 if (conn
->co_numchild
<= 0) {
2508 LIST_REMOVE(conn
, co_link
);
2509 free(conn
->co_proc
);
2514 static struct procinfo
*
2515 search_proc(pid_t pid
, int add
)
2517 struct procinfo
*proc
;
2520 hv
= hashval((char *)&pid
, sizeof(pid
));
2521 LIST_FOREACH(proc
, &proctable
[hv
], pr_link
) {
2522 if (proc
->pr_pid
== pid
)
2525 if (proc
== NULL
&& add
) {
2526 if ((proc
= malloc(sizeof(struct procinfo
))) == NULL
) {
2527 syslog(LOG_ERR
, "malloc: %m");
2531 proc
->pr_conn
= NULL
;
2532 LIST_INSERT_HEAD(&proctable
[hv
], proc
, pr_link
);
2538 free_proc(struct procinfo
*proc
)
2542 LIST_REMOVE(proc
, pr_link
);
2547 hashval(char *p
, int len
)
2549 int i
, hv
= 0xABC3D20F;
2551 for (i
= 0; i
< len
; ++i
, ++p
)
2552 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2553 hv
= (hv
^ (hv
>> 16)) & (PERIPSIZE
- 1);