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. 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
29 * @(#) Copyright (c) 1983, 1991, 1993, 1994 The Regents of the University of California. All rights reserved.
30 * @(#)from: inetd.c 8.4 (Berkeley) 4/13/94
31 * $FreeBSD: src/usr.sbin/inetd/inetd.c,v 1.80.2.11 2003/04/05 13:39:18 dwmalone Exp $
35 * Inetd - Internet super-server
37 * This program invokes all internet services as needed. Connection-oriented
38 * services are invoked each time a connection is made, by creating a process.
39 * This process is passed the connection as file descriptor 0 and is expected
40 * to do a getpeername to find out the source host and port.
42 * Datagram oriented services are invoked when a datagram
43 * arrives; a process is created and passed a pending message
44 * on file descriptor 0. Datagram servers may either connect
45 * to their peer, freeing up the original socket for inetd
46 * to receive further messages on, or ``take over the socket'',
47 * processing all arriving datagrams and, eventually, timing
48 * out. The first type of server is said to be ``multi-threaded'';
49 * the second type of server ``single-threaded''.
51 * Inetd uses a configuration file which is read at startup
52 * and, possibly, at some later time in response to a hangup signal.
53 * The configuration file is ``free format'' with fields given in the
54 * order shown below. Continuation lines for an entry must begin with
55 * a space or tab. All fields must be present in each entry.
57 * service name must be in /etc/services
58 * or name a tcpmux service
59 * or specify a unix domain socket
60 * socket type stream/dgram/raw/rdm/seqpacket
61 * protocol tcp[4][6][/faith,ttcp], udp[4][6], unix
62 * wait/nowait single-threaded/multi-threaded
63 * user user to run daemon as
64 * server program full path name
65 * server program arguments maximum of MAXARGS (20)
67 * TCP services without official port numbers are handled with the
68 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
69 * requests. When a connection is made from a foreign host, the service
70 * requested is passed to tcpmux, which looks it up in the servtab list
71 * and returns the proper entry for the service. Tcpmux returns a
72 * negative reply if the service doesn't exist, otherwise the invoked
73 * server is expected to return the positive reply if the service type in
74 * inetd.conf file has the prefix "tcpmux/". If the service type has the
75 * prefix "tcpmux/+", tcpmux will return the positive reply for the
76 * process; this is for compatibility with older server code, and also
77 * allows you to invoke programs that use stdin/stdout without putting any
78 * special server code in them. Services that use tcpmux are "nowait"
79 * because they do not have a well-known port and hence cannot listen
83 * service name/version must be in /etc/rpc
84 * socket type stream/dgram/raw/rdm/seqpacket
85 * protocol rpc/tcp, rpc/udp
86 * wait/nowait single-threaded/multi-threaded
87 * user user to run daemon as
88 * server program full path name
89 * server program arguments maximum of MAXARGS
91 * Comment lines are indicated by a `#' in column 1.
94 * Comment lines that start with "#@" denote IPsec policy string, as described
95 * in ipsec_set_policy(3). This will affect all the following items in
96 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
97 * there's no IPsec policy.
100 #include <sys/param.h>
101 #include <sys/ioctl.h>
102 #include <sys/wait.h>
103 #include <sys/time.h>
104 #include <sys/resource.h>
105 #include <sys/stat.h>
108 #include <netinet/in.h>
109 #include <netinet/tcp.h>
110 #include <arpa/inet.h>
112 #include <rpc/pmap_clnt.h>
129 #include <sysexits.h>
133 #include "pathnames.h"
136 #include <netinet6/ipsec.h>
137 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
142 /* wrapper for KAME-special getnameinfo() */
143 #ifndef NI_WITHSCOPEID
144 #define NI_WITHSCOPEID 0
147 #ifndef LIBWRAP_ALLOW_FACILITY
148 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
150 #ifndef LIBWRAP_ALLOW_SEVERITY
151 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
153 #ifndef LIBWRAP_DENY_FACILITY
154 # define LIBWRAP_DENY_FACILITY LOG_AUTH
156 #ifndef LIBWRAP_DENY_SEVERITY
157 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
160 #define ISWRAP(sep) \
161 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
162 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
163 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
164 || (sep)->se_socktype == SOCK_DGRAM))
167 #include <login_cap.h>
170 #define RESOURCE_RC "daemon"
175 #define MAXCHILD -1 /* maximum number of this service
180 #define MAXCPM -1 /* rate limit invocations from a
181 single remote address,
186 #define MAXPERIP -1 /* maximum number of this service
187 from a single remote address,
192 #define TOOMANY 256 /* don't start more than TOOMANY */
194 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
195 #define RETRYTIME (60*10) /* retry after bind or server fail */
196 #define MAX_MAXCHLD 32767 /* max allowable max children */
198 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
200 void close_sep(struct servtab
*);
201 void flag_signal(int);
202 void flag_config(int);
204 int cpmip(const struct servtab
*, int);
205 void endconfig(void);
206 struct servtab
*enter(struct servtab
*);
207 void freeconfig(struct servtab
*);
208 struct servtab
*getconfigent(void);
209 int matchservent(const char *, const char *, const char *);
210 char *nextline(FILE *);
211 void addchild(struct servtab
*, int);
212 void flag_reapchild(int);
213 void reapchild(void);
214 void enable(struct servtab
*);
215 void disable(struct servtab
*);
216 void flag_retry(int);
219 void setup(struct servtab
*);
221 void ipsecsetup(struct servtab
*);
223 void unregisterrpc(struct servtab
*sep
);
224 static struct conninfo
*search_conn(struct servtab
*sep
, int ctrl
);
225 static int room_conn(struct servtab
*sep
, struct conninfo
*conn
);
226 static void addchild_conn(struct conninfo
*conn
, pid_t pid
);
227 static void reapchild_conn(pid_t pid
);
228 static void free_conn(struct conninfo
*conn
);
229 static void resize_conn(struct servtab
*sep
, int maxperip
);
230 static void free_connlist(struct servtab
*sep
);
231 static void free_proc(struct procinfo
*);
232 static struct procinfo
*search_proc(pid_t pid
, int add
);
233 static int hashval(char *p
, int len
);
241 int maxsock
; /* highest-numbered descriptor */
245 int toomany
= TOOMANY
;
246 int maxchild
= MAXCHILD
;
248 int maxperip
= MAXPERIP
;
251 char *hostname
= NULL
;
252 struct sockaddr_in
*bind_sa4
;
255 struct sockaddr_in6
*bind_sa6
;
266 struct servtab
*servtab
;
268 extern struct biltin biltins
[];
270 #define NUMINT (sizeof(intab) / sizeof(struct inent))
271 const char *CONFIG
= _PATH_INETDCONF
;
272 const char *pid_file
= _PATH_INETDPID
;
274 static LIST_HEAD(, procinfo
) proctable
[PERIPSIZE
];
277 getvalue(const char *arg
, int *value
, const char *whine
)
282 tmp
= strtol(arg
, &p
, 0);
284 syslog(LOG_ERR
, whine
, arg
);
285 return 1; /* failure */
288 return 0; /* success */
292 whichaf(struct request_info
*req
)
296 sa
= (struct sockaddr
*)req
->client
->sin
;
299 if (sa
->sa_family
== AF_INET6
&&
300 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)sa
)->sin6_addr
))
302 return sa
->sa_family
;
306 main(int argc
, char **argv
)
311 struct sigaction sa
, saalrm
, sachld
, sahup
, sapipe
;
316 login_cap_t
*lc
= NULL
;
318 struct request_info req
;
320 char *service
= NULL
;
322 struct sockaddr peer_un
;
323 struct sockaddr_in peer_un4
;
324 struct sockaddr_in6 peer_un6
;
325 struct sockaddr_storage peer_max
;
327 #define peer p_un.peer_un
328 #define peer4 p_un.peer_un4
329 #define peer6 p_un.peer_un6
330 #define peermax p_un.peer_max
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.
391 servname
= (hostname
== NULL
) ? "discard" /* dummy */ : NULL
;
393 bzero(&hints
, sizeof(struct addrinfo
));
394 hints
.ai_flags
= AI_PASSIVE
;
395 hints
.ai_family
= AF_UNSPEC
;
396 error
= getaddrinfo(hostname
, servname
, &hints
, &res
);
398 syslog(LOG_ERR
, "-a %s: %s", hostname
, gai_strerror(error
));
399 if (error
== EAI_SYSTEM
)
400 syslog(LOG_ERR
, "%s", strerror(errno
));
404 if (res
->ai_addr
== NULL
) {
405 syslog(LOG_ERR
, "-a %s: getaddrinfo failed", hostname
);
408 switch (res
->ai_addr
->sa_family
) {
412 bind_sa4
= (struct sockaddr_in
*)res
->ai_addr
;
413 /* init port num in case servname is dummy */
414 bind_sa4
->sin_port
= 0;
421 bind_sa6
= (struct sockaddr_in6
*)res
->ai_addr
;
422 /* init port num in case servname is dummy */
423 bind_sa6
->sin6_port
= 0;
434 } while ((res
= res
->ai_next
) != NULL
);
440 syslog(LOG_ERR
, "-a %s: unknown address family", hostname
);
446 umask(mask
= umask(0777));
455 if (daemon(0, 0) < 0) {
456 syslog(LOG_WARNING
, "daemon(0,0) failed: %m");
458 /* From now on we don't want syslog messages going to stderr. */
460 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
462 * In case somebody has started inetd manually, we need to
463 * clear the logname, so that old servers run as root do not
464 * get the user's logname..
466 if (setlogin("") < 0) {
467 syslog(LOG_WARNING
, "cannot clear logname: %m");
468 /* no big deal if it fails.. */
471 fp
= fopen(pid_file
, "w");
473 fprintf(fp
, "%ld\n", (long)pid
);
476 syslog(LOG_WARNING
, "%s: %m", pid_file
);
479 for (i
= 0; i
< PERIPSIZE
; ++i
)
480 LIST_INIT(&proctable
[i
]);
482 sigemptyset(&sa
.sa_mask
);
483 sigaddset(&sa
.sa_mask
, SIGALRM
);
484 sigaddset(&sa
.sa_mask
, SIGCHLD
);
485 sigaddset(&sa
.sa_mask
, SIGHUP
);
486 sa
.sa_handler
= flag_retry
;
487 sigaction(SIGALRM
, &sa
, &saalrm
);
489 sa
.sa_handler
= flag_config
;
490 sigaction(SIGHUP
, &sa
, &sahup
);
491 sa
.sa_handler
= flag_reapchild
;
492 sigaction(SIGCHLD
, &sa
, &sachld
);
493 sa
.sa_handler
= SIG_IGN
;
494 sigaction(SIGPIPE
, &sa
, &sapipe
);
497 /* space for daemons to overwrite environment for ps */
498 #define DUMMYSIZE 100
499 char dummy
[DUMMYSIZE
];
501 memset(dummy
, 'x', DUMMYSIZE
- 1);
502 dummy
[DUMMYSIZE
- 1] = '\0';
503 if (setenv("inetd_dummy", dummy
, 1) == -1)
504 syslog(LOG_WARNING
, "setenv: cannot set inetd_dummy=%s: %m", dummy
);
508 if (pipe(signalpipe
) != 0) {
509 syslog(LOG_ERR
, "pipe: %m");
512 if (fcntl(signalpipe
[0], F_SETFD
, FD_CLOEXEC
) < 0 ||
513 fcntl(signalpipe
[1], F_SETFD
, FD_CLOEXEC
) < 0) {
514 syslog(LOG_ERR
, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
517 FD_SET(signalpipe
[0], &allsock
);
521 if (signalpipe
[0] > maxsock
)
522 maxsock
= signalpipe
[0];
523 if (signalpipe
[1] > maxsock
)
524 maxsock
= signalpipe
[1];
532 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
537 if ((n
= select(maxsock
+ 1, &readable
, NULL
, NULL
, NULL
)) <= 0) {
538 if (n
< 0 && errno
!= EINTR
) {
539 syslog(LOG_WARNING
, "select: %m");
544 /* handle any queued signal flags */
545 if (FD_ISSET(signalpipe
[0], &readable
)) {
547 if (ioctl(signalpipe
[0], FIONREAD
, &nsig
) != 0) {
548 syslog(LOG_ERR
, "ioctl: %m");
551 while (--nsig
>= 0) {
553 if (read(signalpipe
[0], &c
, 1) != 1) {
554 syslog(LOG_ERR
, "read: %m");
558 warnx("handling signal flag %c", c
);
560 case 'A': /* sigalrm */
563 case 'C': /* sigchld */
566 case 'H': /* sighup */
572 for (sep
= servtab
; n
&& sep
; sep
= sep
->se_next
)
573 if (sep
->se_fd
!= -1 && FD_ISSET(sep
->se_fd
, &readable
)) {
576 warnx("someone wants %s", sep
->se_service
);
577 dofork
= !sep
->se_bi
|| sep
->se_bi
->bi_fork
|| ISWRAP(sep
);
579 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
) {
581 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
582 syslog(LOG_ERR
, "ioctl (FIONBIO, 1): %m");
583 ctrl
= accept(sep
->se_fd
, NULL
, NULL
);
585 warnx("accept, ctrl %d", ctrl
);
589 "accept (for %s): %m",
591 if (sep
->se_accept
&&
592 sep
->se_socktype
== SOCK_STREAM
)
597 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
598 syslog(LOG_ERR
, "ioctl1(FIONBIO, 0): %m");
599 if (ioctl(ctrl
, FIONBIO
, &i
) < 0)
600 syslog(LOG_ERR
, "ioctl2(FIONBIO, 0): %m");
601 if (cpmip(sep
, ctrl
) < 0) {
606 (conn
= search_conn(sep
, ctrl
)) != NULL
&&
607 !room_conn(sep
, conn
)) {
613 if (dolog
&& !ISWRAP(sep
)) {
614 char pname
[INET6_ADDRSTRLEN
] = "unknown";
617 if (getpeername(ctrl
, (struct sockaddr
*)
620 if (recvfrom(ctrl
, buf
, sizeof(buf
),
622 (struct sockaddr
*)&peermax
,
624 getnameinfo((struct sockaddr
*)&peermax
,
626 pname
, sizeof(pname
),
632 getnameinfo((struct sockaddr
*)&peermax
,
634 pname
, sizeof(pname
),
639 syslog(LOG_INFO
,"%s from %s", sep
->se_service
, pname
);
644 * Fork for all external services, builtins which need to
645 * fork and anything we're wrapping (as wrapping might
646 * block or use hosts_options(5) twist).
649 if (sep
->se_count
++ == 0)
650 gettimeofday(&sep
->se_time
, NULL
);
651 else if (toomany
> 0 && sep
->se_count
>= toomany
) {
654 gettimeofday(&now
, NULL
);
655 if (now
.tv_sec
- sep
->se_time
.tv_sec
>
661 "%s/%s server failing (looping), service terminated",
662 sep
->se_service
, sep
->se_proto
);
663 if (sep
->se_accept
&&
664 sep
->se_socktype
== SOCK_STREAM
)
679 syslog(LOG_ERR
, "fork: %m");
680 if (sep
->se_accept
&&
681 sep
->se_socktype
== SOCK_STREAM
)
689 addchild_conn(conn
, pid
);
695 sigaction(SIGALRM
, &saalrm
, NULL
);
696 sigaction(SIGCHLD
, &sachld
, NULL
);
697 sigaction(SIGHUP
, &sahup
, NULL
);
698 /* SIGPIPE reset before exec */
701 * Call tcpmux to find the real service to exec.
704 sep
->se_bi
->bi_fn
== (bi_fn_t
*) tcpmux
) {
712 inetd_setproctitle("wrapping", ctrl
);
713 service
= sep
->se_server_name
?
714 sep
->se_server_name
: sep
->se_service
;
715 request_init(&req
, RQ_DAEMON
, service
, RQ_FILE
, ctrl
, NULL
);
717 deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
718 allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
719 denied
= !hosts_access(&req
);
721 syslog(deny_severity
,
722 "refused connection from %.500s, service %s (%s%s)",
723 eval_client(&req
), service
, sep
->se_proto
,
724 (whichaf(&req
) == AF_INET6
) ? "6" : "");
725 if (sep
->se_socktype
!= SOCK_STREAM
)
726 recv(ctrl
, buf
, sizeof (buf
), 0);
733 syslog(allow_severity
,
734 "connection from %.500s, service %s (%s%s)",
735 eval_client(&req
), service
, sep
->se_proto
,
736 (whichaf(&req
) == AF_INET6
) ? "6" : "");
740 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
744 getpid(), sep
->se_server
);
745 /* Clear close-on-exec. */
746 if (fcntl(ctrl
, F_SETFD
, 0) < 0) {
748 "%s/%s: fcntl (F_SETFD, 0): %m",
749 sep
->se_service
, sep
->se_proto
);
758 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
760 "%s/%s: %s: no such user",
761 sep
->se_service
, sep
->se_proto
,
763 if (sep
->se_socktype
!= SOCK_STREAM
)
764 recv(0, buf
, sizeof (buf
), 0);
768 if ( sep
->se_group
!= NULL
769 && (grp
= getgrnam(sep
->se_group
)) == NULL
772 "%s/%s: %s: no such group",
773 sep
->se_service
, sep
->se_proto
,
775 if (sep
->se_socktype
!= SOCK_STREAM
)
776 recv(0, buf
, sizeof (buf
), 0);
780 pwd
->pw_gid
= grp
->gr_gid
;
782 if ((lc
= login_getclass(sep
->se_class
)) == NULL
) {
783 /* error syslogged by getclass */
785 "%s/%s: %s: login class error",
786 sep
->se_service
, sep
->se_proto
,
788 if (sep
->se_socktype
!= SOCK_STREAM
)
789 recv(0, buf
, sizeof (buf
), 0);
795 "%s: can't setsid(): %m",
797 /* _exit(EX_OSERR); not fatal yet */
800 if (setusercontext(lc
, pwd
, pwd
->pw_uid
,
801 LOGIN_SETALL
) != 0) {
803 "%s: can't setusercontext(..%s..): %m",
804 sep
->se_service
, sep
->se_user
);
810 if (setlogin(sep
->se_user
) < 0) {
812 "%s: can't setlogin(%s): %m",
813 sep
->se_service
, sep
->se_user
);
814 /* _exit(EX_OSERR); not yet */
816 if (setgid(pwd
->pw_gid
) < 0) {
818 "%s: can't set gid %d: %m",
819 sep
->se_service
, pwd
->pw_gid
);
822 initgroups(pwd
->pw_name
,
824 if (setuid(pwd
->pw_uid
) < 0) {
826 "%s: can't set uid %d: %m",
827 sep
->se_service
, pwd
->pw_uid
);
832 sigaction(SIGPIPE
, &sapipe
, NULL
);
833 execv(sep
->se_server
, sep
->se_argv
);
835 "cannot execute %s: %m", sep
->se_server
);
836 if (sep
->se_socktype
!= SOCK_STREAM
)
837 recv(0, buf
, sizeof (buf
), 0);
842 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
)
849 * Add a signal flag to the signal flag queue for later handling
857 if (write(signalpipe
[1], &ch
, 1) != 1) {
858 syslog(LOG_ERR
, "write: %m");
864 * Record a new child pid for this service. If we've reached the
865 * limit on children, then stop accepting incoming requests.
869 addchild(struct servtab
*sep
, pid_t pid
)
871 if (sep
->se_maxchild
<= 0)
874 if (sep
->se_numchild
>= sep
->se_maxchild
) {
875 syslog(LOG_ERR
, "%s: %d >= %d",
876 __func__
, sep
->se_numchild
, sep
->se_maxchild
);
880 sep
->se_pids
[sep
->se_numchild
++] = pid
;
881 if (sep
->se_numchild
== sep
->se_maxchild
)
886 * Some child process has exited. See if it's on somebody's list.
890 flag_reapchild(int signo __unused
)
903 pid
= wait3(&status
, WNOHANG
, NULL
);
907 warnx("%d reaped, %s %u", pid
,
908 WIFEXITED(status
) ? "status" : "signal",
909 WIFEXITED(status
) ? WEXITSTATUS(status
)
911 for (sep
= servtab
; sep
; sep
= sep
->se_next
) {
912 for (k
= 0; k
< sep
->se_numchild
; k
++)
913 if (sep
->se_pids
[k
] == pid
)
915 if (k
== sep
->se_numchild
)
917 if (sep
->se_numchild
== sep
->se_maxchild
)
919 sep
->se_pids
[k
] = sep
->se_pids
[--sep
->se_numchild
];
920 if (WIFSIGNALED(status
) || WEXITSTATUS(status
))
922 "%s[%d]: exited, %s %u",
924 WIFEXITED(status
) ? "status" : "signal",
925 WIFEXITED(status
) ? WEXITSTATUS(status
)
934 flag_config(int signo __unused
)
942 struct servtab
*sep
, *new, **sepp
;
945 login_cap_t
*lc
= NULL
;
950 syslog(LOG_ERR
, "%s: %m", CONFIG
);
953 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
955 while ((new = getconfigent())) {
956 if (getpwnam(new->se_user
) == NULL
) {
958 "%s/%s: no such user '%s', service ignored",
959 new->se_service
, new->se_proto
, new->se_user
);
962 if (new->se_group
&& getgrnam(new->se_group
) == NULL
) {
964 "%s/%s: no such group '%s', service ignored",
965 new->se_service
, new->se_proto
, new->se_group
);
969 if ((lc
= login_getclass(new->se_class
)) == NULL
) {
970 /* error syslogged by getclass */
972 "%s/%s: %s: login class error, service ignored",
973 new->se_service
, new->se_proto
, new->se_class
);
978 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
979 if (strcmp(sep
->se_service
, new->se_service
) == 0 &&
980 strcmp(sep
->se_proto
, new->se_proto
) == 0 &&
981 sep
->se_socktype
== new->se_socktype
&&
982 sep
->se_family
== new->se_family
)
987 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
988 omask
= sigblock(SIGBLOCK
);
989 if (sep
->se_nomapped
!= new->se_nomapped
) {
990 sep
->se_nomapped
= new->se_nomapped
;
993 /* copy over outstanding child pids */
994 if (sep
->se_maxchild
> 0 && new->se_maxchild
> 0) {
995 new->se_numchild
= sep
->se_numchild
;
996 if (new->se_numchild
> new->se_maxchild
)
997 new->se_numchild
= new->se_maxchild
;
998 memcpy(new->se_pids
, sep
->se_pids
,
999 new->se_numchild
* sizeof(*new->se_pids
));
1001 SWAP(sep
->se_pids
, new->se_pids
);
1002 sep
->se_maxchild
= new->se_maxchild
;
1003 sep
->se_numchild
= new->se_numchild
;
1004 sep
->se_maxcpm
= new->se_maxcpm
;
1005 resize_conn(sep
, new->se_maxperip
);
1006 sep
->se_maxperip
= new->se_maxperip
;
1007 sep
->se_bi
= new->se_bi
;
1008 /* might need to turn on or off service now */
1009 if (sep
->se_fd
>= 0) {
1010 if (sep
->se_maxchild
> 0
1011 && sep
->se_numchild
== sep
->se_maxchild
) {
1012 if (FD_ISSET(sep
->se_fd
, &allsock
))
1015 if (!FD_ISSET(sep
->se_fd
, &allsock
))
1019 sep
->se_accept
= new->se_accept
;
1020 SWAP(sep
->se_user
, new->se_user
);
1021 SWAP(sep
->se_group
, new->se_group
);
1023 SWAP(sep
->se_class
, new->se_class
);
1025 SWAP(sep
->se_server
, new->se_server
);
1026 SWAP(sep
->se_server_name
, new->se_server_name
);
1027 for (i
= 0; i
< MAXARGV
; i
++)
1028 SWAP(sep
->se_argv
[i
], new->se_argv
[i
]);
1030 SWAP(sep
->se_policy
, new->se_policy
);
1036 print_service("REDO", sep
);
1040 print_service("ADD ", sep
);
1042 sep
->se_checked
= 1;
1047 switch (sep
->se_family
) {
1049 if (no_v4bind
!= 0) {
1056 if (no_v6bind
!= 0) {
1064 if (sep
->se_family
!= AF_UNIX
) {
1065 sp
= getservbyname(sep
->se_service
, sep
->se_proto
);
1067 syslog(LOG_ERR
, "%s/%s: unknown service",
1068 sep
->se_service
, sep
->se_proto
);
1069 sep
->se_checked
= 0;
1073 switch (sep
->se_family
) {
1075 if (sp
->s_port
!= sep
->se_ctrladdr4
.sin_port
) {
1076 sep
->se_ctrladdr4
.sin_port
=
1084 sep
->se_ctrladdr6
.sin6_port
) {
1085 sep
->se_ctrladdr6
.sin6_port
=
1092 if (sep
->se_reset
!= 0 && sep
->se_fd
>= 0)
1095 rpc
= getrpcbyname(sep
->se_service
);
1097 syslog(LOG_ERR
, "%s/%s unknown RPC service",
1098 sep
->se_service
, sep
->se_proto
);
1099 if (sep
->se_fd
!= -1)
1104 if (rpc
->r_number
!= sep
->se_rpc_prog
) {
1105 if (sep
->se_rpc_prog
)
1107 sep
->se_rpc_prog
= rpc
->r_number
;
1108 if (sep
->se_fd
!= -1)
1113 if (sep
->se_fd
== -1)
1118 * Purge anything not looked at above.
1120 omask
= sigblock(SIGBLOCK
);
1122 while ((sep
= *sepp
)) {
1123 if (sep
->se_checked
) {
1124 sepp
= &sep
->se_next
;
1127 *sepp
= sep
->se_next
;
1128 if (sep
->se_fd
>= 0)
1131 print_service("FREE", sep
);
1132 if (sep
->se_rpc
&& sep
->se_rpc_prog
> 0)
1141 unregisterrpc(struct servtab
*sep
)
1144 struct servtab
*sepp
;
1147 omask
= sigblock(SIGBLOCK
);
1148 for (sepp
= servtab
; sepp
; sepp
= sepp
->se_next
) {
1151 if (sep
->se_checked
== 0 ||
1153 sep
->se_rpc_prog
!= sepp
->se_rpc_prog
)
1158 print_service("UNREG", sep
);
1159 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++)
1160 pmap_unset(sep
->se_rpc_prog
, i
);
1161 if (sep
->se_fd
!= -1)
1168 flag_retry(int signo __unused
)
1176 struct servtab
*sep
;
1179 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
1180 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1185 setup(struct servtab
*sep
)
1189 if ((sep
->se_fd
= socket(sep
->se_family
, sep
->se_socktype
, 0)) < 0) {
1191 warn("socket failed on %s/%s",
1192 sep
->se_service
, sep
->se_proto
);
1193 syslog(LOG_ERR
, "%s/%s: socket: %m",
1194 sep
->se_service
, sep
->se_proto
);
1197 /* Set all listening sockets to close-on-exec. */
1198 if (fcntl(sep
->se_fd
, F_SETFD
, FD_CLOEXEC
) < 0) {
1199 syslog(LOG_ERR
, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m",
1200 sep
->se_service
, sep
->se_proto
);
1204 #define turnon(fd, opt) \
1205 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1206 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1207 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1208 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1209 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1210 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1212 if (turnon(sep
->se_fd
, SO_PRIVSTATE
) < 0)
1213 syslog(LOG_ERR
, "setsockopt (SO_PRIVSTATE): %m");
1215 /* tftpd opens a new connection then needs more infos */
1216 if ((sep
->se_family
== AF_INET6
) &&
1217 (strcmp(sep
->se_proto
, "udp") == 0) &&
1218 (sep
->se_accept
== 0) &&
1219 (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_PKTINFO
,
1220 (char *)&on
, sizeof (on
)) < 0))
1221 syslog(LOG_ERR
, "setsockopt (IPV6_RECVPKTINFO): %m");
1222 if (sep
->se_family
== AF_INET6
) {
1223 int flag
= sep
->se_nomapped
? 1 : 0;
1224 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1225 (char *)&flag
, sizeof (flag
)) < 0)
1226 syslog(LOG_ERR
, "setsockopt (IPV6_V6ONLY): %m");
1229 if (sep
->se_type
== TTCP_TYPE
)
1230 if (setsockopt(sep
->se_fd
, IPPROTO_TCP
, TCP_NOPUSH
,
1231 (char *)&on
, sizeof (on
)) < 0)
1232 syslog(LOG_ERR
, "setsockopt (TCP_NOPUSH): %m");
1234 if (sep
->se_type
== FAITH_TYPE
) {
1235 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_FAITH
, &on
,
1237 syslog(LOG_ERR
, "setsockopt (IPV6_FAITH): %m");
1244 if (sep
->se_family
== AF_UNIX
) {
1245 unlink(sep
->se_ctrladdr_un
.sun_path
);
1246 umask(0777); /* Make socket with conservative permissions */
1248 if (bind(sep
->se_fd
, (struct sockaddr
*)&sep
->se_ctrladdr
,
1249 sep
->se_ctrladdr_size
) < 0) {
1251 warn("bind failed on %s/%s",
1252 sep
->se_service
, sep
->se_proto
);
1253 syslog(LOG_ERR
, "%s/%s: bind: %m",
1254 sep
->se_service
, sep
->se_proto
);
1261 if (sep
->se_family
== AF_UNIX
)
1265 if (sep
->se_family
== AF_UNIX
) {
1266 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1267 if (chown(sep
->se_service
, sep
->se_sockuid
, sep
->se_sockgid
) < 0)
1268 syslog(LOG_ERR
, "chown socket: %m");
1269 if (chmod(sep
->se_service
, sep
->se_sockmode
) < 0)
1270 syslog(LOG_ERR
, "chmod socket: %m");
1275 socklen_t len
= sep
->se_ctrladdr_size
;
1277 if (sep
->se_family
!= AF_INET
) {
1279 "%s/%s: unsupported address family for rpc",
1280 sep
->se_service
, sep
->se_proto
);
1285 if (getsockname(sep
->se_fd
,
1286 (struct sockaddr
*)&sep
->se_ctrladdr
, &len
) < 0){
1287 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1288 sep
->se_service
, sep
->se_proto
);
1294 print_service("REG ", sep
);
1295 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++) {
1296 pmap_unset(sep
->se_rpc_prog
, i
);
1297 pmap_set(sep
->se_rpc_prog
, i
,
1298 (sep
->se_socktype
== SOCK_DGRAM
)
1299 ? IPPROTO_UDP
: IPPROTO_TCP
,
1300 ntohs(sep
->se_ctrladdr4
.sin_port
));
1303 if (sep
->se_socktype
== SOCK_STREAM
)
1304 listen(sep
->se_fd
, 64);
1307 warnx("registered %s on %d",
1308 sep
->se_server
, sep
->se_fd
);
1314 ipsecsetup(struct servtab
*sep
)
1317 char *policy_in
= NULL
;
1318 char *policy_out
= NULL
;
1322 switch (sep
->se_family
) {
1325 opt
= IP_IPSEC_POLICY
;
1329 level
= IPPROTO_IPV6
;
1330 opt
= IPV6_IPSEC_POLICY
;
1337 if (!sep
->se_policy
|| sep
->se_policy
[0] == '\0') {
1338 static char def_in
[] = "in entrust", def_out
[] = "out entrust";
1340 policy_out
= def_out
;
1342 if (!strncmp("in", sep
->se_policy
, 2))
1343 policy_in
= sep
->se_policy
;
1344 else if (!strncmp("out", sep
->se_policy
, 3))
1345 policy_out
= sep
->se_policy
;
1347 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1353 if (policy_in
!= NULL
) {
1354 buf
= ipsec_set_policy(policy_in
, strlen(policy_in
));
1356 if (setsockopt(sep
->se_fd
, level
, opt
,
1357 buf
, ipsec_get_policylen(buf
)) < 0 &&
1359 warnx("%s/%s: ipsec initialization failed; %s",
1360 sep
->se_service
, sep
->se_proto
,
1364 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1367 if (policy_out
!= NULL
) {
1368 buf
= ipsec_set_policy(policy_out
, strlen(policy_out
));
1370 if (setsockopt(sep
->se_fd
, level
, opt
,
1371 buf
, ipsec_get_policylen(buf
)) < 0 &&
1373 warnx("%s/%s: ipsec initialization failed; %s",
1374 sep
->se_service
, sep
->se_proto
,
1378 syslog(LOG_ERR
, "invalid security policy \"%s\"",
1385 * Finish with a service and its socket.
1388 close_sep(struct servtab
*sep
)
1390 if (sep
->se_fd
>= 0) {
1391 if (FD_ISSET(sep
->se_fd
, &allsock
))
1397 sep
->se_numchild
= 0; /* forget about any existing children */
1401 matchservent(const char *name1
, const char *name2
, const char *proto
)
1406 if (strcmp(proto
, "unix") == 0) {
1407 if ((p
= strrchr(name1
, '/')) != NULL
)
1409 if ((p
= strrchr(name2
, '/')) != NULL
)
1412 if (strcmp(name1
, name2
) == 0)
1414 if ((se
= getservbyname(name1
, proto
)) != NULL
) {
1415 if (strcmp(name2
, se
->s_name
) == 0)
1417 for (alias
= se
->s_aliases
; *alias
; alias
++)
1418 if (strcmp(name2
, *alias
) == 0)
1425 enter(struct servtab
*cp
)
1427 struct servtab
*sep
;
1430 sep
= (struct servtab
*)malloc(sizeof (*sep
));
1432 syslog(LOG_ERR
, "malloc: %m");
1437 omask
= sigblock(SIGBLOCK
);
1438 sep
->se_next
= servtab
;
1445 enable(struct servtab
*sep
)
1449 "enabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1451 if (sep
->se_fd
< 0) {
1453 "%s: %s: bad fd", __func__
, sep
->se_service
);
1458 "%s: %s: is mux", __func__
, sep
->se_service
);
1461 if (FD_ISSET(sep
->se_fd
, &allsock
)) {
1463 "%s: %s: not off", __func__
, sep
->se_service
);
1468 FD_SET(sep
->se_fd
, &allsock
);
1469 if (sep
->se_fd
> maxsock
)
1470 maxsock
= sep
->se_fd
;
1474 disable(struct servtab
*sep
)
1478 "disabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1480 if (sep
->se_fd
< 0) {
1482 "%s: %s: bad fd", __func__
, sep
->se_service
);
1487 "%s: %s: is mux", __func__
, sep
->se_service
);
1490 if (!FD_ISSET(sep
->se_fd
, &allsock
)) {
1492 "%s: %s: not on", __func__
, sep
->se_service
);
1496 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
1501 FD_CLR(sep
->se_fd
, &allsock
);
1502 if (sep
->se_fd
== maxsock
)
1506 FILE *fconfig
= NULL
;
1507 struct servtab serv
;
1508 char line
[LINE_MAX
];
1514 if (fconfig
!= NULL
) {
1515 fseek(fconfig
, 0L, SEEK_SET
);
1518 fconfig
= fopen(CONFIG
, "r");
1519 return (fconfig
!= NULL
);
1534 struct servtab
*sep
= &serv
;
1538 static char TCPMUX_TOKEN
[] = "tcpmux/";
1539 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1541 char *policy
= NULL
;
1550 while ((cp
= nextline(fconfig
)) != NULL
) {
1552 /* lines starting with #@ is not a comment, but the policy */
1553 if (cp
[0] == '#' && cp
[1] == '@') {
1555 for (p
= cp
+ 2; p
&& *p
&& isspace(*p
); p
++)
1561 } else if (ipsec_get_policylen(p
) >= 0) {
1567 "%s: invalid ipsec policy \"%s\"",
1573 if (*cp
== '#' || *cp
== '\0')
1580 * clear the static buffer, since some fields (se_ctrladdr,
1581 * for example) don't get initialized here.
1583 memset(sep
, 0, sizeof *sep
);
1586 /* got an empty line containing just blanks/tabs. */
1589 if (arg
[0] == ':') { /* :user:group:perm: */
1590 char *user
, *group
, *perm
;
1594 if ((group
= strchr(user
, ':')) == NULL
) {
1595 syslog(LOG_ERR
, "no group after user '%s'", user
);
1599 if ((perm
= strchr(group
, ':')) == NULL
) {
1600 syslog(LOG_ERR
, "no mode after group '%s'", group
);
1604 if ((pw
= getpwnam(user
)) == NULL
) {
1605 syslog(LOG_ERR
, "no such user '%s'", user
);
1608 sep
->se_sockuid
= pw
->pw_uid
;
1609 if ((gr
= getgrnam(group
)) == NULL
) {
1610 syslog(LOG_ERR
, "no such user '%s'", group
);
1613 sep
->se_sockgid
= gr
->gr_gid
;
1614 sep
->se_sockmode
= strtol(perm
, &arg
, 8);
1616 syslog(LOG_ERR
, "bad mode '%s'", perm
);
1621 sep
->se_sockuid
= euid
;
1622 sep
->se_sockgid
= egid
;
1623 sep
->se_sockmode
= 0200;
1625 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1626 char *c
= arg
+ MUX_LEN
;
1628 sep
->se_type
= MUXPLUS_TYPE
;
1631 sep
->se_type
= MUX_TYPE
;
1632 sep
->se_service
= newstr(c
);
1634 sep
->se_service
= newstr(arg
);
1635 sep
->se_type
= NORM_TYPE
;
1638 if (strcmp(arg
, "stream") == 0)
1639 sep
->se_socktype
= SOCK_STREAM
;
1640 else if (strcmp(arg
, "dgram") == 0)
1641 sep
->se_socktype
= SOCK_DGRAM
;
1642 else if (strcmp(arg
, "rdm") == 0)
1643 sep
->se_socktype
= SOCK_RDM
;
1644 else if (strcmp(arg
, "seqpacket") == 0)
1645 sep
->se_socktype
= SOCK_SEQPACKET
;
1646 else if (strcmp(arg
, "raw") == 0)
1647 sep
->se_socktype
= SOCK_RAW
;
1649 sep
->se_socktype
= -1;
1652 if (strncmp(arg
, "tcp", 3) == 0) {
1653 sep
->se_proto
= newstr(strsep(&arg
, "/"));
1655 if (strcmp(arg
, "ttcp") == 0)
1656 sep
->se_type
= TTCP_TYPE
;
1657 else if (strcmp(arg
, "faith") == 0)
1658 sep
->se_type
= FAITH_TYPE
;
1661 if (sep
->se_type
== NORM_TYPE
&&
1662 strncmp(arg
, "faith/", 6) == 0) {
1664 sep
->se_type
= FAITH_TYPE
;
1666 sep
->se_proto
= newstr(arg
);
1668 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1669 if (no_v4bind
!= 0) {
1670 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1675 memmove(sep
->se_proto
, sep
->se_proto
+ 4,
1676 strlen(sep
->se_proto
) + 1 - 4);
1678 sep
->se_rpc_prog
= sep
->se_rpc_lowvers
=
1679 sep
->se_rpc_highvers
= 0;
1680 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1681 sizeof(sep
->se_ctrladdr4
));
1682 if ((versp
= strrchr(sep
->se_service
, '/'))) {
1684 switch (sscanf(versp
, "%u-%u",
1685 &sep
->se_rpc_lowvers
,
1686 &sep
->se_rpc_highvers
)) {
1690 sep
->se_rpc_highvers
=
1691 sep
->se_rpc_lowvers
;
1695 "bad RPC version specifier; %s",
1702 sep
->se_rpc_lowvers
=
1703 sep
->se_rpc_highvers
= 1;
1706 sep
->se_nomapped
= 0;
1707 while (isdigit(sep
->se_proto
[strlen(sep
->se_proto
) - 1])) {
1709 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '6') {
1710 if (no_v6bind
!= 0) {
1711 syslog(LOG_NOTICE
, "IPv6 bind is ignored for %s",
1716 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1721 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '4') {
1722 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1726 /* illegal version num */
1727 syslog(LOG_ERR
, "bad IP version for %s", sep
->se_proto
);
1731 if (strcmp(sep
->se_proto
, "unix") == 0) {
1732 sep
->se_family
= AF_UNIX
;
1736 sep
->se_family
= AF_INET6
;
1737 if (v4bind
== 0 || no_v4bind
!= 0)
1738 sep
->se_nomapped
= 1;
1741 { /* default to v4 bind if not v6 bind */
1742 if (no_v4bind
!= 0) {
1743 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1748 sep
->se_family
= AF_INET
;
1751 switch(sep
->se_family
) {
1753 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1754 sizeof(sep
->se_ctrladdr4
));
1755 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr4
);
1759 memcpy(&sep
->se_ctrladdr6
, bind_sa6
,
1760 sizeof(sep
->se_ctrladdr6
));
1761 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr6
);
1765 if (strlen(sep
->se_service
) >= sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
1767 "domain socket pathname too long for service %s",
1771 memset(&sep
->se_ctrladdr
, 0, sizeof(sep
->se_ctrladdr
));
1772 sep
->se_ctrladdr_un
.sun_family
= sep
->se_family
;
1773 sep
->se_ctrladdr_un
.sun_len
= strlen(sep
->se_service
);
1774 strcpy(sep
->se_ctrladdr_un
.sun_path
, sep
->se_service
);
1775 sep
->se_ctrladdr_size
= SUN_LEN(&sep
->se_ctrladdr_un
);
1778 if (!strncmp(arg
, "wait", 4))
1780 else if (!strncmp(arg
, "nowait", 6))
1784 "%s: bad wait/nowait for service %s",
1785 CONFIG
, sep
->se_service
);
1788 sep
->se_maxchild
= -1;
1789 sep
->se_maxcpm
= -1;
1790 sep
->se_maxperip
= -1;
1791 if ((s
= strchr(arg
, '/')) != NULL
) {
1795 val
= strtoul(s
+ 1, &eptr
, 10);
1796 if (eptr
== s
+ 1 || val
> MAX_MAXCHLD
) {
1798 "%s: bad max-child for service %s",
1799 CONFIG
, sep
->se_service
);
1803 if (!sep
->se_accept
&& val
!= 1)
1804 warnx("maxchild=%lu for wait service %s"
1805 " not recommended", val
, sep
->se_service
);
1806 sep
->se_maxchild
= val
;
1808 sep
->se_maxcpm
= strtol(eptr
+ 1, &eptr
, 10);
1810 sep
->se_maxperip
= strtol(eptr
+ 1, &eptr
, 10);
1812 * explicitly do not check for \0 for future expansion /
1813 * backwards compatibility
1818 * Silently enforce "nowait" mode for TCPMUX services
1819 * since they don't have an assigned port to listen on.
1822 if (strcmp(sep
->se_proto
, "tcp")) {
1824 "%s: bad protocol for tcpmux service %s",
1825 CONFIG
, sep
->se_service
);
1828 if (sep
->se_socktype
!= SOCK_STREAM
) {
1830 "%s: bad socket type for tcpmux service %s",
1831 CONFIG
, sep
->se_service
);
1835 sep
->se_user
= newstr(sskip(&cp
));
1837 if ((s
= strrchr(sep
->se_user
, '/')) != NULL
) {
1839 sep
->se_class
= newstr(s
+ 1);
1841 sep
->se_class
= newstr(RESOURCE_RC
);
1843 if ((s
= strrchr(sep
->se_user
, ':')) != NULL
) {
1845 sep
->se_group
= newstr(s
+ 1);
1847 sep
->se_group
= NULL
;
1848 sep
->se_server
= newstr(sskip(&cp
));
1849 if ((sep
->se_server_name
= strrchr(sep
->se_server
, '/')))
1850 sep
->se_server_name
++;
1851 if (strcmp(sep
->se_server
, "internal") == 0) {
1854 for (bi
= biltins
; bi
->bi_service
; bi
++)
1855 if (bi
->bi_socktype
== sep
->se_socktype
&&
1856 matchservent(bi
->bi_service
, sep
->se_service
,
1859 if (bi
->bi_service
== 0) {
1860 syslog(LOG_ERR
, "internal service %s unknown",
1864 sep
->se_accept
= 1; /* force accept mode for built-ins */
1868 if (sep
->se_maxperip
< 0)
1869 sep
->se_maxperip
= maxperip
;
1870 if (sep
->se_maxcpm
< 0)
1871 sep
->se_maxcpm
= maxcpm
;
1872 if (sep
->se_maxchild
< 0) { /* apply default max-children */
1873 if (sep
->se_bi
&& sep
->se_bi
->bi_maxchild
>= 0)
1874 sep
->se_maxchild
= sep
->se_bi
->bi_maxchild
;
1875 else if (sep
->se_accept
)
1876 sep
->se_maxchild
= maxchild
> 0 ? maxchild
: 0;
1878 sep
->se_maxchild
= 1;
1880 if (sep
->se_maxchild
> 0) {
1881 sep
->se_pids
= malloc(sep
->se_maxchild
* sizeof(*sep
->se_pids
));
1882 if (sep
->se_pids
== NULL
) {
1883 syslog(LOG_ERR
, "malloc: %m");
1888 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
))
1889 if (argc
< MAXARGV
) {
1890 sep
->se_argv
[argc
++] = newstr(arg
);
1893 "%s: too many arguments for service %s",
1894 CONFIG
, sep
->se_service
);
1897 while (argc
<= MAXARGV
)
1898 sep
->se_argv
[argc
++] = NULL
;
1899 for (i
= 0; i
< PERIPSIZE
; ++i
)
1900 LIST_INIT(&sep
->se_conn
[i
]);
1902 sep
->se_policy
= policy
? newstr(policy
) : NULL
;
1908 freeconfig(struct servtab
*cp
)
1913 free(cp
->se_service
);
1925 free(cp
->se_server
);
1928 for (i
= 0; i
< MAXARGV
; i
++)
1930 free(cp
->se_argv
[i
]);
1934 free(cp
->se_policy
);
1940 * Safe skip - if skip returns null, log a syntax error in the
1941 * configuration file and exit.
1950 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
1964 while (*cp
== ' ' || *cp
== '\t')
1971 if (c
== ' ' || c
== '\t')
1972 if ((cp
= nextline(fconfig
)))
1977 if (*cp
== '"' || *cp
== '\'')
1981 while (*cp
&& *cp
!= quote
)
1984 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
1997 if (fgets(line
, sizeof (line
), fd
) == NULL
)
1999 cp
= strchr(line
, '\n');
2006 newstr(const char *cp
)
2010 if ((cr
= strdup(cp
!= NULL
? cp
: "")))
2012 syslog(LOG_ERR
, "strdup: %m");
2017 inetd_setproctitle(const char *a
, int s
)
2020 struct sockaddr_storage ss
;
2021 char buf
[80], pbuf
[INET6_ADDRSTRLEN
];
2024 if (getpeername(s
, (struct sockaddr
*)&ss
, &size
) == 0) {
2025 getnameinfo((struct sockaddr
*)&ss
, size
, pbuf
, sizeof(pbuf
),
2026 NULL
, 0, NI_NUMERICHOST
|NI_WITHSCOPEID
);
2027 sprintf(buf
, "%s [%s]", a
, pbuf
);
2029 sprintf(buf
, "%s", a
);
2030 setproctitle("%s", buf
);
2034 check_loop(const struct sockaddr
*sa
, const struct servtab
*sep
)
2036 struct servtab
*se2
;
2037 char pname
[INET6_ADDRSTRLEN
];
2039 for (se2
= servtab
; se2
; se2
= se2
->se_next
) {
2040 if (!se2
->se_bi
|| se2
->se_socktype
!= SOCK_DGRAM
)
2043 switch (se2
->se_family
) {
2045 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2046 se2
->se_ctrladdr4
.sin_port
)
2051 if (((const struct sockaddr_in
*)sa
)->sin_port
==
2052 se2
->se_ctrladdr4
.sin_port
)
2060 getnameinfo(sa
, sa
->sa_len
, pname
, sizeof(pname
), NULL
, 0,
2061 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2062 syslog(LOG_WARNING
, "%s/%s:%s/%s loop request REFUSED from %s",
2063 sep
->se_service
, sep
->se_proto
,
2064 se2
->se_service
, se2
->se_proto
,
2073 * Dump relevant information to stderr
2076 print_service(const char *action
, const struct servtab
*sep
)
2079 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2083 " builtin=%p server=%s"
2088 action
, sep
->se_service
, sep
->se_proto
,
2089 sep
->se_accept
, sep
->se_maxchild
, sep
->se_user
, sep
->se_group
,
2093 (void *) sep
->se_bi
, sep
->se_server
2095 , (sep
->se_policy
? sep
->se_policy
: "")
2100 #define CPMHSIZE 256
2101 #define CPMHMASK (CPMHSIZE-1)
2105 typedef struct CTime
{
2106 unsigned long ct_Ticks
;
2110 typedef struct CHash
{
2112 struct in_addr c4_Addr
;
2113 struct in6_addr c6_Addr
;
2115 #define ch_Addr4 cu_Addr.c4_Addr
2116 #define ch_Addr6 cu_Addr.c6_Addr
2120 CTime ch_Times
[CHTSIZE
];
2123 CHash CHashAry
[CPMHSIZE
];
2126 cpmip(const struct servtab
*sep
, int ctrl
)
2128 struct sockaddr_storage rss
;
2129 socklen_t rssLen
= sizeof(rss
);
2133 * If getpeername() fails, just let it through (if logging is
2134 * enabled the condition is caught elsewhere)
2137 if (sep
->se_maxcpm
> 0 &&
2138 getpeername(ctrl
, (struct sockaddr
*)&rss
, &rssLen
) == 0 ) {
2139 time_t t
= time(NULL
);
2140 int hv
= 0xABC3D20F;
2143 CHash
*chBest
= NULL
;
2144 unsigned int ticks
= t
/ CHTGRAN
;
2145 struct sockaddr_in
*sin4
;
2147 struct sockaddr_in6
*sin6
;
2150 sin4
= (struct sockaddr_in
*)&rss
;
2152 sin6
= (struct sockaddr_in6
*)&rss
;
2158 switch (rss
.ss_family
) {
2160 p
= (char *)&sin4
->sin_addr
;
2161 addrlen
= sizeof(struct in_addr
);
2165 p
= (char *)&sin6
->sin6_addr
;
2166 addrlen
= sizeof(struct in6_addr
);
2170 /* should not happen */
2174 for (i
= 0; i
< addrlen
; ++i
, ++p
) {
2175 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2177 hv
= (hv
^ (hv
>> 16));
2179 for (i
= 0; i
< 5; ++i
) {
2180 CHash
*ch
= &CHashAry
[(hv
+ i
) & CPMHMASK
];
2182 if (rss
.ss_family
== AF_INET
&&
2183 ch
->ch_Family
== AF_INET
&&
2184 sin4
->sin_addr
.s_addr
== ch
->ch_Addr4
.s_addr
&&
2185 ch
->ch_Service
&& strcmp(sep
->se_service
,
2186 ch
->ch_Service
) == 0) {
2191 if (rss
.ss_family
== AF_INET6
&&
2192 ch
->ch_Family
== AF_INET6
&&
2193 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2194 &ch
->ch_Addr6
) != 0 &&
2195 ch
->ch_Service
&& strcmp(sep
->se_service
,
2196 ch
->ch_Service
) == 0) {
2201 if (chBest
== NULL
|| ch
->ch_LTime
== 0 ||
2202 ch
->ch_LTime
< chBest
->ch_LTime
) {
2206 if ((rss
.ss_family
== AF_INET
&&
2207 (chBest
->ch_Family
!= AF_INET
||
2208 sin4
->sin_addr
.s_addr
!= chBest
->ch_Addr4
.s_addr
)) ||
2209 chBest
->ch_Service
== NULL
||
2210 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2211 chBest
->ch_Family
= sin4
->sin_family
;
2212 chBest
->ch_Addr4
= sin4
->sin_addr
;
2213 if (chBest
->ch_Service
)
2214 free(chBest
->ch_Service
);
2215 chBest
->ch_Service
= strdup(sep
->se_service
);
2216 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2219 if ((rss
.ss_family
== AF_INET6
&&
2220 (chBest
->ch_Family
!= AF_INET6
||
2221 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2222 &chBest
->ch_Addr6
) == 0)) ||
2223 chBest
->ch_Service
== NULL
||
2224 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2225 chBest
->ch_Family
= sin6
->sin6_family
;
2226 chBest
->ch_Addr6
= sin6
->sin6_addr
;
2227 if (chBest
->ch_Service
)
2228 free(chBest
->ch_Service
);
2229 chBest
->ch_Service
= strdup(sep
->se_service
);
2230 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2233 chBest
->ch_LTime
= t
;
2235 CTime
*ct
= &chBest
->ch_Times
[ticks
% CHTSIZE
];
2236 if (ct
->ct_Ticks
!= ticks
) {
2237 ct
->ct_Ticks
= ticks
;
2242 for (i
= 0; i
< CHTSIZE
; ++i
) {
2243 CTime
*ct
= &chBest
->ch_Times
[i
];
2244 if (ct
->ct_Ticks
<= ticks
&&
2245 ct
->ct_Ticks
>= ticks
- CHTSIZE
) {
2246 cnt
+= ct
->ct_Count
;
2249 if (cnt
* (CHTSIZE
* CHTGRAN
) / 60 > sep
->se_maxcpm
) {
2250 char pname
[INET6_ADDRSTRLEN
];
2252 getnameinfo((struct sockaddr
*)&rss
,
2253 ((struct sockaddr
*)&rss
)->sa_len
,
2254 pname
, sizeof(pname
), NULL
, 0,
2255 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2258 "%s from %s exceeded counts/min (limit %d/min)",
2259 sep
->se_service
, pname
,
2266 static struct conninfo
*
2267 search_conn(struct servtab
*sep
, int ctrl
)
2269 struct sockaddr_storage ss
;
2270 socklen_t sslen
= sizeof(ss
);
2271 struct conninfo
*conn
;
2273 char pname
[NI_MAXHOST
], pname2
[NI_MAXHOST
];
2275 if (sep
->se_maxperip
<= 0)
2279 * If getpeername() fails, just let it through (if logging is
2280 * enabled the condition is caught elsewhere)
2282 if (getpeername(ctrl
, (struct sockaddr
*)&ss
, &sslen
) != 0)
2285 switch (ss
.ss_family
) {
2287 hv
= hashval((char *)&((struct sockaddr_in
*)&ss
)->sin_addr
,
2288 sizeof(struct in_addr
));
2292 hv
= hashval((char *)&((struct sockaddr_in6
*)&ss
)->sin6_addr
,
2293 sizeof(struct in6_addr
));
2298 * Since we only support AF_INET and AF_INET6, just
2299 * let other than AF_INET and AF_INET6 through.
2304 if (getnameinfo((struct sockaddr
*)&ss
, sslen
, pname
, sizeof(pname
),
2305 NULL
, 0, NI_NUMERICHOST
| NI_WITHSCOPEID
) != 0)
2308 LIST_FOREACH(conn
, &sep
->se_conn
[hv
], co_link
) {
2309 if (getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2310 conn
->co_addr
.ss_len
, pname2
, sizeof(pname2
), NULL
, 0,
2311 NI_NUMERICHOST
| NI_WITHSCOPEID
) == 0 &&
2312 strcmp(pname
, pname2
) == 0)
2317 if ((conn
= malloc(sizeof(struct conninfo
))) == NULL
) {
2318 syslog(LOG_ERR
, "malloc: %m");
2321 conn
->co_proc
= malloc(sep
->se_maxperip
* sizeof(*conn
->co_proc
));
2322 if (conn
->co_proc
== NULL
) {
2323 syslog(LOG_ERR
, "malloc: %m");
2326 memcpy(&conn
->co_addr
, (struct sockaddr
*)&ss
, sslen
);
2327 conn
->co_numchild
= 0;
2328 LIST_INSERT_HEAD(&sep
->se_conn
[hv
], conn
, co_link
);
2332 * Since a child process is not invoked yet, we cannot
2333 * determine a pid of a child. So, co_proc and co_numchild
2334 * should be filled leter.
2341 room_conn(struct servtab
*sep
, struct conninfo
*conn
)
2343 char pname
[NI_MAXHOST
];
2345 if (conn
->co_numchild
>= sep
->se_maxperip
) {
2346 getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2347 conn
->co_addr
.ss_len
, pname
, sizeof(pname
), NULL
, 0,
2348 NI_NUMERICHOST
| NI_WITHSCOPEID
);
2349 syslog(LOG_ERR
, "%s from %s exceeded counts (limit %d)",
2350 sep
->se_service
, pname
, sep
->se_maxperip
);
2357 addchild_conn(struct conninfo
*conn
, pid_t pid
)
2359 struct procinfo
*proc
;
2364 if ((proc
= search_proc(pid
, 1)) != NULL
) {
2365 if (proc
->pr_conn
!= NULL
) {
2367 "addchild_conn: child already on process list");
2370 proc
->pr_conn
= conn
;
2373 conn
->co_proc
[conn
->co_numchild
++] = proc
;
2377 reapchild_conn(pid_t pid
)
2379 struct procinfo
*proc
;
2380 struct conninfo
*conn
;
2383 if ((proc
= search_proc(pid
, 0)) == NULL
)
2385 if ((conn
= proc
->pr_conn
) == NULL
)
2387 for (i
= 0; i
< conn
->co_numchild
; ++i
)
2388 if (conn
->co_proc
[i
] == proc
) {
2389 conn
->co_proc
[i
] = conn
->co_proc
[--conn
->co_numchild
];
2397 resize_conn(struct servtab
*sep
, int maxpip
)
2399 struct conninfo
*conn
;
2402 if (sep
->se_maxperip
<= 0)
2408 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2409 LIST_FOREACH(conn
, &sep
->se_conn
[i
], co_link
) {
2410 for (j
= maxpip
; j
< conn
->co_numchild
; ++j
)
2411 free_proc(conn
->co_proc
[j
]);
2412 conn
->co_proc
= realloc(conn
->co_proc
,
2413 maxpip
* sizeof(*conn
->co_proc
));
2414 if (conn
->co_proc
== NULL
) {
2415 syslog(LOG_ERR
, "realloc: %m");
2418 if (conn
->co_numchild
> maxpip
)
2419 conn
->co_numchild
= maxpip
;
2425 free_connlist(struct servtab
*sep
)
2427 struct conninfo
*conn
;
2430 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2431 while ((conn
= LIST_FIRST(&sep
->se_conn
[i
])) != NULL
) {
2432 for (j
= 0; j
< conn
->co_numchild
; ++j
)
2433 free_proc(conn
->co_proc
[j
]);
2434 conn
->co_numchild
= 0;
2441 free_conn(struct conninfo
*conn
)
2445 if (conn
->co_numchild
<= 0) {
2446 LIST_REMOVE(conn
, co_link
);
2447 free(conn
->co_proc
);
2452 static struct procinfo
*
2453 search_proc(pid_t pid
, int add
)
2455 struct procinfo
*proc
;
2458 hv
= hashval((char *)&pid
, sizeof(pid
));
2459 LIST_FOREACH(proc
, &proctable
[hv
], pr_link
) {
2460 if (proc
->pr_pid
== pid
)
2463 if (proc
== NULL
&& add
) {
2464 if ((proc
= malloc(sizeof(struct procinfo
))) == NULL
) {
2465 syslog(LOG_ERR
, "malloc: %m");
2469 proc
->pr_conn
= NULL
;
2470 LIST_INSERT_HEAD(&proctable
[hv
], proc
, pr_link
);
2476 free_proc(struct procinfo
*proc
)
2480 LIST_REMOVE(proc
, pr_link
);
2485 hashval(char *p
, int len
)
2487 int i
, hv
= 0xABC3D20F;
2489 for (i
= 0; i
< len
; ++i
, ++p
)
2490 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2491 hv
= (hv
^ (hv
>> 16)) & (PERIPSIZE
- 1);