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>
133 #include <sysexits.h>
137 #include "pathnames.h"
140 #include <netinet6/ipsec.h>
141 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
146 /* wrapper for KAME-special getnameinfo() */
147 #ifndef NI_WITHSCOPEID
148 #define NI_WITHSCOPEID 0
151 #ifndef LIBWRAP_ALLOW_FACILITY
152 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
154 #ifndef LIBWRAP_ALLOW_SEVERITY
155 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
157 #ifndef LIBWRAP_DENY_FACILITY
158 # define LIBWRAP_DENY_FACILITY LOG_AUTH
160 #ifndef LIBWRAP_DENY_SEVERITY
161 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
164 #define ISWRAP(sep) \
165 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
166 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
167 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
168 || (sep)->se_socktype == SOCK_DGRAM))
171 #include <login_cap.h>
174 #define RESOURCE_RC "daemon"
179 #define MAXCHILD -1 /* maximum number of this service
184 #define MAXCPM -1 /* rate limit invocations from a
185 single remote address,
190 #define MAXPERIP -1 /* maximum number of this service
191 from a single remote address,
196 #define TOOMANY 256 /* don't start more than TOOMANY */
198 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
199 #define RETRYTIME (60*10) /* retry after bind or server fail */
200 #define MAX_MAXCHLD 32767 /* max allowable max children */
202 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
204 void close_sep(struct servtab
*);
205 void flag_signal(int);
206 void flag_config(int);
208 int cpmip(const struct servtab
*, int);
209 void endconfig(void);
210 struct servtab
*enter(struct servtab
*);
211 void freeconfig(struct servtab
*);
212 struct servtab
*getconfigent(void);
213 int matchservent(const char *, const char *, const char *);
214 char *nextline(FILE *);
215 void addchild(struct servtab
*, int);
216 void flag_reapchild(int);
217 void reapchild(void);
218 void enable(struct servtab
*);
219 void disable(struct servtab
*);
220 void flag_retry(int);
223 void setup(struct servtab
*);
225 void ipsecsetup(struct servtab
*);
227 void unregisterrpc(struct servtab
*sep
);
228 static struct conninfo
*search_conn(struct servtab
*sep
, int ctrl
);
229 static int room_conn(struct servtab
*sep
, struct conninfo
*conn
);
230 static void addchild_conn(struct conninfo
*conn
, pid_t pid
);
231 static void reapchild_conn(pid_t pid
);
232 static void free_conn(struct conninfo
*conn
);
233 static void resize_conn(struct servtab
*sep
, int maxperip
);
234 static void free_connlist(struct servtab
*sep
);
235 static void free_proc(struct procinfo
*);
236 static struct procinfo
*search_proc(pid_t pid
, int add
);
237 static int hashval(char *p
, int len
);
245 int maxsock
; /* highest-numbered descriptor */
249 int toomany
= TOOMANY
;
250 int maxchild
= MAXCHILD
;
252 int maxperip
= MAXPERIP
;
255 char *hostname
= NULL
;
256 struct sockaddr_in
*bind_sa4
;
259 struct sockaddr_in6
*bind_sa6
;
270 struct servtab
*servtab
;
272 extern struct biltin biltins
[];
274 #define NUMINT (sizeof(intab) / sizeof(struct inent))
275 const char *CONFIG
= _PATH_INETDCONF
;
276 const char *pid_file
= _PATH_INETDPID
;
278 static LIST_HEAD(, procinfo
) proctable
[PERIPSIZE
];
281 getvalue(const char *arg
, int *value
, const char *whine
)
286 tmp
= strtol(arg
, &p
, 0);
288 syslog(LOG_ERR
, whine
, arg
);
289 return 1; /* failure */
292 return 0; /* success */
296 whichaf(struct request_info
*req
)
300 sa
= (struct sockaddr
*)req
->client
->sin
;
303 if (sa
->sa_family
== AF_INET6
&&
304 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)sa
)->sin6_addr
))
306 return sa
->sa_family
;
310 main(int argc
, char **argv
)
315 struct sigaction sa
, saalrm
, sachld
, sahup
, sapipe
;
320 login_cap_t
*lc
= NULL
;
322 struct request_info req
;
324 char *service
= NULL
;
326 struct sockaddr peer_un
;
327 struct sockaddr_in peer_un4
;
328 struct sockaddr_in6 peer_un6
;
329 struct sockaddr_storage peer_max
;
331 #define peer p_un.peer_un
332 #define peer4 p_un.peer_un4
333 #define peer6 p_un.peer_un6
334 #define peermax p_un.peer_max
336 struct addrinfo hints
, *res
;
337 const char *servname
;
339 struct conninfo
*conn
;
341 openlog("inetd", LOG_PID
| LOG_NOWAIT
| LOG_PERROR
, LOG_DAEMON
);
343 while ((ch
= getopt(argc
, argv
, "dlwWR:a:c:C:p:s:")) != -1)
353 getvalue(optarg
, &toomany
,
354 "-R %s: bad value for service invocation rate");
357 getvalue(optarg
, &maxchild
,
358 "-c %s: bad value for maximum children");
361 getvalue(optarg
, &maxcpm
,
362 "-C %s: bad value for maximum children/minute");
371 getvalue(optarg
, &maxperip
,
372 "-s %s: bad value for maximum children per source address");
383 "usage: inetd [-dlwW] [-a address] [-R rate]"
384 " [-c maximum] [-C rate]"
385 " [-p pidfile] [conf-file]");
389 * Initialize Bind Addrs.
390 * When hostname is NULL, wild card bind addrs are obtained from
391 * getaddrinfo(). But getaddrinfo() requires at least one of
392 * hostname or servname is non NULL.
393 * So when hostname is NULL, set dummy value to servname.
395 servname
= (hostname
== NULL
) ? "discard" /* dummy */ : NULL
;
397 bzero(&hints
, sizeof(struct addrinfo
));
398 hints
.ai_flags
= AI_PASSIVE
;
399 hints
.ai_family
= AF_UNSPEC
;
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));
459 if (daemon(0, 0) < 0) {
460 syslog(LOG_WARNING
, "daemon(0,0) failed: %m");
462 /* From now on we don't want syslog messages going to stderr. */
464 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
466 * In case somebody has started inetd manually, we need to
467 * clear the logname, so that old servers run as root do not
468 * get the user's logname..
470 if (setlogin("") < 0) {
471 syslog(LOG_WARNING
, "cannot clear logname: %m");
472 /* no big deal if it fails.. */
475 fp
= fopen(pid_file
, "w");
477 fprintf(fp
, "%ld\n", (long)pid
);
480 syslog(LOG_WARNING
, "%s: %m", pid_file
);
483 for (i
= 0; i
< PERIPSIZE
; ++i
)
484 LIST_INIT(&proctable
[i
]);
486 sigemptyset(&sa
.sa_mask
);
487 sigaddset(&sa
.sa_mask
, SIGALRM
);
488 sigaddset(&sa
.sa_mask
, SIGCHLD
);
489 sigaddset(&sa
.sa_mask
, SIGHUP
);
490 sa
.sa_handler
= flag_retry
;
491 sigaction(SIGALRM
, &sa
, &saalrm
);
493 sa
.sa_handler
= flag_config
;
494 sigaction(SIGHUP
, &sa
, &sahup
);
495 sa
.sa_handler
= flag_reapchild
;
496 sigaction(SIGCHLD
, &sa
, &sachld
);
497 sa
.sa_handler
= SIG_IGN
;
498 sigaction(SIGPIPE
, &sa
, &sapipe
);
501 /* space for daemons to overwrite environment for ps */
502 #define DUMMYSIZE 100
503 char dummy
[DUMMYSIZE
];
505 memset(dummy
, 'x', DUMMYSIZE
- 1);
506 dummy
[DUMMYSIZE
- 1] = '\0';
507 if (setenv("inetd_dummy", dummy
, 1) == -1)
508 syslog(LOG_WARNING
, "setenv: cannot set inetd_dummy=%s: %m", dummy
);
512 if (pipe(signalpipe
) != 0) {
513 syslog(LOG_ERR
, "pipe: %m");
516 if (fcntl(signalpipe
[0], F_SETFD
, FD_CLOEXEC
) < 0 ||
517 fcntl(signalpipe
[1], F_SETFD
, FD_CLOEXEC
) < 0) {
518 syslog(LOG_ERR
, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
521 FD_SET(signalpipe
[0], &allsock
);
525 if (signalpipe
[0] > maxsock
)
526 maxsock
= signalpipe
[0];
527 if (signalpipe
[1] > maxsock
)
528 maxsock
= signalpipe
[1];
536 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
541 if ((n
= select(maxsock
+ 1, &readable
, (fd_set
*)0,
542 (fd_set
*)0, (struct timeval
*)0)) <= 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
, (struct sockaddr
*)0,
591 warnx("accept, ctrl %d", ctrl
);
595 "accept (for %s): %m",
597 if (sep
->se_accept
&&
598 sep
->se_socktype
== SOCK_STREAM
)
603 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
604 syslog(LOG_ERR
, "ioctl1(FIONBIO, 0): %m");
605 if (ioctl(ctrl
, FIONBIO
, &i
) < 0)
606 syslog(LOG_ERR
, "ioctl2(FIONBIO, 0): %m");
607 if (cpmip(sep
, ctrl
) < 0) {
612 (conn
= search_conn(sep
, ctrl
)) != NULL
&&
613 !room_conn(sep
, conn
)) {
619 if (dolog
&& !ISWRAP(sep
)) {
620 char pname
[INET6_ADDRSTRLEN
] = "unknown";
623 if (getpeername(ctrl
, (struct sockaddr
*)
626 if (recvfrom(ctrl
, buf
, sizeof(buf
),
628 (struct sockaddr
*)&peermax
,
630 getnameinfo((struct sockaddr
*)&peermax
,
632 pname
, sizeof(pname
),
638 getnameinfo((struct sockaddr
*)&peermax
,
640 pname
, sizeof(pname
),
645 syslog(LOG_INFO
,"%s from %s", sep
->se_service
, pname
);
650 * Fork for all external services, builtins which need to
651 * fork and anything we're wrapping (as wrapping might
652 * block or use hosts_options(5) twist).
655 if (sep
->se_count
++ == 0)
656 gettimeofday(&sep
->se_time
, (struct timezone
*)NULL
);
657 else if (toomany
> 0 && sep
->se_count
>= toomany
) {
660 gettimeofday(&now
, (struct timezone
*)NULL
);
661 if (now
.tv_sec
- sep
->se_time
.tv_sec
>
667 "%s/%s server failing (looping), service terminated",
668 sep
->se_service
, sep
->se_proto
);
669 if (sep
->se_accept
&&
670 sep
->se_socktype
== SOCK_STREAM
)
685 syslog(LOG_ERR
, "fork: %m");
686 if (sep
->se_accept
&&
687 sep
->se_socktype
== SOCK_STREAM
)
695 addchild_conn(conn
, pid
);
701 sigaction(SIGALRM
, &saalrm
, (struct sigaction
*)0);
702 sigaction(SIGCHLD
, &sachld
, (struct sigaction
*)0);
703 sigaction(SIGHUP
, &sahup
, (struct sigaction
*)0);
704 /* SIGPIPE reset before exec */
707 * Call tcpmux to find the real service to exec.
710 sep
->se_bi
->bi_fn
== (bi_fn_t
*) tcpmux
) {
718 inetd_setproctitle("wrapping", ctrl
);
719 service
= sep
->se_server_name
?
720 sep
->se_server_name
: sep
->se_service
;
721 request_init(&req
, RQ_DAEMON
, service
, RQ_FILE
, ctrl
, NULL
);
723 deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
724 allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
725 denied
= !hosts_access(&req
);
727 syslog(deny_severity
,
728 "refused connection from %.500s, service %s (%s%s)",
729 eval_client(&req
), service
, sep
->se_proto
,
730 (whichaf(&req
) == AF_INET6
) ? "6" : "");
731 if (sep
->se_socktype
!= SOCK_STREAM
)
732 recv(ctrl
, buf
, sizeof (buf
), 0);
739 syslog(allow_severity
,
740 "connection from %.500s, service %s (%s%s)",
741 eval_client(&req
), service
, sep
->se_proto
,
742 (whichaf(&req
) == AF_INET6
) ? "6" : "");
746 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
750 getpid(), sep
->se_server
);
751 /* Clear close-on-exec. */
752 if (fcntl(ctrl
, F_SETFD
, 0) < 0) {
754 "%s/%s: fcntl (F_SETFD, 0): %m",
755 sep
->se_service
, sep
->se_proto
);
764 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
766 "%s/%s: %s: no such user",
767 sep
->se_service
, sep
->se_proto
,
769 if (sep
->se_socktype
!= SOCK_STREAM
)
770 recv(0, buf
, sizeof (buf
), 0);
774 if ( sep
->se_group
!= NULL
775 && (grp
= getgrnam(sep
->se_group
)) == NULL
778 "%s/%s: %s: no such group",
779 sep
->se_service
, sep
->se_proto
,
781 if (sep
->se_socktype
!= SOCK_STREAM
)
782 recv(0, buf
, sizeof (buf
), 0);
786 pwd
->pw_gid
= grp
->gr_gid
;
788 if ((lc
= login_getclass(sep
->se_class
)) == NULL
) {
789 /* error syslogged by getclass */
791 "%s/%s: %s: login class error",
792 sep
->se_service
, sep
->se_proto
,
794 if (sep
->se_socktype
!= SOCK_STREAM
)
795 recv(0, buf
, sizeof (buf
), 0);
801 "%s: can't setsid(): %m",
803 /* _exit(EX_OSERR); not fatal yet */
806 if (setusercontext(lc
, pwd
, pwd
->pw_uid
,
807 LOGIN_SETALL
) != 0) {
809 "%s: can't setusercontext(..%s..): %m",
810 sep
->se_service
, sep
->se_user
);
816 if (setlogin(sep
->se_user
) < 0) {
818 "%s: can't setlogin(%s): %m",
819 sep
->se_service
, sep
->se_user
);
820 /* _exit(EX_OSERR); not yet */
822 if (setgid(pwd
->pw_gid
) < 0) {
824 "%s: can't set gid %d: %m",
825 sep
->se_service
, pwd
->pw_gid
);
828 initgroups(pwd
->pw_name
,
830 if (setuid(pwd
->pw_uid
) < 0) {
832 "%s: can't set uid %d: %m",
833 sep
->se_service
, pwd
->pw_uid
);
838 sigaction(SIGPIPE
, &sapipe
,
839 (struct sigaction
*)0);
840 execv(sep
->se_server
, sep
->se_argv
);
842 "cannot execute %s: %m", sep
->se_server
);
843 if (sep
->se_socktype
!= SOCK_STREAM
)
844 recv(0, buf
, sizeof (buf
), 0);
849 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
)
856 * Add a signal flag to the signal flag queue for later handling
864 if (write(signalpipe
[1], &ch
, 1) != 1) {
865 syslog(LOG_ERR
, "write: %m");
871 * Record a new child pid for this service. If we've reached the
872 * limit on children, then stop accepting incoming requests.
876 addchild(struct servtab
*sep
, pid_t pid
)
878 if (sep
->se_maxchild
<= 0)
881 if (sep
->se_numchild
>= sep
->se_maxchild
) {
882 syslog(LOG_ERR
, "%s: %d >= %d",
883 __func__
, sep
->se_numchild
, sep
->se_maxchild
);
887 sep
->se_pids
[sep
->se_numchild
++] = pid
;
888 if (sep
->se_numchild
== sep
->se_maxchild
)
893 * Some child process has exited. See if it's on somebody's list.
897 flag_reapchild(int signo __unused
)
910 pid
= wait3(&status
, WNOHANG
, (struct rusage
*)0);
914 warnx("%d reaped, %s %u", pid
,
915 WIFEXITED(status
) ? "status" : "signal",
916 WIFEXITED(status
) ? WEXITSTATUS(status
)
918 for (sep
= servtab
; sep
; sep
= sep
->se_next
) {
919 for (k
= 0; k
< sep
->se_numchild
; k
++)
920 if (sep
->se_pids
[k
] == pid
)
922 if (k
== sep
->se_numchild
)
924 if (sep
->se_numchild
== sep
->se_maxchild
)
926 sep
->se_pids
[k
] = sep
->se_pids
[--sep
->se_numchild
];
927 if (WIFSIGNALED(status
) || WEXITSTATUS(status
))
929 "%s[%d]: exited, %s %u",
931 WIFEXITED(status
) ? "status" : "signal",
932 WIFEXITED(status
) ? WEXITSTATUS(status
)
941 flag_config(int signo __unused
)
949 struct servtab
*sep
, *new, **sepp
;
952 login_cap_t
*lc
= NULL
;
957 syslog(LOG_ERR
, "%s: %m", CONFIG
);
960 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
962 while ((new = getconfigent())) {
963 if (getpwnam(new->se_user
) == NULL
) {
965 "%s/%s: no such user '%s', service ignored",
966 new->se_service
, new->se_proto
, new->se_user
);
969 if (new->se_group
&& getgrnam(new->se_group
) == NULL
) {
971 "%s/%s: no such group '%s', service ignored",
972 new->se_service
, new->se_proto
, new->se_group
);
976 if ((lc
= login_getclass(new->se_class
)) == NULL
) {
977 /* error syslogged by getclass */
979 "%s/%s: %s: login class error, service ignored",
980 new->se_service
, new->se_proto
, new->se_class
);
985 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
986 if (strcmp(sep
->se_service
, new->se_service
) == 0 &&
987 strcmp(sep
->se_proto
, new->se_proto
) == 0 &&
988 sep
->se_socktype
== new->se_socktype
&&
989 sep
->se_family
== new->se_family
)
994 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
995 omask
= sigblock(SIGBLOCK
);
996 if (sep
->se_nomapped
!= new->se_nomapped
) {
997 sep
->se_nomapped
= new->se_nomapped
;
1000 /* copy over outstanding child pids */
1001 if (sep
->se_maxchild
> 0 && new->se_maxchild
> 0) {
1002 new->se_numchild
= sep
->se_numchild
;
1003 if (new->se_numchild
> new->se_maxchild
)
1004 new->se_numchild
= new->se_maxchild
;
1005 memcpy(new->se_pids
, sep
->se_pids
,
1006 new->se_numchild
* sizeof(*new->se_pids
));
1008 SWAP(sep
->se_pids
, new->se_pids
);
1009 sep
->se_maxchild
= new->se_maxchild
;
1010 sep
->se_numchild
= new->se_numchild
;
1011 sep
->se_maxcpm
= new->se_maxcpm
;
1012 resize_conn(sep
, new->se_maxperip
);
1013 sep
->se_maxperip
= new->se_maxperip
;
1014 sep
->se_bi
= new->se_bi
;
1015 /* might need to turn on or off service now */
1016 if (sep
->se_fd
>= 0) {
1017 if (sep
->se_maxchild
> 0
1018 && sep
->se_numchild
== sep
->se_maxchild
) {
1019 if (FD_ISSET(sep
->se_fd
, &allsock
))
1022 if (!FD_ISSET(sep
->se_fd
, &allsock
))
1026 sep
->se_accept
= new->se_accept
;
1027 SWAP(sep
->se_user
, new->se_user
);
1028 SWAP(sep
->se_group
, new->se_group
);
1030 SWAP(sep
->se_class
, new->se_class
);
1032 SWAP(sep
->se_server
, new->se_server
);
1033 SWAP(sep
->se_server_name
, new->se_server_name
);
1034 for (i
= 0; i
< MAXARGV
; i
++)
1035 SWAP(sep
->se_argv
[i
], new->se_argv
[i
]);
1037 SWAP(sep
->se_policy
, new->se_policy
);
1043 print_service("REDO", sep
);
1047 print_service("ADD ", sep
);
1049 sep
->se_checked
= 1;
1054 switch (sep
->se_family
) {
1056 if (no_v4bind
!= 0) {
1063 if (no_v6bind
!= 0) {
1071 if (sep
->se_family
!= AF_UNIX
) {
1072 sp
= getservbyname(sep
->se_service
, sep
->se_proto
);
1074 syslog(LOG_ERR
, "%s/%s: unknown service",
1075 sep
->se_service
, sep
->se_proto
);
1076 sep
->se_checked
= 0;
1080 switch (sep
->se_family
) {
1082 if (sp
->s_port
!= sep
->se_ctrladdr4
.sin_port
) {
1083 sep
->se_ctrladdr4
.sin_port
=
1091 sep
->se_ctrladdr6
.sin6_port
) {
1092 sep
->se_ctrladdr6
.sin6_port
=
1099 if (sep
->se_reset
!= 0 && sep
->se_fd
>= 0)
1102 rpc
= getrpcbyname(sep
->se_service
);
1104 syslog(LOG_ERR
, "%s/%s unknown RPC service",
1105 sep
->se_service
, sep
->se_proto
);
1106 if (sep
->se_fd
!= -1)
1111 if (rpc
->r_number
!= sep
->se_rpc_prog
) {
1112 if (sep
->se_rpc_prog
)
1114 sep
->se_rpc_prog
= rpc
->r_number
;
1115 if (sep
->se_fd
!= -1)
1120 if (sep
->se_fd
== -1)
1125 * Purge anything not looked at above.
1127 omask
= sigblock(SIGBLOCK
);
1129 while ((sep
= *sepp
)) {
1130 if (sep
->se_checked
) {
1131 sepp
= &sep
->se_next
;
1134 *sepp
= sep
->se_next
;
1135 if (sep
->se_fd
>= 0)
1138 print_service("FREE", sep
);
1139 if (sep
->se_rpc
&& sep
->se_rpc_prog
> 0)
1148 unregisterrpc(struct servtab
*sep
)
1151 struct servtab
*sepp
;
1154 omask
= sigblock(SIGBLOCK
);
1155 for (sepp
= servtab
; sepp
; sepp
= sepp
->se_next
) {
1158 if (sep
->se_checked
== 0 ||
1160 sep
->se_rpc_prog
!= sepp
->se_rpc_prog
)
1165 print_service("UNREG", sep
);
1166 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++)
1167 pmap_unset(sep
->se_rpc_prog
, i
);
1168 if (sep
->se_fd
!= -1)
1175 flag_retry(int signo __unused
)
1183 struct servtab
*sep
;
1186 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
1187 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1192 setup(struct servtab
*sep
)
1196 if ((sep
->se_fd
= socket(sep
->se_family
, sep
->se_socktype
, 0)) < 0) {
1198 warn("socket failed on %s/%s",
1199 sep
->se_service
, sep
->se_proto
);
1200 syslog(LOG_ERR
, "%s/%s: socket: %m",
1201 sep
->se_service
, sep
->se_proto
);
1204 /* Set all listening sockets to close-on-exec. */
1205 if (fcntl(sep
->se_fd
, F_SETFD
, FD_CLOEXEC
) < 0) {
1206 syslog(LOG_ERR
, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m",
1207 sep
->se_service
, sep
->se_proto
);
1211 #define turnon(fd, opt) \
1212 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1213 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1214 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1215 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1216 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1217 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1219 if (turnon(sep
->se_fd
, SO_PRIVSTATE
) < 0)
1220 syslog(LOG_ERR
, "setsockopt (SO_PRIVSTATE): %m");
1222 /* tftpd opens a new connection then needs more infos */
1223 if ((sep
->se_family
== AF_INET6
) &&
1224 (strcmp(sep
->se_proto
, "udp") == 0) &&
1225 (sep
->se_accept
== 0) &&
1226 (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_PKTINFO
,
1227 (char *)&on
, sizeof (on
)) < 0))
1228 syslog(LOG_ERR
, "setsockopt (IPV6_RECVPKTINFO): %m");
1229 if (sep
->se_family
== AF_INET6
) {
1230 int flag
= sep
->se_nomapped
? 1 : 0;
1231 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1232 (char *)&flag
, sizeof (flag
)) < 0)
1233 syslog(LOG_ERR
, "setsockopt (IPV6_V6ONLY): %m");
1236 if (sep
->se_type
== TTCP_TYPE
)
1237 if (setsockopt(sep
->se_fd
, IPPROTO_TCP
, TCP_NOPUSH
,
1238 (char *)&on
, sizeof (on
)) < 0)
1239 syslog(LOG_ERR
, "setsockopt (TCP_NOPUSH): %m");
1241 if (sep
->se_type
== FAITH_TYPE
) {
1242 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_FAITH
, &on
,
1244 syslog(LOG_ERR
, "setsockopt (IPV6_FAITH): %m");
1251 if (sep
->se_family
== AF_UNIX
) {
1252 unlink(sep
->se_ctrladdr_un
.sun_path
);
1253 umask(0777); /* Make socket with conservative permissions */
1255 if (bind(sep
->se_fd
, (struct sockaddr
*)&sep
->se_ctrladdr
,
1256 sep
->se_ctrladdr_size
) < 0) {
1258 warn("bind failed on %s/%s",
1259 sep
->se_service
, sep
->se_proto
);
1260 syslog(LOG_ERR
, "%s/%s: bind: %m",
1261 sep
->se_service
, sep
->se_proto
);
1268 if (sep
->se_family
== AF_UNIX
)
1272 if (sep
->se_family
== AF_UNIX
) {
1273 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1274 if (chown(sep
->se_service
, sep
->se_sockuid
, sep
->se_sockgid
) < 0)
1275 syslog(LOG_ERR
, "chown socket: %m");
1276 if (chmod(sep
->se_service
, sep
->se_sockmode
) < 0)
1277 syslog(LOG_ERR
, "chmod socket: %m");
1282 socklen_t len
= sep
->se_ctrladdr_size
;
1284 if (sep
->se_family
!= AF_INET
) {
1286 "%s/%s: unsupported address family for rpc",
1287 sep
->se_service
, sep
->se_proto
);
1292 if (getsockname(sep
->se_fd
,
1293 (struct sockaddr
*)&sep
->se_ctrladdr
, &len
) < 0){
1294 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1295 sep
->se_service
, sep
->se_proto
);
1301 print_service("REG ", sep
);
1302 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++) {
1303 pmap_unset(sep
->se_rpc_prog
, i
);
1304 pmap_set(sep
->se_rpc_prog
, i
,
1305 (sep
->se_socktype
== SOCK_DGRAM
)
1306 ? IPPROTO_UDP
: IPPROTO_TCP
,
1307 ntohs(sep
->se_ctrladdr4
.sin_port
));
1310 if (sep
->se_socktype
== SOCK_STREAM
)
1311 listen(sep
->se_fd
, 64);
1314 warnx("registered %s on %d",
1315 sep
->se_server
, sep
->se_fd
);
1321 ipsecsetup(struct servtab
*sep
)
1324 char *policy_in
= NULL
;
1325 char *policy_out
= NULL
;
1329 switch (sep
->se_family
) {
1332 opt
= IP_IPSEC_POLICY
;
1336 level
= IPPROTO_IPV6
;
1337 opt
= IPV6_IPSEC_POLICY
;
1344 if (!sep
->se_policy
|| sep
->se_policy
[0] == '\0') {
1345 static char def_in
[] = "in entrust", def_out
[] = "out entrust";
1347 policy_out
= def_out
;
1349 if (!strncmp("in", sep
->se_policy
, 2))
1350 policy_in
= sep
->se_policy
;
1351 else if (!strncmp("out", sep
->se_policy
, 3))
1352 policy_out
= sep
->se_policy
;
1354 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1360 if (policy_in
!= NULL
) {
1361 buf
= ipsec_set_policy(policy_in
, strlen(policy_in
));
1363 if (setsockopt(sep
->se_fd
, level
, opt
,
1364 buf
, ipsec_get_policylen(buf
)) < 0 &&
1366 warnx("%s/%s: ipsec initialization failed; %s",
1367 sep
->se_service
, sep
->se_proto
,
1371 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1374 if (policy_out
!= NULL
) {
1375 buf
= ipsec_set_policy(policy_out
, strlen(policy_out
));
1377 if (setsockopt(sep
->se_fd
, level
, opt
,
1378 buf
, ipsec_get_policylen(buf
)) < 0 &&
1380 warnx("%s/%s: ipsec initialization failed; %s",
1381 sep
->se_service
, sep
->se_proto
,
1385 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1392 * Finish with a service and its socket.
1395 close_sep(struct servtab
*sep
)
1397 if (sep
->se_fd
>= 0) {
1398 if (FD_ISSET(sep
->se_fd
, &allsock
))
1404 sep
->se_numchild
= 0; /* forget about any existing children */
1408 matchservent(const char *name1
, const char *name2
, const char *proto
)
1413 if (strcmp(proto
, "unix") == 0) {
1414 if ((p
= strrchr(name1
, '/')) != NULL
)
1416 if ((p
= strrchr(name2
, '/')) != NULL
)
1419 if (strcmp(name1
, name2
) == 0)
1421 if ((se
= getservbyname(name1
, proto
)) != NULL
) {
1422 if (strcmp(name2
, se
->s_name
) == 0)
1424 for (alias
= se
->s_aliases
; *alias
; alias
++)
1425 if (strcmp(name2
, *alias
) == 0)
1432 enter(struct servtab
*cp
)
1434 struct servtab
*sep
;
1437 sep
= (struct servtab
*)malloc(sizeof (*sep
));
1438 if (sep
== (struct servtab
*)0) {
1439 syslog(LOG_ERR
, "malloc: %m");
1444 omask
= sigblock(SIGBLOCK
);
1445 sep
->se_next
= servtab
;
1452 enable(struct servtab
*sep
)
1456 "enabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1458 if (sep
->se_fd
< 0) {
1460 "%s: %s: bad fd", __func__
, sep
->se_service
);
1465 "%s: %s: is mux", __func__
, sep
->se_service
);
1468 if (FD_ISSET(sep
->se_fd
, &allsock
)) {
1470 "%s: %s: not off", __func__
, sep
->se_service
);
1475 FD_SET(sep
->se_fd
, &allsock
);
1476 if (sep
->se_fd
> maxsock
)
1477 maxsock
= sep
->se_fd
;
1481 disable(struct servtab
*sep
)
1485 "disabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1487 if (sep
->se_fd
< 0) {
1489 "%s: %s: bad fd", __func__
, sep
->se_service
);
1494 "%s: %s: is mux", __func__
, sep
->se_service
);
1497 if (!FD_ISSET(sep
->se_fd
, &allsock
)) {
1499 "%s: %s: not on", __func__
, sep
->se_service
);
1503 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
1508 FD_CLR(sep
->se_fd
, &allsock
);
1509 if (sep
->se_fd
== maxsock
)
1513 FILE *fconfig
= NULL
;
1514 struct servtab serv
;
1515 char line
[LINE_MAX
];
1521 if (fconfig
!= NULL
) {
1522 fseek(fconfig
, 0L, SEEK_SET
);
1525 fconfig
= fopen(CONFIG
, "r");
1526 return (fconfig
!= NULL
);
1541 struct servtab
*sep
= &serv
;
1545 static char TCPMUX_TOKEN
[] = "tcpmux/";
1546 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1548 char *policy
= NULL
;
1557 while ((cp
= nextline(fconfig
)) != NULL
) {
1559 /* lines starting with #@ is not a comment, but the policy */
1560 if (cp
[0] == '#' && cp
[1] == '@') {
1562 for (p
= cp
+ 2; p
&& *p
&& isspace(*p
); p
++)
1568 } else if (ipsec_get_policylen(p
) >= 0) {
1574 "%s: invalid ipsec policy \"%s\"",
1580 if (*cp
== '#' || *cp
== '\0')
1585 return ((struct servtab
*)0);
1587 * clear the static buffer, since some fields (se_ctrladdr,
1588 * for example) don't get initialized here.
1590 memset(sep
, 0, sizeof *sep
);
1593 /* got an empty line containing just blanks/tabs. */
1596 if (arg
[0] == ':') { /* :user:group:perm: */
1597 char *user
, *group
, *perm
;
1601 if ((group
= strchr(user
, ':')) == NULL
) {
1602 syslog(LOG_ERR
, "no group after user '%s'", user
);
1606 if ((perm
= strchr(group
, ':')) == NULL
) {
1607 syslog(LOG_ERR
, "no mode after group '%s'", group
);
1611 if ((pw
= getpwnam(user
)) == NULL
) {
1612 syslog(LOG_ERR
, "no such user '%s'", user
);
1615 sep
->se_sockuid
= pw
->pw_uid
;
1616 if ((gr
= getgrnam(group
)) == NULL
) {
1617 syslog(LOG_ERR
, "no such user '%s'", group
);
1620 sep
->se_sockgid
= gr
->gr_gid
;
1621 sep
->se_sockmode
= strtol(perm
, &arg
, 8);
1623 syslog(LOG_ERR
, "bad mode '%s'", perm
);
1628 sep
->se_sockuid
= euid
;
1629 sep
->se_sockgid
= egid
;
1630 sep
->se_sockmode
= 0200;
1632 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1633 char *c
= arg
+ MUX_LEN
;
1635 sep
->se_type
= MUXPLUS_TYPE
;
1638 sep
->se_type
= MUX_TYPE
;
1639 sep
->se_service
= newstr(c
);
1641 sep
->se_service
= newstr(arg
);
1642 sep
->se_type
= NORM_TYPE
;
1645 if (strcmp(arg
, "stream") == 0)
1646 sep
->se_socktype
= SOCK_STREAM
;
1647 else if (strcmp(arg
, "dgram") == 0)
1648 sep
->se_socktype
= SOCK_DGRAM
;
1649 else if (strcmp(arg
, "rdm") == 0)
1650 sep
->se_socktype
= SOCK_RDM
;
1651 else if (strcmp(arg
, "seqpacket") == 0)
1652 sep
->se_socktype
= SOCK_SEQPACKET
;
1653 else if (strcmp(arg
, "raw") == 0)
1654 sep
->se_socktype
= SOCK_RAW
;
1656 sep
->se_socktype
= -1;
1659 if (strncmp(arg
, "tcp", 3) == 0) {
1660 sep
->se_proto
= newstr(strsep(&arg
, "/"));
1662 if (strcmp(arg
, "ttcp") == 0)
1663 sep
->se_type
= TTCP_TYPE
;
1664 else if (strcmp(arg
, "faith") == 0)
1665 sep
->se_type
= FAITH_TYPE
;
1668 if (sep
->se_type
== NORM_TYPE
&&
1669 strncmp(arg
, "faith/", 6) == 0) {
1671 sep
->se_type
= FAITH_TYPE
;
1673 sep
->se_proto
= newstr(arg
);
1675 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1676 if (no_v4bind
!= 0) {
1677 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1682 memmove(sep
->se_proto
, sep
->se_proto
+ 4,
1683 strlen(sep
->se_proto
) + 1 - 4);
1685 sep
->se_rpc_prog
= sep
->se_rpc_lowvers
=
1686 sep
->se_rpc_lowvers
= 0;
1687 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1688 sizeof(sep
->se_ctrladdr4
));
1689 if ((versp
= strrchr(sep
->se_service
, '/'))) {
1691 switch (sscanf(versp
, "%u-%u",
1692 &sep
->se_rpc_lowvers
,
1693 &sep
->se_rpc_highvers
)) {
1697 sep
->se_rpc_highvers
=
1698 sep
->se_rpc_lowvers
;
1702 "bad RPC version specifier; %s",
1709 sep
->se_rpc_lowvers
=
1710 sep
->se_rpc_highvers
= 1;
1713 sep
->se_nomapped
= 0;
1714 while (isdigit(sep
->se_proto
[strlen(sep
->se_proto
) - 1])) {
1716 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '6') {
1717 if (no_v6bind
!= 0) {
1718 syslog(LOG_NOTICE
, "IPv6 bind is ignored for %s",
1723 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1728 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '4') {
1729 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1733 /* illegal version num */
1734 syslog(LOG_ERR
, "bad IP version for %s", sep
->se_proto
);
1738 if (strcmp(sep
->se_proto
, "unix") == 0) {
1739 sep
->se_family
= AF_UNIX
;
1743 sep
->se_family
= AF_INET6
;
1744 if (v4bind
== 0 || no_v4bind
!= 0)
1745 sep
->se_nomapped
= 1;
1748 { /* default to v4 bind if not v6 bind */
1749 if (no_v4bind
!= 0) {
1750 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1755 sep
->se_family
= AF_INET
;
1758 switch(sep
->se_family
) {
1760 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1761 sizeof(sep
->se_ctrladdr4
));
1762 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr4
);
1766 memcpy(&sep
->se_ctrladdr6
, bind_sa6
,
1767 sizeof(sep
->se_ctrladdr6
));
1768 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr6
);
1772 if (strlen(sep
->se_service
) >= sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
1774 "domain socket pathname too long for service %s",
1778 memset(&sep
->se_ctrladdr
, 0, sizeof(sep
->se_ctrladdr
));
1779 sep
->se_ctrladdr_un
.sun_family
= sep
->se_family
;
1780 sep
->se_ctrladdr_un
.sun_len
= strlen(sep
->se_service
);
1781 strcpy(sep
->se_ctrladdr_un
.sun_path
, sep
->se_service
);
1782 sep
->se_ctrladdr_size
= SUN_LEN(&sep
->se_ctrladdr_un
);
1785 if (!strncmp(arg
, "wait", 4))
1787 else if (!strncmp(arg
, "nowait", 6))
1791 "%s: bad wait/nowait for service %s",
1792 CONFIG
, sep
->se_service
);
1795 sep
->se_maxchild
= -1;
1796 sep
->se_maxcpm
= -1;
1797 sep
->se_maxperip
= -1;
1798 if ((s
= strchr(arg
, '/')) != NULL
) {
1802 val
= strtoul(s
+ 1, &eptr
, 10);
1803 if (eptr
== s
+ 1 || val
> MAX_MAXCHLD
) {
1805 "%s: bad max-child for service %s",
1806 CONFIG
, sep
->se_service
);
1810 if (!sep
->se_accept
&& val
!= 1)
1811 warnx("maxchild=%lu for wait service %s"
1812 " not recommended", val
, sep
->se_service
);
1813 sep
->se_maxchild
= val
;
1815 sep
->se_maxcpm
= strtol(eptr
+ 1, &eptr
, 10);
1817 sep
->se_maxperip
= strtol(eptr
+ 1, &eptr
, 10);
1819 * explicitly do not check for \0 for future expansion /
1820 * backwards compatibility
1825 * Silently enforce "nowait" mode for TCPMUX services
1826 * since they don't have an assigned port to listen on.
1829 if (strcmp(sep
->se_proto
, "tcp")) {
1831 "%s: bad protocol for tcpmux service %s",
1832 CONFIG
, sep
->se_service
);
1835 if (sep
->se_socktype
!= SOCK_STREAM
) {
1837 "%s: bad socket type for tcpmux service %s",
1838 CONFIG
, sep
->se_service
);
1842 sep
->se_user
= newstr(sskip(&cp
));
1844 if ((s
= strrchr(sep
->se_user
, '/')) != NULL
) {
1846 sep
->se_class
= newstr(s
+ 1);
1848 sep
->se_class
= newstr(RESOURCE_RC
);
1850 if ((s
= strrchr(sep
->se_user
, ':')) != NULL
) {
1852 sep
->se_group
= newstr(s
+ 1);
1854 sep
->se_group
= NULL
;
1855 sep
->se_server
= newstr(sskip(&cp
));
1856 if ((sep
->se_server_name
= strrchr(sep
->se_server
, '/')))
1857 sep
->se_server_name
++;
1858 if (strcmp(sep
->se_server
, "internal") == 0) {
1861 for (bi
= biltins
; bi
->bi_service
; bi
++)
1862 if (bi
->bi_socktype
== sep
->se_socktype
&&
1863 matchservent(bi
->bi_service
, sep
->se_service
,
1866 if (bi
->bi_service
== 0) {
1867 syslog(LOG_ERR
, "internal service %s unknown",
1871 sep
->se_accept
= 1; /* force accept mode for built-ins */
1875 if (sep
->se_maxperip
< 0)
1876 sep
->se_maxperip
= maxperip
;
1877 if (sep
->se_maxcpm
< 0)
1878 sep
->se_maxcpm
= maxcpm
;
1879 if (sep
->se_maxchild
< 0) { /* apply default max-children */
1880 if (sep
->se_bi
&& sep
->se_bi
->bi_maxchild
>= 0)
1881 sep
->se_maxchild
= sep
->se_bi
->bi_maxchild
;
1882 else if (sep
->se_accept
)
1883 sep
->se_maxchild
= maxchild
> 0 ? maxchild
: 0;
1885 sep
->se_maxchild
= 1;
1887 if (sep
->se_maxchild
> 0) {
1888 sep
->se_pids
= malloc(sep
->se_maxchild
* sizeof(*sep
->se_pids
));
1889 if (sep
->se_pids
== NULL
) {
1890 syslog(LOG_ERR
, "malloc: %m");
1895 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
))
1896 if (argc
< MAXARGV
) {
1897 sep
->se_argv
[argc
++] = newstr(arg
);
1900 "%s: too many arguments for service %s",
1901 CONFIG
, sep
->se_service
);
1904 while (argc
<= MAXARGV
)
1905 sep
->se_argv
[argc
++] = NULL
;
1906 for (i
= 0; i
< PERIPSIZE
; ++i
)
1907 LIST_INIT(&sep
->se_conn
[i
]);
1909 sep
->se_policy
= policy
? newstr(policy
) : NULL
;
1915 freeconfig(struct servtab
*cp
)
1920 free(cp
->se_service
);
1932 free(cp
->se_server
);
1935 for (i
= 0; i
< MAXARGV
; i
++)
1937 free(cp
->se_argv
[i
]);
1941 free(cp
->se_policy
);
1947 * Safe skip - if skip returns null, log a syntax error in the
1948 * configuration file and exit.
1957 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
1971 while (*cp
== ' ' || *cp
== '\t')
1978 if (c
== ' ' || c
== '\t')
1979 if ((cp
= nextline(fconfig
)))
1984 if (*cp
== '"' || *cp
== '\'')
1988 while (*cp
&& *cp
!= quote
)
1991 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
2004 if (fgets(line
, sizeof (line
), fd
) == NULL
)
2006 cp
= strchr(line
, '\n');
2013 newstr(const char *cp
)
2017 if ((cr
= strdup(cp
!= NULL
? cp
: "")))
2019 syslog(LOG_ERR
, "strdup: %m");
2024 inetd_setproctitle(const char *a
, int s
)
2027 struct sockaddr_storage ss
;
2028 char buf
[80], pbuf
[INET6_ADDRSTRLEN
];
2031 if (getpeername(s
, (struct sockaddr
*)&ss
, &size
) == 0) {
2032 getnameinfo((struct sockaddr
*)&ss
, size
, pbuf
, sizeof(pbuf
),
2033 NULL
, 0, NI_NUMERICHOST
|NI_WITHSCOPEID
);
2034 sprintf(buf
, "%s [%s]", a
, pbuf
);
2036 sprintf(buf
, "%s", a
);
2037 setproctitle("%s", buf
);
2041 check_loop(const struct sockaddr
*sa
, const struct servtab
*sep
)
2043 struct servtab
*se2
;
2044 char pname
[INET6_ADDRSTRLEN
];
2046 for (se2
= servtab
; se2
; se2
= se2
->se_next
) {
2047 if (!se2
->se_bi
|| se2
->se_socktype
!= SOCK_DGRAM
)
2050 switch (se2
->se_family
) {
2052 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2053 se2
->se_ctrladdr4
.sin_port
)
2058 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2059 se2
->se_ctrladdr4
.sin_port
)
2067 getnameinfo(sa
, sa
->sa_len
, pname
, sizeof(pname
), NULL
, 0,
2068 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2069 syslog(LOG_WARNING
, "%s/%s:%s/%s loop request REFUSED from %s",
2070 sep
->se_service
, sep
->se_proto
,
2071 se2
->se_service
, se2
->se_proto
,
2080 * Dump relevant information to stderr
2083 print_service(const char *action
, const struct servtab
*sep
)
2086 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2090 " builtin=%p server=%s"
2095 action
, sep
->se_service
, sep
->se_proto
,
2096 sep
->se_accept
, sep
->se_maxchild
, sep
->se_user
, sep
->se_group
,
2100 (void *) sep
->se_bi
, sep
->se_server
2102 , (sep
->se_policy
? sep
->se_policy
: "")
2107 #define CPMHSIZE 256
2108 #define CPMHMASK (CPMHSIZE-1)
2112 typedef struct CTime
{
2113 unsigned long ct_Ticks
;
2117 typedef struct CHash
{
2119 struct in_addr c4_Addr
;
2120 struct in6_addr c6_Addr
;
2122 #define ch_Addr4 cu_Addr.c4_Addr
2123 #define ch_Addr6 cu_Addr.c6_Addr
2127 CTime ch_Times
[CHTSIZE
];
2130 CHash CHashAry
[CPMHSIZE
];
2133 cpmip(const struct servtab
*sep
, int ctrl
)
2135 struct sockaddr_storage rss
;
2136 socklen_t rssLen
= sizeof(rss
);
2140 * If getpeername() fails, just let it through (if logging is
2141 * enabled the condition is caught elsewhere)
2144 if (sep
->se_maxcpm
> 0 &&
2145 getpeername(ctrl
, (struct sockaddr
*)&rss
, &rssLen
) == 0 ) {
2146 time_t t
= time(NULL
);
2147 int hv
= 0xABC3D20F;
2150 CHash
*chBest
= NULL
;
2151 unsigned int ticks
= t
/ CHTGRAN
;
2152 struct sockaddr_in
*sin4
;
2154 struct sockaddr_in6
*sin6
;
2157 sin4
= (struct sockaddr_in
*)&rss
;
2159 sin6
= (struct sockaddr_in6
*)&rss
;
2165 switch (rss
.ss_family
) {
2167 p
= (char *)&sin4
->sin_addr
;
2168 addrlen
= sizeof(struct in_addr
);
2172 p
= (char *)&sin6
->sin6_addr
;
2173 addrlen
= sizeof(struct in6_addr
);
2177 /* should not happen */
2181 for (i
= 0; i
< addrlen
; ++i
, ++p
) {
2182 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2184 hv
= (hv
^ (hv
>> 16));
2186 for (i
= 0; i
< 5; ++i
) {
2187 CHash
*ch
= &CHashAry
[(hv
+ i
) & CPMHMASK
];
2189 if (rss
.ss_family
== AF_INET
&&
2190 ch
->ch_Family
== AF_INET
&&
2191 sin4
->sin_addr
.s_addr
== ch
->ch_Addr4
.s_addr
&&
2192 ch
->ch_Service
&& strcmp(sep
->se_service
,
2193 ch
->ch_Service
) == 0) {
2198 if (rss
.ss_family
== AF_INET6
&&
2199 ch
->ch_Family
== AF_INET6
&&
2200 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2201 &ch
->ch_Addr6
) != 0 &&
2202 ch
->ch_Service
&& strcmp(sep
->se_service
,
2203 ch
->ch_Service
) == 0) {
2208 if (chBest
== NULL
|| ch
->ch_LTime
== 0 ||
2209 ch
->ch_LTime
< chBest
->ch_LTime
) {
2213 if ((rss
.ss_family
== AF_INET
&&
2214 (chBest
->ch_Family
!= AF_INET
||
2215 sin4
->sin_addr
.s_addr
!= chBest
->ch_Addr4
.s_addr
)) ||
2216 chBest
->ch_Service
== NULL
||
2217 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2218 chBest
->ch_Family
= sin4
->sin_family
;
2219 chBest
->ch_Addr4
= sin4
->sin_addr
;
2220 if (chBest
->ch_Service
)
2221 free(chBest
->ch_Service
);
2222 chBest
->ch_Service
= strdup(sep
->se_service
);
2223 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2226 if ((rss
.ss_family
== AF_INET6
&&
2227 (chBest
->ch_Family
!= AF_INET6
||
2228 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2229 &chBest
->ch_Addr6
) == 0)) ||
2230 chBest
->ch_Service
== NULL
||
2231 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2232 chBest
->ch_Family
= sin6
->sin6_family
;
2233 chBest
->ch_Addr6
= sin6
->sin6_addr
;
2234 if (chBest
->ch_Service
)
2235 free(chBest
->ch_Service
);
2236 chBest
->ch_Service
= strdup(sep
->se_service
);
2237 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2240 chBest
->ch_LTime
= t
;
2242 CTime
*ct
= &chBest
->ch_Times
[ticks
% CHTSIZE
];
2243 if (ct
->ct_Ticks
!= ticks
) {
2244 ct
->ct_Ticks
= ticks
;
2249 for (i
= 0; i
< CHTSIZE
; ++i
) {
2250 CTime
*ct
= &chBest
->ch_Times
[i
];
2251 if (ct
->ct_Ticks
<= ticks
&&
2252 ct
->ct_Ticks
>= ticks
- CHTSIZE
) {
2253 cnt
+= ct
->ct_Count
;
2256 if (cnt
* (CHTSIZE
* CHTGRAN
) / 60 > sep
->se_maxcpm
) {
2257 char pname
[INET6_ADDRSTRLEN
];
2259 getnameinfo((struct sockaddr
*)&rss
,
2260 ((struct sockaddr
*)&rss
)->sa_len
,
2261 pname
, sizeof(pname
), NULL
, 0,
2262 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2265 "%s from %s exceeded counts/min (limit %d/min)",
2266 sep
->se_service
, pname
,
2273 static struct conninfo
*
2274 search_conn(struct servtab
*sep
, int ctrl
)
2276 struct sockaddr_storage ss
;
2277 socklen_t sslen
= sizeof(ss
);
2278 struct conninfo
*conn
;
2280 char pname
[NI_MAXHOST
], pname2
[NI_MAXHOST
];
2282 if (sep
->se_maxperip
<= 0)
2286 * If getpeername() fails, just let it through (if logging is
2287 * enabled the condition is caught elsewhere)
2289 if (getpeername(ctrl
, (struct sockaddr
*)&ss
, &sslen
) != 0)
2292 switch (ss
.ss_family
) {
2294 hv
= hashval((char *)&((struct sockaddr_in
*)&ss
)->sin_addr
,
2295 sizeof(struct in_addr
));
2299 hv
= hashval((char *)&((struct sockaddr_in6
*)&ss
)->sin6_addr
,
2300 sizeof(struct in6_addr
));
2305 * Since we only support AF_INET and AF_INET6, just
2306 * let other than AF_INET and AF_INET6 through.
2311 if (getnameinfo((struct sockaddr
*)&ss
, sslen
, pname
, sizeof(pname
),
2312 NULL
, 0, NI_NUMERICHOST
| NI_WITHSCOPEID
) != 0)
2315 LIST_FOREACH(conn
, &sep
->se_conn
[hv
], co_link
) {
2316 if (getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2317 conn
->co_addr
.ss_len
, pname2
, sizeof(pname2
), NULL
, 0,
2318 NI_NUMERICHOST
| NI_WITHSCOPEID
) == 0 &&
2319 strcmp(pname
, pname2
) == 0)
2324 if ((conn
= malloc(sizeof(struct conninfo
))) == NULL
) {
2325 syslog(LOG_ERR
, "malloc: %m");
2328 conn
->co_proc
= malloc(sep
->se_maxperip
* sizeof(*conn
->co_proc
));
2329 if (conn
->co_proc
== NULL
) {
2330 syslog(LOG_ERR
, "malloc: %m");
2333 memcpy(&conn
->co_addr
, (struct sockaddr
*)&ss
, sslen
);
2334 conn
->co_numchild
= 0;
2335 LIST_INSERT_HEAD(&sep
->se_conn
[hv
], conn
, co_link
);
2339 * Since a child process is not invoked yet, we cannot
2340 * determine a pid of a child. So, co_proc and co_numchild
2341 * should be filled leter.
2348 room_conn(struct servtab
*sep
, struct conninfo
*conn
)
2350 char pname
[NI_MAXHOST
];
2352 if (conn
->co_numchild
>= sep
->se_maxperip
) {
2353 getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2354 conn
->co_addr
.ss_len
, pname
, sizeof(pname
), NULL
, 0,
2355 NI_NUMERICHOST
| NI_WITHSCOPEID
);
2356 syslog(LOG_ERR
, "%s from %s exceeded counts (limit %d)",
2357 sep
->se_service
, pname
, sep
->se_maxperip
);
2364 addchild_conn(struct conninfo
*conn
, pid_t pid
)
2366 struct procinfo
*proc
;
2371 if ((proc
= search_proc(pid
, 1)) != NULL
) {
2372 if (proc
->pr_conn
!= NULL
) {
2374 "addchild_conn: child already on process list");
2377 proc
->pr_conn
= conn
;
2380 conn
->co_proc
[conn
->co_numchild
++] = proc
;
2384 reapchild_conn(pid_t pid
)
2386 struct procinfo
*proc
;
2387 struct conninfo
*conn
;
2390 if ((proc
= search_proc(pid
, 0)) == NULL
)
2392 if ((conn
= proc
->pr_conn
) == NULL
)
2394 for (i
= 0; i
< conn
->co_numchild
; ++i
)
2395 if (conn
->co_proc
[i
] == proc
) {
2396 conn
->co_proc
[i
] = conn
->co_proc
[--conn
->co_numchild
];
2404 resize_conn(struct servtab
*sep
, int maxpip
)
2406 struct conninfo
*conn
;
2409 if (sep
->se_maxperip
<= 0)
2415 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2416 LIST_FOREACH(conn
, &sep
->se_conn
[i
], co_link
) {
2417 for (j
= maxpip
; j
< conn
->co_numchild
; ++j
)
2418 free_proc(conn
->co_proc
[j
]);
2419 conn
->co_proc
= realloc(conn
->co_proc
,
2420 maxpip
* sizeof(*conn
->co_proc
));
2421 if (conn
->co_proc
== NULL
) {
2422 syslog(LOG_ERR
, "realloc: %m");
2425 if (conn
->co_numchild
> maxpip
)
2426 conn
->co_numchild
= maxpip
;
2432 free_connlist(struct servtab
*sep
)
2434 struct conninfo
*conn
;
2437 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2438 while ((conn
= LIST_FIRST(&sep
->se_conn
[i
])) != NULL
) {
2439 for (j
= 0; j
< conn
->co_numchild
; ++j
)
2440 free_proc(conn
->co_proc
[j
]);
2441 conn
->co_numchild
= 0;
2448 free_conn(struct conninfo
*conn
)
2452 if (conn
->co_numchild
<= 0) {
2453 LIST_REMOVE(conn
, co_link
);
2454 free(conn
->co_proc
);
2459 static struct procinfo
*
2460 search_proc(pid_t pid
, int add
)
2462 struct procinfo
*proc
;
2465 hv
= hashval((char *)&pid
, sizeof(pid
));
2466 LIST_FOREACH(proc
, &proctable
[hv
], pr_link
) {
2467 if (proc
->pr_pid
== pid
)
2470 if (proc
== NULL
&& add
) {
2471 if ((proc
= malloc(sizeof(struct procinfo
))) == NULL
) {
2472 syslog(LOG_ERR
, "malloc: %m");
2476 proc
->pr_conn
= NULL
;
2477 LIST_INSERT_HEAD(&proctable
[hv
], proc
, pr_link
);
2483 free_proc(struct procinfo
*proc
)
2487 LIST_REMOVE(proc
, pr_link
);
2492 hashval(char *p
, int len
)
2494 int i
, hv
= 0xABC3D20F;
2496 for (i
= 0; i
< len
; ++i
, ++p
)
2497 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2498 hv
= (hv
^ (hv
>> 16)) & (PERIPSIZE
- 1);