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][/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.
93 #include <sys/param.h>
94 #include <sys/ioctl.h>
97 #include <sys/resource.h>
101 #include <netinet/in.h>
102 #include <netinet/tcp.h>
103 #include <arpa/inet.h>
105 #include <rpc/pmap_clnt.h>
122 #include <sysexits.h>
126 #include "pathnames.h"
128 /* wrapper for KAME-special getnameinfo() */
129 #ifndef NI_WITHSCOPEID
130 #define NI_WITHSCOPEID 0
133 #ifndef LIBWRAP_ALLOW_FACILITY
134 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
136 #ifndef LIBWRAP_ALLOW_SEVERITY
137 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
139 #ifndef LIBWRAP_DENY_FACILITY
140 # define LIBWRAP_DENY_FACILITY LOG_AUTH
142 #ifndef LIBWRAP_DENY_SEVERITY
143 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
146 #define ISWRAP(sep) \
147 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
148 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
149 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
150 || (sep)->se_socktype == SOCK_DGRAM))
153 #include <login_cap.h>
156 #define RESOURCE_RC "daemon"
161 #define MAXCHILD -1 /* maximum number of this service
166 #define MAXCPM -1 /* rate limit invocations from a
167 single remote address,
172 #define MAXPERIP -1 /* maximum number of this service
173 from a single remote address,
178 #define TOOMANY 256 /* don't start more than TOOMANY */
180 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
181 #define RETRYTIME (60*10) /* retry after bind or server fail */
182 #define MAX_MAXCHLD 32767 /* max allowable max children */
184 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
186 void close_sep(struct servtab
*);
187 void flag_signal(int);
188 void flag_config(int);
190 int cpmip(const struct servtab
*, int);
191 void endconfig(void);
192 struct servtab
*enter(struct servtab
*);
193 void freeconfig(struct servtab
*);
194 struct servtab
*getconfigent(void);
195 int matchservent(const char *, const char *, const char *);
196 char *nextline(FILE *);
197 void addchild(struct servtab
*, int);
198 void flag_reapchild(int);
199 void reapchild(void);
200 void enable(struct servtab
*);
201 void disable(struct servtab
*);
202 void flag_retry(int);
205 void setup(struct servtab
*);
206 void unregisterrpc(struct servtab
*sep
);
207 static struct conninfo
*search_conn(struct servtab
*sep
, int ctrl
);
208 static int room_conn(struct servtab
*sep
, struct conninfo
*conn
);
209 static void addchild_conn(struct conninfo
*conn
, pid_t pid
);
210 static void reapchild_conn(pid_t pid
);
211 static void free_conn(struct conninfo
*conn
);
212 static void resize_conn(struct servtab
*sep
, int maxperip
);
213 static void free_connlist(struct servtab
*sep
);
214 static void free_proc(struct procinfo
*);
215 static struct procinfo
*search_proc(pid_t pid
, int add
);
216 static int hashval(char *p
, int len
);
224 int maxsock
; /* highest-numbered descriptor */
228 int toomany
= TOOMANY
;
229 int maxchild
= MAXCHILD
;
231 int maxperip
= MAXPERIP
;
234 char *hostname
= NULL
;
235 struct sockaddr_in
*bind_sa4
;
238 struct sockaddr_in6
*bind_sa6
;
249 struct servtab
*servtab
;
251 extern struct biltin biltins
[];
253 #define NUMINT (sizeof(intab) / sizeof(struct inent))
254 const char *CONFIG
= _PATH_INETDCONF
;
255 const char *pid_file
= _PATH_INETDPID
;
257 static LIST_HEAD(, procinfo
) proctable
[PERIPSIZE
];
260 getvalue(const char *arg
, int *value
, const char *whine
)
265 tmp
= strtol(arg
, &p
, 0);
267 syslog(LOG_ERR
, whine
, arg
);
268 return 1; /* failure */
271 return 0; /* success */
275 whichaf(struct request_info
*req
)
279 sa
= (struct sockaddr
*)req
->client
->sin
;
282 if (sa
->sa_family
== AF_INET6
&&
283 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)sa
)->sin6_addr
))
285 return sa
->sa_family
;
289 main(int argc
, char **argv
)
294 struct sigaction sa
, saalrm
, sachld
, sahup
, sapipe
;
299 login_cap_t
*lc
= NULL
;
301 struct request_info req
;
303 char *service
= NULL
;
305 struct sockaddr peer_un
;
306 struct sockaddr_in peer_un4
;
307 struct sockaddr_in6 peer_un6
;
308 struct sockaddr_storage peer_max
;
310 #define peer p_un.peer_un
311 #define peer4 p_un.peer_un4
312 #define peer6 p_un.peer_un6
313 #define peermax p_un.peer_max
315 struct addrinfo hints
, *res
;
316 const char *servname
;
318 struct conninfo
*conn
;
320 openlog("inetd", LOG_PID
| LOG_NOWAIT
| LOG_PERROR
, LOG_DAEMON
);
322 while ((ch
= getopt(argc
, argv
, "dlwWR:a:c:C:p:s:")) != -1)
332 getvalue(optarg
, &toomany
,
333 "-R %s: bad value for service invocation rate");
336 getvalue(optarg
, &maxchild
,
337 "-c %s: bad value for maximum children");
340 getvalue(optarg
, &maxcpm
,
341 "-C %s: bad value for maximum children/minute");
350 getvalue(optarg
, &maxperip
,
351 "-s %s: bad value for maximum children per source address");
362 "usage: inetd [-dlwW] [-a address] [-R rate]"
363 " [-c maximum] [-C rate]"
364 " [-p pidfile] [conf-file]");
368 * Initialize Bind Addrs.
369 * When hostname is NULL, wild card bind addrs are obtained from
370 * getaddrinfo(). But getaddrinfo() requires at least one of
371 * hostname or servname is non NULL.
372 * So when hostname is NULL, set dummy value to servname.
374 servname
= (hostname
== NULL
) ? "discard" /* dummy */ : NULL
;
376 bzero(&hints
, sizeof(struct addrinfo
));
377 hints
.ai_flags
= AI_PASSIVE
;
378 hints
.ai_family
= AF_UNSPEC
;
379 error
= getaddrinfo(hostname
, servname
, &hints
, &res
);
381 syslog(LOG_ERR
, "-a %s: %s", hostname
, gai_strerror(error
));
382 if (error
== EAI_SYSTEM
)
383 syslog(LOG_ERR
, "%s", strerror(errno
));
387 if (res
->ai_addr
== NULL
) {
388 syslog(LOG_ERR
, "-a %s: getaddrinfo failed", hostname
);
391 switch (res
->ai_addr
->sa_family
) {
395 bind_sa4
= (struct sockaddr_in
*)res
->ai_addr
;
396 /* init port num in case servname is dummy */
397 bind_sa4
->sin_port
= 0;
404 bind_sa6
= (struct sockaddr_in6
*)res
->ai_addr
;
405 /* init port num in case servname is dummy */
406 bind_sa6
->sin6_port
= 0;
417 } while ((res
= res
->ai_next
) != NULL
);
423 syslog(LOG_ERR
, "-a %s: unknown address family", hostname
);
429 umask(mask
= umask(0777));
438 if (daemon(0, 0) < 0) {
439 syslog(LOG_WARNING
, "daemon(0,0) failed: %m");
441 /* From now on we don't want syslog messages going to stderr. */
443 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
445 * In case somebody has started inetd manually, we need to
446 * clear the logname, so that old servers run as root do not
447 * get the user's logname..
449 if (setlogin("") < 0) {
450 syslog(LOG_WARNING
, "cannot clear logname: %m");
451 /* no big deal if it fails.. */
454 fp
= fopen(pid_file
, "w");
456 fprintf(fp
, "%ld\n", (long)pid
);
459 syslog(LOG_WARNING
, "%s: %m", pid_file
);
462 for (i
= 0; i
< PERIPSIZE
; ++i
)
463 LIST_INIT(&proctable
[i
]);
465 sigemptyset(&sa
.sa_mask
);
466 sigaddset(&sa
.sa_mask
, SIGALRM
);
467 sigaddset(&sa
.sa_mask
, SIGCHLD
);
468 sigaddset(&sa
.sa_mask
, SIGHUP
);
469 sa
.sa_handler
= flag_retry
;
470 sigaction(SIGALRM
, &sa
, &saalrm
);
472 sa
.sa_handler
= flag_config
;
473 sigaction(SIGHUP
, &sa
, &sahup
);
474 sa
.sa_handler
= flag_reapchild
;
475 sigaction(SIGCHLD
, &sa
, &sachld
);
476 sa
.sa_handler
= SIG_IGN
;
477 sigaction(SIGPIPE
, &sa
, &sapipe
);
480 /* space for daemons to overwrite environment for ps */
481 #define DUMMYSIZE 100
482 char dummy
[DUMMYSIZE
];
484 memset(dummy
, 'x', DUMMYSIZE
- 1);
485 dummy
[DUMMYSIZE
- 1] = '\0';
486 if (setenv("inetd_dummy", dummy
, 1) == -1)
487 syslog(LOG_WARNING
, "setenv: cannot set inetd_dummy=%s: %m", dummy
);
491 if (pipe(signalpipe
) != 0) {
492 syslog(LOG_ERR
, "pipe: %m");
495 if (fcntl(signalpipe
[0], F_SETFD
, FD_CLOEXEC
) < 0 ||
496 fcntl(signalpipe
[1], F_SETFD
, FD_CLOEXEC
) < 0) {
497 syslog(LOG_ERR
, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
500 FD_SET(signalpipe
[0], &allsock
);
504 if (signalpipe
[0] > maxsock
)
505 maxsock
= signalpipe
[0];
506 if (signalpipe
[1] > maxsock
)
507 maxsock
= signalpipe
[1];
515 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
520 if ((n
= select(maxsock
+ 1, &readable
, NULL
, NULL
, NULL
)) <= 0) {
521 if (n
< 0 && errno
!= EINTR
) {
522 syslog(LOG_WARNING
, "select: %m");
527 /* handle any queued signal flags */
528 if (FD_ISSET(signalpipe
[0], &readable
)) {
530 if (ioctl(signalpipe
[0], FIONREAD
, &nsig
) != 0) {
531 syslog(LOG_ERR
, "ioctl: %m");
534 while (--nsig
>= 0) {
536 if (read(signalpipe
[0], &c
, 1) != 1) {
537 syslog(LOG_ERR
, "read: %m");
541 warnx("handling signal flag %c", c
);
543 case 'A': /* sigalrm */
546 case 'C': /* sigchld */
549 case 'H': /* sighup */
555 for (sep
= servtab
; n
&& sep
; sep
= sep
->se_next
)
556 if (sep
->se_fd
!= -1 && FD_ISSET(sep
->se_fd
, &readable
)) {
559 warnx("someone wants %s", sep
->se_service
);
560 dofork
= !sep
->se_bi
|| sep
->se_bi
->bi_fork
|| ISWRAP(sep
);
562 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
) {
564 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
565 syslog(LOG_ERR
, "ioctl (FIONBIO, 1): %m");
566 ctrl
= accept(sep
->se_fd
, NULL
, NULL
);
568 warnx("accept, ctrl %d", ctrl
);
572 "accept (for %s): %m",
574 if (sep
->se_accept
&&
575 sep
->se_socktype
== SOCK_STREAM
)
580 if (ioctl(sep
->se_fd
, FIONBIO
, &i
) < 0)
581 syslog(LOG_ERR
, "ioctl1(FIONBIO, 0): %m");
582 if (ioctl(ctrl
, FIONBIO
, &i
) < 0)
583 syslog(LOG_ERR
, "ioctl2(FIONBIO, 0): %m");
584 if (cpmip(sep
, ctrl
) < 0) {
589 (conn
= search_conn(sep
, ctrl
)) != NULL
&&
590 !room_conn(sep
, conn
)) {
596 if (dolog
&& !ISWRAP(sep
)) {
597 char pname
[INET6_ADDRSTRLEN
] = "unknown";
600 if (getpeername(ctrl
, (struct sockaddr
*)
603 if (recvfrom(ctrl
, buf
, sizeof(buf
),
605 (struct sockaddr
*)&peermax
,
607 getnameinfo((struct sockaddr
*)&peermax
,
609 pname
, sizeof(pname
),
615 getnameinfo((struct sockaddr
*)&peermax
,
617 pname
, sizeof(pname
),
622 syslog(LOG_INFO
,"%s from %s", sep
->se_service
, pname
);
627 * Fork for all external services, builtins which need to
628 * fork and anything we're wrapping (as wrapping might
629 * block or use hosts_options(5) twist).
632 if (sep
->se_count
++ == 0)
633 gettimeofday(&sep
->se_time
, NULL
);
634 else if (toomany
> 0 && sep
->se_count
>= toomany
) {
637 gettimeofday(&now
, NULL
);
638 if (now
.tv_sec
- sep
->se_time
.tv_sec
>
644 "%s/%s server failing (looping), service terminated",
645 sep
->se_service
, sep
->se_proto
);
646 if (sep
->se_accept
&&
647 sep
->se_socktype
== SOCK_STREAM
)
662 syslog(LOG_ERR
, "fork: %m");
663 if (sep
->se_accept
&&
664 sep
->se_socktype
== SOCK_STREAM
)
672 addchild_conn(conn
, pid
);
678 sigaction(SIGALRM
, &saalrm
, NULL
);
679 sigaction(SIGCHLD
, &sachld
, NULL
);
680 sigaction(SIGHUP
, &sahup
, NULL
);
681 /* SIGPIPE reset before exec */
684 * Call tcpmux to find the real service to exec.
687 sep
->se_bi
->bi_fn
== (bi_fn_t
*) tcpmux
) {
695 inetd_setproctitle("wrapping", ctrl
);
696 service
= sep
->se_server_name
?
697 sep
->se_server_name
: sep
->se_service
;
698 request_init(&req
, RQ_DAEMON
, service
, RQ_FILE
, ctrl
, NULL
);
700 deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
701 allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
702 denied
= !hosts_access(&req
);
704 syslog(deny_severity
,
705 "refused connection from %.500s, service %s (%s%s)",
706 eval_client(&req
), service
, sep
->se_proto
,
707 (whichaf(&req
) == AF_INET6
) ? "6" : "");
708 if (sep
->se_socktype
!= SOCK_STREAM
)
709 recv(ctrl
, buf
, sizeof (buf
), 0);
716 syslog(allow_severity
,
717 "connection from %.500s, service %s (%s%s)",
718 eval_client(&req
), service
, sep
->se_proto
,
719 (whichaf(&req
) == AF_INET6
) ? "6" : "");
723 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
727 getpid(), sep
->se_server
);
728 /* Clear close-on-exec. */
729 if (fcntl(ctrl
, F_SETFD
, 0) < 0) {
731 "%s/%s: fcntl (F_SETFD, 0): %m",
732 sep
->se_service
, sep
->se_proto
);
741 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
743 "%s/%s: %s: no such user",
744 sep
->se_service
, sep
->se_proto
,
746 if (sep
->se_socktype
!= SOCK_STREAM
)
747 recv(0, buf
, sizeof (buf
), 0);
751 if ( sep
->se_group
!= NULL
752 && (grp
= getgrnam(sep
->se_group
)) == NULL
755 "%s/%s: %s: no such group",
756 sep
->se_service
, sep
->se_proto
,
758 if (sep
->se_socktype
!= SOCK_STREAM
)
759 recv(0, buf
, sizeof (buf
), 0);
763 pwd
->pw_gid
= grp
->gr_gid
;
765 if ((lc
= login_getclass(sep
->se_class
)) == NULL
) {
766 /* error syslogged by getclass */
768 "%s/%s: %s: login class error",
769 sep
->se_service
, sep
->se_proto
,
771 if (sep
->se_socktype
!= SOCK_STREAM
)
772 recv(0, buf
, sizeof (buf
), 0);
778 "%s: can't setsid(): %m",
780 /* _exit(EX_OSERR); not fatal yet */
783 if (setusercontext(lc
, pwd
, pwd
->pw_uid
,
784 LOGIN_SETALL
) != 0) {
786 "%s: can't setusercontext(..%s..): %m",
787 sep
->se_service
, sep
->se_user
);
793 if (setlogin(sep
->se_user
) < 0) {
795 "%s: can't setlogin(%s): %m",
796 sep
->se_service
, sep
->se_user
);
797 /* _exit(EX_OSERR); not yet */
799 if (setgid(pwd
->pw_gid
) < 0) {
801 "%s: can't set gid %d: %m",
802 sep
->se_service
, pwd
->pw_gid
);
805 initgroups(pwd
->pw_name
,
807 if (setuid(pwd
->pw_uid
) < 0) {
809 "%s: can't set uid %d: %m",
810 sep
->se_service
, pwd
->pw_uid
);
815 sigaction(SIGPIPE
, &sapipe
, NULL
);
816 execv(sep
->se_server
, sep
->se_argv
);
818 "cannot execute %s: %m", sep
->se_server
);
819 if (sep
->se_socktype
!= SOCK_STREAM
)
820 recv(0, buf
, sizeof (buf
), 0);
825 if (sep
->se_accept
&& sep
->se_socktype
== SOCK_STREAM
)
832 * Add a signal flag to the signal flag queue for later handling
840 if (write(signalpipe
[1], &ch
, 1) != 1) {
841 syslog(LOG_ERR
, "write: %m");
847 * Record a new child pid for this service. If we've reached the
848 * limit on children, then stop accepting incoming requests.
852 addchild(struct servtab
*sep
, pid_t pid
)
854 if (sep
->se_maxchild
<= 0)
857 if (sep
->se_numchild
>= sep
->se_maxchild
) {
858 syslog(LOG_ERR
, "%s: %d >= %d",
859 __func__
, sep
->se_numchild
, sep
->se_maxchild
);
863 sep
->se_pids
[sep
->se_numchild
++] = pid
;
864 if (sep
->se_numchild
== sep
->se_maxchild
)
869 * Some child process has exited. See if it's on somebody's list.
873 flag_reapchild(int signo __unused
)
886 pid
= wait3(&status
, WNOHANG
, NULL
);
890 warnx("%d reaped, %s %u", pid
,
891 WIFEXITED(status
) ? "status" : "signal",
892 WIFEXITED(status
) ? WEXITSTATUS(status
)
894 for (sep
= servtab
; sep
; sep
= sep
->se_next
) {
895 for (k
= 0; k
< sep
->se_numchild
; k
++)
896 if (sep
->se_pids
[k
] == pid
)
898 if (k
== sep
->se_numchild
)
900 if (sep
->se_numchild
== sep
->se_maxchild
)
902 sep
->se_pids
[k
] = sep
->se_pids
[--sep
->se_numchild
];
903 if (WIFSIGNALED(status
) || WEXITSTATUS(status
))
905 "%s[%d]: exited, %s %u",
907 WIFEXITED(status
) ? "status" : "signal",
908 WIFEXITED(status
) ? WEXITSTATUS(status
)
917 flag_config(int signo __unused
)
925 struct servtab
*sep
, *new, **sepp
;
928 login_cap_t
*lc
= NULL
;
933 syslog(LOG_ERR
, "%s: %m", CONFIG
);
936 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
938 while ((new = getconfigent())) {
939 if (getpwnam(new->se_user
) == NULL
) {
941 "%s/%s: no such user '%s', service ignored",
942 new->se_service
, new->se_proto
, new->se_user
);
945 if (new->se_group
&& getgrnam(new->se_group
) == NULL
) {
947 "%s/%s: no such group '%s', service ignored",
948 new->se_service
, new->se_proto
, new->se_group
);
952 if ((lc
= login_getclass(new->se_class
)) == NULL
) {
953 /* error syslogged by getclass */
955 "%s/%s: %s: login class error, service ignored",
956 new->se_service
, new->se_proto
, new->se_class
);
961 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
962 if (strcmp(sep
->se_service
, new->se_service
) == 0 &&
963 strcmp(sep
->se_proto
, new->se_proto
) == 0 &&
964 sep
->se_socktype
== new->se_socktype
&&
965 sep
->se_family
== new->se_family
)
970 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
971 omask
= sigblock(SIGBLOCK
);
972 if (sep
->se_nomapped
!= new->se_nomapped
) {
973 sep
->se_nomapped
= new->se_nomapped
;
976 /* copy over outstanding child pids */
977 if (sep
->se_maxchild
> 0 && new->se_maxchild
> 0) {
978 new->se_numchild
= sep
->se_numchild
;
979 if (new->se_numchild
> new->se_maxchild
)
980 new->se_numchild
= new->se_maxchild
;
981 memcpy(new->se_pids
, sep
->se_pids
,
982 new->se_numchild
* sizeof(*new->se_pids
));
984 SWAP(sep
->se_pids
, new->se_pids
);
985 sep
->se_maxchild
= new->se_maxchild
;
986 sep
->se_numchild
= new->se_numchild
;
987 sep
->se_maxcpm
= new->se_maxcpm
;
988 resize_conn(sep
, new->se_maxperip
);
989 sep
->se_maxperip
= new->se_maxperip
;
990 sep
->se_bi
= new->se_bi
;
991 /* might need to turn on or off service now */
992 if (sep
->se_fd
>= 0) {
993 if (sep
->se_maxchild
> 0
994 && sep
->se_numchild
== sep
->se_maxchild
) {
995 if (FD_ISSET(sep
->se_fd
, &allsock
))
998 if (!FD_ISSET(sep
->se_fd
, &allsock
))
1002 sep
->se_accept
= new->se_accept
;
1003 SWAP(sep
->se_user
, new->se_user
);
1004 SWAP(sep
->se_group
, new->se_group
);
1006 SWAP(sep
->se_class
, new->se_class
);
1008 SWAP(sep
->se_server
, new->se_server
);
1009 SWAP(sep
->se_server_name
, new->se_server_name
);
1010 for (i
= 0; i
< MAXARGV
; i
++)
1011 SWAP(sep
->se_argv
[i
], new->se_argv
[i
]);
1015 print_service("REDO", sep
);
1019 print_service("ADD ", sep
);
1021 sep
->se_checked
= 1;
1026 switch (sep
->se_family
) {
1028 if (no_v4bind
!= 0) {
1035 if (no_v6bind
!= 0) {
1043 if (sep
->se_family
!= AF_UNIX
) {
1044 sp
= getservbyname(sep
->se_service
, sep
->se_proto
);
1046 syslog(LOG_ERR
, "%s/%s: unknown service",
1047 sep
->se_service
, sep
->se_proto
);
1048 sep
->se_checked
= 0;
1052 switch (sep
->se_family
) {
1054 if (sp
->s_port
!= sep
->se_ctrladdr4
.sin_port
) {
1055 sep
->se_ctrladdr4
.sin_port
=
1063 sep
->se_ctrladdr6
.sin6_port
) {
1064 sep
->se_ctrladdr6
.sin6_port
=
1071 if (sep
->se_reset
!= 0 && sep
->se_fd
>= 0)
1074 rpc
= getrpcbyname(sep
->se_service
);
1076 syslog(LOG_ERR
, "%s/%s unknown RPC service",
1077 sep
->se_service
, sep
->se_proto
);
1078 if (sep
->se_fd
!= -1)
1083 if (rpc
->r_number
!= sep
->se_rpc_prog
) {
1084 if (sep
->se_rpc_prog
)
1086 sep
->se_rpc_prog
= rpc
->r_number
;
1087 if (sep
->se_fd
!= -1)
1092 if (sep
->se_fd
== -1)
1097 * Purge anything not looked at above.
1099 omask
= sigblock(SIGBLOCK
);
1101 while ((sep
= *sepp
)) {
1102 if (sep
->se_checked
) {
1103 sepp
= &sep
->se_next
;
1106 *sepp
= sep
->se_next
;
1107 if (sep
->se_fd
>= 0)
1110 print_service("FREE", sep
);
1111 if (sep
->se_rpc
&& sep
->se_rpc_prog
> 0)
1120 unregisterrpc(struct servtab
*sep
)
1123 struct servtab
*sepp
;
1126 omask
= sigblock(SIGBLOCK
);
1127 for (sepp
= servtab
; sepp
; sepp
= sepp
->se_next
) {
1130 if (sep
->se_checked
== 0 ||
1132 sep
->se_rpc_prog
!= sepp
->se_rpc_prog
)
1137 print_service("UNREG", sep
);
1138 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++)
1139 pmap_unset(sep
->se_rpc_prog
, i
);
1140 if (sep
->se_fd
!= -1)
1147 flag_retry(int signo __unused
)
1155 struct servtab
*sep
;
1158 for (sep
= servtab
; sep
; sep
= sep
->se_next
)
1159 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1164 setup(struct servtab
*sep
)
1168 if ((sep
->se_fd
= socket(sep
->se_family
, sep
->se_socktype
, 0)) < 0) {
1170 warn("socket failed on %s/%s",
1171 sep
->se_service
, sep
->se_proto
);
1172 syslog(LOG_ERR
, "%s/%s: socket: %m",
1173 sep
->se_service
, sep
->se_proto
);
1176 /* Set all listening sockets to close-on-exec. */
1177 if (fcntl(sep
->se_fd
, F_SETFD
, FD_CLOEXEC
) < 0) {
1178 syslog(LOG_ERR
, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m",
1179 sep
->se_service
, sep
->se_proto
);
1183 #define turnon(fd, opt) \
1184 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1185 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1186 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1187 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1188 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1189 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1191 if (turnon(sep
->se_fd
, SO_PRIVSTATE
) < 0)
1192 syslog(LOG_ERR
, "setsockopt (SO_PRIVSTATE): %m");
1194 /* tftpd opens a new connection then needs more infos */
1195 if ((sep
->se_family
== AF_INET6
) &&
1196 (strcmp(sep
->se_proto
, "udp") == 0) &&
1197 (sep
->se_accept
== 0) &&
1198 (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_PKTINFO
,
1199 (char *)&on
, sizeof (on
)) < 0))
1200 syslog(LOG_ERR
, "setsockopt (IPV6_RECVPKTINFO): %m");
1201 if (sep
->se_family
== AF_INET6
) {
1202 int flag
= sep
->se_nomapped
? 1 : 0;
1203 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1204 (char *)&flag
, sizeof (flag
)) < 0)
1205 syslog(LOG_ERR
, "setsockopt (IPV6_V6ONLY): %m");
1208 if (sep
->se_type
== TTCP_TYPE
)
1209 if (setsockopt(sep
->se_fd
, IPPROTO_TCP
, TCP_NOPUSH
,
1210 (char *)&on
, sizeof (on
)) < 0)
1211 syslog(LOG_ERR
, "setsockopt (TCP_NOPUSH): %m");
1212 if (sep
->se_family
== AF_UNIX
) {
1213 unlink(sep
->se_ctrladdr_un
.sun_path
);
1214 umask(0777); /* Make socket with conservative permissions */
1216 if (bind(sep
->se_fd
, (struct sockaddr
*)&sep
->se_ctrladdr
,
1217 sep
->se_ctrladdr_size
) < 0) {
1219 warn("bind failed on %s/%s",
1220 sep
->se_service
, sep
->se_proto
);
1221 syslog(LOG_ERR
, "%s/%s: bind: %m",
1222 sep
->se_service
, sep
->se_proto
);
1229 if (sep
->se_family
== AF_UNIX
)
1233 if (sep
->se_family
== AF_UNIX
) {
1234 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1235 if (chown(sep
->se_service
, sep
->se_sockuid
, sep
->se_sockgid
) < 0)
1236 syslog(LOG_ERR
, "chown socket: %m");
1237 if (chmod(sep
->se_service
, sep
->se_sockmode
) < 0)
1238 syslog(LOG_ERR
, "chmod socket: %m");
1243 socklen_t len
= sep
->se_ctrladdr_size
;
1245 if (sep
->se_family
!= AF_INET
) {
1247 "%s/%s: unsupported address family for rpc",
1248 sep
->se_service
, sep
->se_proto
);
1253 if (getsockname(sep
->se_fd
,
1254 (struct sockaddr
*)&sep
->se_ctrladdr
, &len
) < 0){
1255 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1256 sep
->se_service
, sep
->se_proto
);
1262 print_service("REG ", sep
);
1263 for (i
= sep
->se_rpc_lowvers
; i
<= sep
->se_rpc_highvers
; i
++) {
1264 pmap_unset(sep
->se_rpc_prog
, i
);
1265 pmap_set(sep
->se_rpc_prog
, i
,
1266 (sep
->se_socktype
== SOCK_DGRAM
)
1267 ? IPPROTO_UDP
: IPPROTO_TCP
,
1268 ntohs(sep
->se_ctrladdr4
.sin_port
));
1271 if (sep
->se_socktype
== SOCK_STREAM
)
1272 listen(sep
->se_fd
, 64);
1275 warnx("registered %s on %d",
1276 sep
->se_server
, sep
->se_fd
);
1281 * Finish with a service and its socket.
1284 close_sep(struct servtab
*sep
)
1286 if (sep
->se_fd
>= 0) {
1287 if (FD_ISSET(sep
->se_fd
, &allsock
))
1293 sep
->se_numchild
= 0; /* forget about any existing children */
1297 matchservent(const char *name1
, const char *name2
, const char *proto
)
1302 if (strcmp(proto
, "unix") == 0) {
1303 if ((p
= strrchr(name1
, '/')) != NULL
)
1305 if ((p
= strrchr(name2
, '/')) != NULL
)
1308 if (strcmp(name1
, name2
) == 0)
1310 if ((se
= getservbyname(name1
, proto
)) != NULL
) {
1311 if (strcmp(name2
, se
->s_name
) == 0)
1313 for (alias
= se
->s_aliases
; *alias
; alias
++)
1314 if (strcmp(name2
, *alias
) == 0)
1321 enter(struct servtab
*cp
)
1323 struct servtab
*sep
;
1326 sep
= (struct servtab
*)malloc(sizeof (*sep
));
1328 syslog(LOG_ERR
, "malloc: %m");
1333 omask
= sigblock(SIGBLOCK
);
1334 sep
->se_next
= servtab
;
1341 enable(struct servtab
*sep
)
1345 "enabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1347 if (sep
->se_fd
< 0) {
1349 "%s: %s: bad fd", __func__
, sep
->se_service
);
1354 "%s: %s: is mux", __func__
, sep
->se_service
);
1357 if (FD_ISSET(sep
->se_fd
, &allsock
)) {
1359 "%s: %s: not off", __func__
, sep
->se_service
);
1364 FD_SET(sep
->se_fd
, &allsock
);
1365 if (sep
->se_fd
> maxsock
)
1366 maxsock
= sep
->se_fd
;
1370 disable(struct servtab
*sep
)
1374 "disabling %s, fd %d", sep
->se_service
, sep
->se_fd
);
1376 if (sep
->se_fd
< 0) {
1378 "%s: %s: bad fd", __func__
, sep
->se_service
);
1383 "%s: %s: is mux", __func__
, sep
->se_service
);
1386 if (!FD_ISSET(sep
->se_fd
, &allsock
)) {
1388 "%s: %s: not on", __func__
, sep
->se_service
);
1392 syslog(LOG_ERR
, "%s: nsock=0", __func__
);
1397 FD_CLR(sep
->se_fd
, &allsock
);
1398 if (sep
->se_fd
== maxsock
)
1402 FILE *fconfig
= NULL
;
1403 struct servtab serv
;
1404 char line
[LINE_MAX
];
1410 if (fconfig
!= NULL
) {
1411 fseek(fconfig
, 0L, SEEK_SET
);
1414 fconfig
= fopen(CONFIG
, "r");
1415 return (fconfig
!= NULL
);
1430 struct servtab
*sep
= &serv
;
1434 static char TCPMUX_TOKEN
[] = "tcpmux/";
1435 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1443 while ((cp
= nextline(fconfig
)) != NULL
) {
1444 if (*cp
== '#' || *cp
== '\0')
1451 * clear the static buffer, since some fields (se_ctrladdr,
1452 * for example) don't get initialized here.
1454 memset(sep
, 0, sizeof *sep
);
1457 /* got an empty line containing just blanks/tabs. */
1460 if (arg
[0] == ':') { /* :user:group:perm: */
1461 char *user
, *group
, *perm
;
1465 if ((group
= strchr(user
, ':')) == NULL
) {
1466 syslog(LOG_ERR
, "no group after user '%s'", user
);
1470 if ((perm
= strchr(group
, ':')) == NULL
) {
1471 syslog(LOG_ERR
, "no mode after group '%s'", group
);
1475 if ((pw
= getpwnam(user
)) == NULL
) {
1476 syslog(LOG_ERR
, "no such user '%s'", user
);
1479 sep
->se_sockuid
= pw
->pw_uid
;
1480 if ((gr
= getgrnam(group
)) == NULL
) {
1481 syslog(LOG_ERR
, "no such user '%s'", group
);
1484 sep
->se_sockgid
= gr
->gr_gid
;
1485 sep
->se_sockmode
= strtol(perm
, &arg
, 8);
1487 syslog(LOG_ERR
, "bad mode '%s'", perm
);
1492 sep
->se_sockuid
= euid
;
1493 sep
->se_sockgid
= egid
;
1494 sep
->se_sockmode
= 0200;
1496 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1497 char *c
= arg
+ MUX_LEN
;
1499 sep
->se_type
= MUXPLUS_TYPE
;
1502 sep
->se_type
= MUX_TYPE
;
1503 sep
->se_service
= newstr(c
);
1505 sep
->se_service
= newstr(arg
);
1506 sep
->se_type
= NORM_TYPE
;
1509 if (strcmp(arg
, "stream") == 0)
1510 sep
->se_socktype
= SOCK_STREAM
;
1511 else if (strcmp(arg
, "dgram") == 0)
1512 sep
->se_socktype
= SOCK_DGRAM
;
1513 else if (strcmp(arg
, "rdm") == 0)
1514 sep
->se_socktype
= SOCK_RDM
;
1515 else if (strcmp(arg
, "seqpacket") == 0)
1516 sep
->se_socktype
= SOCK_SEQPACKET
;
1517 else if (strcmp(arg
, "raw") == 0)
1518 sep
->se_socktype
= SOCK_RAW
;
1520 sep
->se_socktype
= -1;
1523 if (strncmp(arg
, "tcp", 3) == 0) {
1524 sep
->se_proto
= newstr(strsep(&arg
, "/"));
1526 if (strcmp(arg
, "ttcp") == 0)
1527 sep
->se_type
= TTCP_TYPE
;
1530 sep
->se_proto
= newstr(arg
);
1532 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1533 if (no_v4bind
!= 0) {
1534 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1539 memmove(sep
->se_proto
, sep
->se_proto
+ 4,
1540 strlen(sep
->se_proto
) + 1 - 4);
1542 sep
->se_rpc_prog
= sep
->se_rpc_lowvers
=
1543 sep
->se_rpc_highvers
= 0;
1544 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1545 sizeof(sep
->se_ctrladdr4
));
1546 if ((versp
= strrchr(sep
->se_service
, '/'))) {
1548 switch (sscanf(versp
, "%u-%u",
1549 &sep
->se_rpc_lowvers
,
1550 &sep
->se_rpc_highvers
)) {
1554 sep
->se_rpc_highvers
=
1555 sep
->se_rpc_lowvers
;
1559 "bad RPC version specifier; %s",
1566 sep
->se_rpc_lowvers
=
1567 sep
->se_rpc_highvers
= 1;
1570 sep
->se_nomapped
= 0;
1571 while (isdigit(sep
->se_proto
[strlen(sep
->se_proto
) - 1])) {
1573 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '6') {
1574 if (no_v6bind
!= 0) {
1575 syslog(LOG_NOTICE
, "IPv6 bind is ignored for %s",
1580 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1585 if (sep
->se_proto
[strlen(sep
->se_proto
) - 1] == '4') {
1586 sep
->se_proto
[strlen(sep
->se_proto
) - 1] = '\0';
1590 /* illegal version num */
1591 syslog(LOG_ERR
, "bad IP version for %s", sep
->se_proto
);
1595 if (strcmp(sep
->se_proto
, "unix") == 0) {
1596 sep
->se_family
= AF_UNIX
;
1600 sep
->se_family
= AF_INET6
;
1601 if (v4bind
== 0 || no_v4bind
!= 0)
1602 sep
->se_nomapped
= 1;
1605 { /* default to v4 bind if not v6 bind */
1606 if (no_v4bind
!= 0) {
1607 syslog(LOG_NOTICE
, "IPv4 bind is ignored for %s",
1612 sep
->se_family
= AF_INET
;
1615 switch(sep
->se_family
) {
1617 memcpy(&sep
->se_ctrladdr4
, bind_sa4
,
1618 sizeof(sep
->se_ctrladdr4
));
1619 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr4
);
1623 memcpy(&sep
->se_ctrladdr6
, bind_sa6
,
1624 sizeof(sep
->se_ctrladdr6
));
1625 sep
->se_ctrladdr_size
= sizeof(sep
->se_ctrladdr6
);
1629 if (strlen(sep
->se_service
) >= sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
1631 "domain socket pathname too long for service %s",
1635 memset(&sep
->se_ctrladdr
, 0, sizeof(sep
->se_ctrladdr
));
1636 sep
->se_ctrladdr_un
.sun_family
= sep
->se_family
;
1637 sep
->se_ctrladdr_un
.sun_len
= strlen(sep
->se_service
);
1638 strcpy(sep
->se_ctrladdr_un
.sun_path
, sep
->se_service
);
1639 sep
->se_ctrladdr_size
= SUN_LEN(&sep
->se_ctrladdr_un
);
1642 if (!strncmp(arg
, "wait", 4))
1644 else if (!strncmp(arg
, "nowait", 6))
1648 "%s: bad wait/nowait for service %s",
1649 CONFIG
, sep
->se_service
);
1652 sep
->se_maxchild
= -1;
1653 sep
->se_maxcpm
= -1;
1654 sep
->se_maxperip
= -1;
1655 if ((s
= strchr(arg
, '/')) != NULL
) {
1659 val
= strtoul(s
+ 1, &eptr
, 10);
1660 if (eptr
== s
+ 1 || val
> MAX_MAXCHLD
) {
1662 "%s: bad max-child for service %s",
1663 CONFIG
, sep
->se_service
);
1667 if (!sep
->se_accept
&& val
!= 1)
1668 warnx("maxchild=%lu for wait service %s"
1669 " not recommended", val
, sep
->se_service
);
1670 sep
->se_maxchild
= val
;
1672 sep
->se_maxcpm
= strtol(eptr
+ 1, &eptr
, 10);
1674 sep
->se_maxperip
= strtol(eptr
+ 1, &eptr
, 10);
1676 * explicitly do not check for \0 for future expansion /
1677 * backwards compatibility
1682 * Silently enforce "nowait" mode for TCPMUX services
1683 * since they don't have an assigned port to listen on.
1686 if (strcmp(sep
->se_proto
, "tcp")) {
1688 "%s: bad protocol for tcpmux service %s",
1689 CONFIG
, sep
->se_service
);
1692 if (sep
->se_socktype
!= SOCK_STREAM
) {
1694 "%s: bad socket type for tcpmux service %s",
1695 CONFIG
, sep
->se_service
);
1699 sep
->se_user
= newstr(sskip(&cp
));
1701 if ((s
= strrchr(sep
->se_user
, '/')) != NULL
) {
1703 sep
->se_class
= newstr(s
+ 1);
1705 sep
->se_class
= newstr(RESOURCE_RC
);
1707 if ((s
= strrchr(sep
->se_user
, ':')) != NULL
) {
1709 sep
->se_group
= newstr(s
+ 1);
1711 sep
->se_group
= NULL
;
1712 sep
->se_server
= newstr(sskip(&cp
));
1713 if ((sep
->se_server_name
= strrchr(sep
->se_server
, '/')))
1714 sep
->se_server_name
++;
1715 if (strcmp(sep
->se_server
, "internal") == 0) {
1718 for (bi
= biltins
; bi
->bi_service
; bi
++)
1719 if (bi
->bi_socktype
== sep
->se_socktype
&&
1720 matchservent(bi
->bi_service
, sep
->se_service
,
1723 if (bi
->bi_service
== 0) {
1724 syslog(LOG_ERR
, "internal service %s unknown",
1728 sep
->se_accept
= 1; /* force accept mode for built-ins */
1732 if (sep
->se_maxperip
< 0)
1733 sep
->se_maxperip
= maxperip
;
1734 if (sep
->se_maxcpm
< 0)
1735 sep
->se_maxcpm
= maxcpm
;
1736 if (sep
->se_maxchild
< 0) { /* apply default max-children */
1737 if (sep
->se_bi
&& sep
->se_bi
->bi_maxchild
>= 0)
1738 sep
->se_maxchild
= sep
->se_bi
->bi_maxchild
;
1739 else if (sep
->se_accept
)
1740 sep
->se_maxchild
= maxchild
> 0 ? maxchild
: 0;
1742 sep
->se_maxchild
= 1;
1744 if (sep
->se_maxchild
> 0) {
1745 sep
->se_pids
= malloc(sep
->se_maxchild
* sizeof(*sep
->se_pids
));
1746 if (sep
->se_pids
== NULL
) {
1747 syslog(LOG_ERR
, "malloc: %m");
1752 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
))
1753 if (argc
< MAXARGV
) {
1754 sep
->se_argv
[argc
++] = newstr(arg
);
1757 "%s: too many arguments for service %s",
1758 CONFIG
, sep
->se_service
);
1761 while (argc
<= MAXARGV
)
1762 sep
->se_argv
[argc
++] = NULL
;
1763 for (i
= 0; i
< PERIPSIZE
; ++i
)
1764 LIST_INIT(&sep
->se_conn
[i
]);
1769 freeconfig(struct servtab
*cp
)
1774 free(cp
->se_service
);
1786 free(cp
->se_server
);
1789 for (i
= 0; i
< MAXARGV
; i
++)
1791 free(cp
->se_argv
[i
]);
1797 * Safe skip - if skip returns null, log a syntax error in the
1798 * configuration file and exit.
1807 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
1821 while (*cp
== ' ' || *cp
== '\t')
1828 if (c
== ' ' || c
== '\t')
1829 if ((cp
= nextline(fconfig
)))
1834 if (*cp
== '"' || *cp
== '\'')
1838 while (*cp
&& *cp
!= quote
)
1841 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
1854 if (fgets(line
, sizeof (line
), fd
) == NULL
)
1856 cp
= strchr(line
, '\n');
1863 newstr(const char *cp
)
1867 if ((cr
= strdup(cp
!= NULL
? cp
: "")))
1869 syslog(LOG_ERR
, "strdup: %m");
1874 inetd_setproctitle(const char *a
, int s
)
1877 struct sockaddr_storage ss
;
1878 char buf
[80], pbuf
[INET6_ADDRSTRLEN
];
1881 if (getpeername(s
, (struct sockaddr
*)&ss
, &size
) == 0) {
1882 getnameinfo((struct sockaddr
*)&ss
, size
, pbuf
, sizeof(pbuf
),
1883 NULL
, 0, NI_NUMERICHOST
|NI_WITHSCOPEID
);
1884 sprintf(buf
, "%s [%s]", a
, pbuf
);
1886 sprintf(buf
, "%s", a
);
1887 setproctitle("%s", buf
);
1891 check_loop(const struct sockaddr
*sa
, const struct servtab
*sep
)
1893 struct servtab
*se2
;
1894 char pname
[INET6_ADDRSTRLEN
];
1896 for (se2
= servtab
; se2
; se2
= se2
->se_next
) {
1897 if (!se2
->se_bi
|| se2
->se_socktype
!= SOCK_DGRAM
)
1900 switch (se2
->se_family
) {
1902 if (((const struct sockaddr_in
*)sa
)->sin_port
==
1903 se2
->se_ctrladdr4
.sin_port
)
1908 if (((const struct sockaddr_in
*)sa
)->sin_port
==
1909 se2
->se_ctrladdr4
.sin_port
)
1917 getnameinfo(sa
, sa
->sa_len
, pname
, sizeof(pname
), NULL
, 0,
1918 NI_NUMERICHOST
|NI_WITHSCOPEID
);
1919 syslog(LOG_WARNING
, "%s/%s:%s/%s loop request REFUSED from %s",
1920 sep
->se_service
, sep
->se_proto
,
1921 se2
->se_service
, se2
->se_proto
,
1930 * Dump relevant information to stderr
1933 print_service(const char *action
, const struct servtab
*sep
)
1936 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
1940 " builtin=%p server=%s"
1942 action
, sep
->se_service
, sep
->se_proto
,
1943 sep
->se_accept
, sep
->se_maxchild
, sep
->se_user
, sep
->se_group
,
1947 (void *) sep
->se_bi
, sep
->se_server
1951 #define CPMHSIZE 256
1952 #define CPMHMASK (CPMHSIZE-1)
1956 typedef struct CTime
{
1957 unsigned long ct_Ticks
;
1961 typedef struct CHash
{
1963 struct in_addr c4_Addr
;
1964 struct in6_addr c6_Addr
;
1966 #define ch_Addr4 cu_Addr.c4_Addr
1967 #define ch_Addr6 cu_Addr.c6_Addr
1971 CTime ch_Times
[CHTSIZE
];
1974 CHash CHashAry
[CPMHSIZE
];
1977 cpmip(const struct servtab
*sep
, int ctrl
)
1979 struct sockaddr_storage rss
;
1980 socklen_t rssLen
= sizeof(rss
);
1984 * If getpeername() fails, just let it through (if logging is
1985 * enabled the condition is caught elsewhere)
1988 if (sep
->se_maxcpm
> 0 &&
1989 getpeername(ctrl
, (struct sockaddr
*)&rss
, &rssLen
) == 0 ) {
1990 time_t t
= time(NULL
);
1991 int hv
= 0xABC3D20F;
1994 CHash
*chBest
= NULL
;
1995 unsigned int ticks
= t
/ CHTGRAN
;
1996 struct sockaddr_in
*sin4
;
1998 struct sockaddr_in6
*sin6
;
2001 sin4
= (struct sockaddr_in
*)&rss
;
2003 sin6
= (struct sockaddr_in6
*)&rss
;
2009 switch (rss
.ss_family
) {
2011 p
= (char *)&sin4
->sin_addr
;
2012 addrlen
= sizeof(struct in_addr
);
2016 p
= (char *)&sin6
->sin6_addr
;
2017 addrlen
= sizeof(struct in6_addr
);
2021 /* should not happen */
2025 for (i
= 0; i
< addrlen
; ++i
, ++p
) {
2026 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2028 hv
= (hv
^ (hv
>> 16));
2030 for (i
= 0; i
< 5; ++i
) {
2031 CHash
*ch
= &CHashAry
[(hv
+ i
) & CPMHMASK
];
2033 if (rss
.ss_family
== AF_INET
&&
2034 ch
->ch_Family
== AF_INET
&&
2035 sin4
->sin_addr
.s_addr
== ch
->ch_Addr4
.s_addr
&&
2036 ch
->ch_Service
&& strcmp(sep
->se_service
,
2037 ch
->ch_Service
) == 0) {
2042 if (rss
.ss_family
== AF_INET6
&&
2043 ch
->ch_Family
== AF_INET6
&&
2044 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2045 &ch
->ch_Addr6
) != 0 &&
2046 ch
->ch_Service
&& strcmp(sep
->se_service
,
2047 ch
->ch_Service
) == 0) {
2052 if (chBest
== NULL
|| ch
->ch_LTime
== 0 ||
2053 ch
->ch_LTime
< chBest
->ch_LTime
) {
2057 if ((rss
.ss_family
== AF_INET
&&
2058 (chBest
->ch_Family
!= AF_INET
||
2059 sin4
->sin_addr
.s_addr
!= chBest
->ch_Addr4
.s_addr
)) ||
2060 chBest
->ch_Service
== NULL
||
2061 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2062 chBest
->ch_Family
= sin4
->sin_family
;
2063 chBest
->ch_Addr4
= sin4
->sin_addr
;
2064 if (chBest
->ch_Service
)
2065 free(chBest
->ch_Service
);
2066 chBest
->ch_Service
= strdup(sep
->se_service
);
2067 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2070 if ((rss
.ss_family
== AF_INET6
&&
2071 (chBest
->ch_Family
!= AF_INET6
||
2072 IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
,
2073 &chBest
->ch_Addr6
) == 0)) ||
2074 chBest
->ch_Service
== NULL
||
2075 strcmp(sep
->se_service
, chBest
->ch_Service
) != 0) {
2076 chBest
->ch_Family
= sin6
->sin6_family
;
2077 chBest
->ch_Addr6
= sin6
->sin6_addr
;
2078 if (chBest
->ch_Service
)
2079 free(chBest
->ch_Service
);
2080 chBest
->ch_Service
= strdup(sep
->se_service
);
2081 bzero(chBest
->ch_Times
, sizeof(chBest
->ch_Times
));
2084 chBest
->ch_LTime
= t
;
2086 CTime
*ct
= &chBest
->ch_Times
[ticks
% CHTSIZE
];
2087 if (ct
->ct_Ticks
!= ticks
) {
2088 ct
->ct_Ticks
= ticks
;
2093 for (i
= 0; i
< CHTSIZE
; ++i
) {
2094 CTime
*ct
= &chBest
->ch_Times
[i
];
2095 if (ct
->ct_Ticks
<= ticks
&&
2096 ct
->ct_Ticks
>= ticks
- CHTSIZE
) {
2097 cnt
+= ct
->ct_Count
;
2100 if (cnt
* (CHTSIZE
* CHTGRAN
) / 60 > sep
->se_maxcpm
) {
2101 char pname
[INET6_ADDRSTRLEN
];
2103 getnameinfo((struct sockaddr
*)&rss
,
2104 ((struct sockaddr
*)&rss
)->sa_len
,
2105 pname
, sizeof(pname
), NULL
, 0,
2106 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2109 "%s from %s exceeded counts/min (limit %d/min)",
2110 sep
->se_service
, pname
,
2117 static struct conninfo
*
2118 search_conn(struct servtab
*sep
, int ctrl
)
2120 struct sockaddr_storage ss
;
2121 socklen_t sslen
= sizeof(ss
);
2122 struct conninfo
*conn
;
2124 char pname
[NI_MAXHOST
], pname2
[NI_MAXHOST
];
2126 if (sep
->se_maxperip
<= 0)
2130 * If getpeername() fails, just let it through (if logging is
2131 * enabled the condition is caught elsewhere)
2133 if (getpeername(ctrl
, (struct sockaddr
*)&ss
, &sslen
) != 0)
2136 switch (ss
.ss_family
) {
2138 hv
= hashval((char *)&((struct sockaddr_in
*)&ss
)->sin_addr
,
2139 sizeof(struct in_addr
));
2143 hv
= hashval((char *)&((struct sockaddr_in6
*)&ss
)->sin6_addr
,
2144 sizeof(struct in6_addr
));
2149 * Since we only support AF_INET and AF_INET6, just
2150 * let other than AF_INET and AF_INET6 through.
2155 if (getnameinfo((struct sockaddr
*)&ss
, sslen
, pname
, sizeof(pname
),
2156 NULL
, 0, NI_NUMERICHOST
| NI_WITHSCOPEID
) != 0)
2159 LIST_FOREACH(conn
, &sep
->se_conn
[hv
], co_link
) {
2160 if (getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2161 conn
->co_addr
.ss_len
, pname2
, sizeof(pname2
), NULL
, 0,
2162 NI_NUMERICHOST
| NI_WITHSCOPEID
) == 0 &&
2163 strcmp(pname
, pname2
) == 0)
2168 if ((conn
= malloc(sizeof(struct conninfo
))) == NULL
) {
2169 syslog(LOG_ERR
, "malloc: %m");
2172 conn
->co_proc
= malloc(sep
->se_maxperip
* sizeof(*conn
->co_proc
));
2173 if (conn
->co_proc
== NULL
) {
2174 syslog(LOG_ERR
, "malloc: %m");
2177 memcpy(&conn
->co_addr
, (struct sockaddr
*)&ss
, sslen
);
2178 conn
->co_numchild
= 0;
2179 LIST_INSERT_HEAD(&sep
->se_conn
[hv
], conn
, co_link
);
2183 * Since a child process is not invoked yet, we cannot
2184 * determine a pid of a child. So, co_proc and co_numchild
2185 * should be filled leter.
2192 room_conn(struct servtab
*sep
, struct conninfo
*conn
)
2194 char pname
[NI_MAXHOST
];
2196 if (conn
->co_numchild
>= sep
->se_maxperip
) {
2197 getnameinfo((struct sockaddr
*)&conn
->co_addr
,
2198 conn
->co_addr
.ss_len
, pname
, sizeof(pname
), NULL
, 0,
2199 NI_NUMERICHOST
| NI_WITHSCOPEID
);
2200 syslog(LOG_ERR
, "%s from %s exceeded counts (limit %d)",
2201 sep
->se_service
, pname
, sep
->se_maxperip
);
2208 addchild_conn(struct conninfo
*conn
, pid_t pid
)
2210 struct procinfo
*proc
;
2215 if ((proc
= search_proc(pid
, 1)) != NULL
) {
2216 if (proc
->pr_conn
!= NULL
) {
2218 "addchild_conn: child already on process list");
2221 proc
->pr_conn
= conn
;
2224 conn
->co_proc
[conn
->co_numchild
++] = proc
;
2228 reapchild_conn(pid_t pid
)
2230 struct procinfo
*proc
;
2231 struct conninfo
*conn
;
2234 if ((proc
= search_proc(pid
, 0)) == NULL
)
2236 if ((conn
= proc
->pr_conn
) == NULL
)
2238 for (i
= 0; i
< conn
->co_numchild
; ++i
)
2239 if (conn
->co_proc
[i
] == proc
) {
2240 conn
->co_proc
[i
] = conn
->co_proc
[--conn
->co_numchild
];
2248 resize_conn(struct servtab
*sep
, int maxpip
)
2250 struct conninfo
*conn
;
2253 if (sep
->se_maxperip
<= 0)
2259 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2260 LIST_FOREACH(conn
, &sep
->se_conn
[i
], co_link
) {
2261 for (j
= maxpip
; j
< conn
->co_numchild
; ++j
)
2262 free_proc(conn
->co_proc
[j
]);
2263 conn
->co_proc
= realloc(conn
->co_proc
,
2264 maxpip
* sizeof(*conn
->co_proc
));
2265 if (conn
->co_proc
== NULL
) {
2266 syslog(LOG_ERR
, "realloc: %m");
2269 if (conn
->co_numchild
> maxpip
)
2270 conn
->co_numchild
= maxpip
;
2276 free_connlist(struct servtab
*sep
)
2278 struct conninfo
*conn
;
2281 for (i
= 0; i
< PERIPSIZE
; ++i
) {
2282 while ((conn
= LIST_FIRST(&sep
->se_conn
[i
])) != NULL
) {
2283 for (j
= 0; j
< conn
->co_numchild
; ++j
)
2284 free_proc(conn
->co_proc
[j
]);
2285 conn
->co_numchild
= 0;
2292 free_conn(struct conninfo
*conn
)
2296 if (conn
->co_numchild
<= 0) {
2297 LIST_REMOVE(conn
, co_link
);
2298 free(conn
->co_proc
);
2303 static struct procinfo
*
2304 search_proc(pid_t pid
, int add
)
2306 struct procinfo
*proc
;
2309 hv
= hashval((char *)&pid
, sizeof(pid
));
2310 LIST_FOREACH(proc
, &proctable
[hv
], pr_link
) {
2311 if (proc
->pr_pid
== pid
)
2314 if (proc
== NULL
&& add
) {
2315 if ((proc
= malloc(sizeof(struct procinfo
))) == NULL
) {
2316 syslog(LOG_ERR
, "malloc: %m");
2320 proc
->pr_conn
= NULL
;
2321 LIST_INSERT_HEAD(&proctable
[hv
], proc
, pr_link
);
2327 free_proc(struct procinfo
*proc
)
2331 LIST_REMOVE(proc
, pr_link
);
2336 hashval(char *p
, int len
)
2338 int i
, hv
= 0xABC3D20F;
2340 for (i
= 0; i
< len
; ++i
, ++p
)
2341 hv
= (hv
<< 5) ^ (hv
>> 23) ^ *p
;
2342 hv
= (hv
^ (hv
>> 16)) & (PERIPSIZE
- 1);