1 /* $NetBSD: inetd.c,v 1.122 2014/04/05 23:36:10 khorben Exp $ */
4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Matthias Scheler.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1983, 1991, 1993, 1994
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 #include <sys/cdefs.h>
64 __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\
65 The Regents of the University of California. All rights reserved.");
67 static char sccsid
[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94";
69 __RCSID("$NetBSD: inetd.c,v 1.122 2014/04/05 23:36:10 khorben Exp $");
74 * Inetd - Internet super-server
76 * This program invokes all internet services as needed. Connection-oriented
77 * services are invoked each time a connection is made, by creating a process.
78 * This process is passed the connection as file descriptor 0 and is expected
79 * to do a getpeername to find out the source host and port.
81 * Datagram oriented services are invoked when a datagram
82 * arrives; a process is created and passed a pending message
83 * on file descriptor 0. Datagram servers may either connect
84 * to their peer, freeing up the original socket for inetd
85 * to receive further messages on, or ``take over the socket'',
86 * processing all arriving datagrams and, eventually, timing
87 * out. The first type of server is said to be ``multi-threaded'';
88 * the second type of server ``single-threaded''.
90 * Inetd uses a configuration file which is read at startup
91 * and, possibly, at some later time in response to a hangup signal.
92 * The configuration file is ``free format'' with fields given in the
93 * order shown below. Continuation lines for an entry must being with
94 * a space or tab. All fields must be present in each entry.
96 * service name must be in /etc/services or must
97 * name a tcpmux service
98 * socket type[:accf[,arg]] stream/dgram/raw/rdm/seqpacket,
99 only stream can name an accept filter
100 * protocol must be in /etc/protocols
101 * wait/nowait[:max] single-threaded/multi-threaded, max #
102 * user[:group] user/group to run daemon as
103 * server program full path name
104 * server program arguments maximum of MAXARGS (20)
107 * service name/version must be in /etc/rpc
108 * socket type stream/dgram/raw/rdm/seqpacket
109 * protocol must be in /etc/protocols
110 * wait/nowait[:max] single-threaded/multi-threaded
111 * user[:group] user to run daemon as
112 * server program full path name
113 * server program arguments maximum of MAXARGS (20)
115 * For non-RPC services, the "service name" can be of the form
116 * hostaddress:servicename, in which case the hostaddress is used
117 * as the host portion of the address to listen on. If hostaddress
118 * consists of a single `*' character, INADDR_ANY is used.
120 * A line can also consist of just
122 * where hostaddress is as in the preceding paragraph. Such a line must
123 * have no further fields; the specified hostaddress is remembered and
124 * used for all further lines that have no hostaddress specified,
125 * until the next such line (or EOF). (This is why * is provided to
126 * allow explicit specification of INADDR_ANY.) A line
128 * is implicitly in effect at the beginning of the file.
130 * The hostaddress specifier may (and often will) contain dots;
131 * the service name must not.
133 * For RPC services, host-address specifiers are accepted and will
134 * work to some extent; however, because of limitations in the
135 * portmapper interface, it will not work to try to give more than
136 * one line for any given RPC service, even if the host-address
137 * specifiers are different.
139 * TCP services without official port numbers are handled with the
140 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
141 * requests. When a connection is made from a foreign host, the service
142 * requested is passed to tcpmux, which looks it up in the servtab list
143 * and returns the proper entry for the service. Tcpmux returns a
144 * negative reply if the service doesn't exist, otherwise the invoked
145 * server is expected to return the positive reply if the service type in
146 * inetd.conf file has the prefix "tcpmux/". If the service type has the
147 * prefix "tcpmux/+", tcpmux will return the positive reply for the
148 * process; this is for compatibility with older server code, and also
149 * allows you to invoke programs that use stdin/stdout without putting any
150 * special server code in them. Services that use tcpmux are "nowait"
151 * because they do not have a well-known port and hence cannot listen
154 * Comment lines are indicated by a `#' in column 1.
157 * Comment lines that start with "#@" denote IPsec policy string, as described
158 * in ipsec_set_policy(3). This will affect all the following items in
159 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
160 * there's no IPsec policy.
165 * Here's the scoop concerning the user:group feature:
167 * 1) set-group-option off.
169 * a) user = root: NO setuid() or setgid() is done
172 * setgid(primary group as found in passwd)
173 * initgroups(name, primary group)
175 * 2) set-group-option on.
177 * a) user = root: NO setuid()
178 * setgid(specified group)
182 * setgid(specified group)
183 * initgroups(name, specified group)
187 #include <sys/param.h>
188 #include <sys/stat.h>
189 #include <sys/ioctl.h>
190 #include <sys/socket.h>
192 #include <sys/wait.h>
193 #include <sys/time.h>
194 #include <sys/resource.h>
195 #include <sys/event.h>
203 #include <netinet/in.h>
204 #include <arpa/inet.h>
207 #include <rpc/rpcb_clnt.h>
208 #include <netconfig.h>
226 #include "pathnames.h"
229 #include <netipsec/ipsec.h>
230 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
238 #ifndef LIBWRAP_ALLOW_FACILITY
239 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
241 #ifndef LIBWRAP_ALLOW_SEVERITY
242 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
244 #ifndef LIBWRAP_DENY_FACILITY
245 # define LIBWRAP_DENY_FACILITY LOG_AUTH
247 #ifndef LIBWRAP_DENY_SEVERITY
248 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
250 int allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
251 int deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
254 #define TOOMANY 40 /* don't start more than TOOMANY */
255 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
256 #define RETRYTIME (60*10) /* retry after bind or server fail */
258 #define A_CNT(a) (sizeof (a) / sizeof (a[0]))
269 sigset_t sig_mask
, old_mask
;
273 const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
279 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
280 #define FD_MARGIN (8)
281 rlim_t rlim_ofile_cur
= OPEN_MAX
;
283 struct rlimit rlim_ofile
;
285 struct kevent changebuf
[64];
289 char *se_hostaddr
; /* host address to listen on */
290 char *se_service
; /* name of service */
291 int se_socktype
; /* type of socket to use */
292 int se_family
; /* address family */
293 char *se_proto
; /* protocol used */
294 int se_sndbuf
; /* sndbuf size */
295 int se_rcvbuf
; /* rcvbuf size */
296 int se_rpcprog
; /* rpc program number */
297 int se_rpcversl
; /* rpc program lowest version */
298 int se_rpcversh
; /* rpc program highest version */
299 #define isrpcservice(sep) ((sep)->se_rpcversl != 0)
300 pid_t se_wait
; /* single threaded server */
301 short se_checked
; /* looked at during merge */
302 char *se_user
; /* user name to run as */
303 char *se_group
; /* group name to run as */
304 struct biltin
*se_bi
; /* if built-in, description */
305 char *se_server
; /* server program */
307 char *se_argv
[MAXARGV
+1]; /* program arguments */
309 char *se_policy
; /* IPsec poilcy string */
311 struct accept_filter_arg se_accf
; /* accept filter for stream service */
312 int se_fd
; /* open descriptor */
313 int se_type
; /* type */
315 struct sockaddr se_un_ctrladdr
;
316 struct sockaddr_in se_un_ctrladdr_in
;
317 struct sockaddr_in6 se_un_ctrladdr_in6
;
318 struct sockaddr_un se_un_ctrladdr_un
;
319 } se_un
; /* bound address */
320 #define se_ctrladdr se_un.se_un_ctrladdr
321 #define se_ctrladdr_in se_un.se_un_ctrladdr_in
322 #define se_ctrladdr_un se_un.se_un_ctrladdr_un
323 int se_ctrladdr_size
;
324 int se_max
; /* max # of instances of this service */
325 int se_count
; /* number started since se_time */
326 struct timeval se_time
; /* start of se_count */
327 struct servtab
*se_next
;
332 #define MUXPLUS_TYPE 2
334 #define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \
335 ((sep)->se_type == MUXPLUS_TYPE))
336 #define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE)
339 static void chargen_dg(int, struct servtab
*);
340 static void chargen_stream(int, struct servtab
*);
341 static void close_sep(struct servtab
*);
342 static void config(void);
343 static void daytime_dg(int, struct servtab
*);
344 static void daytime_stream(int, struct servtab
*);
345 static void discard_dg(int, struct servtab
*);
346 static void discard_stream(int, struct servtab
*);
347 static void echo_dg(int, struct servtab
*);
348 static void echo_stream(int, struct servtab
*);
349 static void endconfig(void);
350 static struct servtab
*enter(struct servtab
*);
351 static void freeconfig(struct servtab
*);
352 static struct servtab
*getconfigent(void);
353 __dead
static void goaway(void);
354 static void machtime_dg(int, struct servtab
*);
355 static void machtime_stream(int, struct servtab
*);
356 static char *newstr(const char *);
357 static char *nextline(FILE *);
358 static void print_service(const char *, struct servtab
*);
359 static void reapchild(void);
360 static void retry(void);
361 static void run_service(int, struct servtab
*, int);
362 static int setconfig(void);
363 static void setup(struct servtab
*);
364 static char *sskip(char **);
365 static char *skip(char **);
366 static void tcpmux(int, struct servtab
*);
367 __dead
static void usage(void);
368 static void register_rpc(struct servtab
*);
369 static void unregister_rpc(struct servtab
*);
370 static void bump_nofile(void);
371 static void inetd_setproctitle(char *, int);
372 static void initring(void);
373 static uint32_t machtime(void);
374 static int port_good_dg(struct sockaddr
*);
375 static int dg_broadcast(struct in_addr
*);
377 static int my_kevent(const struct kevent
*, size_t, struct kevent
*,
379 static struct kevent
* allocchange(void);
380 #endif /* !__minix */
381 static int get_line(int, char *, int);
382 static void spawn(struct servtab
*, int);
385 const char *bi_service
; /* internally provided service name */
386 int bi_socktype
; /* type of socket supported */
387 short bi_fork
; /* 1 if should fork before call */
388 short bi_wait
; /* 1 if should wait for child */
389 void (*bi_fn
)(int, struct servtab
*);
390 /* function which performs it */
392 /* Echo received data */
393 { "echo", SOCK_STREAM
, 1, 0, echo_stream
},
394 { "echo", SOCK_DGRAM
, 0, 0, echo_dg
},
396 /* Internet /dev/null */
397 { "discard", SOCK_STREAM
, 1, 0, discard_stream
},
398 { "discard", SOCK_DGRAM
, 0, 0, discard_dg
},
400 /* Return 32 bit time since 1970 */
401 { "time", SOCK_STREAM
, 0, 0, machtime_stream
},
402 { "time", SOCK_DGRAM
, 0, 0, machtime_dg
},
404 /* Return human-readable time */
405 { "daytime", SOCK_STREAM
, 0, 0, daytime_stream
},
406 { "daytime", SOCK_DGRAM
, 0, 0, daytime_dg
},
408 /* Familiar character generator */
409 { "chargen", SOCK_STREAM
, 1, 0, chargen_stream
},
410 { "chargen", SOCK_DGRAM
, 0, 0, chargen_dg
},
412 { "tcpmux", SOCK_STREAM
, 1, 0, tcpmux
},
414 { NULL
, 0, 0, 0, NULL
}
417 /* list of "bad" ports. I.e. ports that are most obviously used for
418 * "cycling packets" denial of service attacks. See /etc/services.
419 * List must end with port number "0".
422 u_int16_t bad_ports
[] = { 7, 9, 13, 19, 37, 0 };
425 #define NUMINT (sizeof(intab) / sizeof(struct inent))
426 const char *CONFIG
= _PATH_INETDCONF
;
428 static int my_signals
[] =
429 { SIGALRM
, SIGHUP
, SIGCHLD
, SIGTERM
, SIGINT
, SIGPIPE
};
433 * NetBSD uses kqueue to catch signals, while (explicitly) ignoring them at the
434 * process level. We (MINIX3) do catch the signals at the process level,
435 * instead sending them into select() using a pipe (djb's self-pipe trick).
436 * That is safe, except it may interrupt system calls other than our select(),
437 * so we also have to set appropriate signal masks (clearing them upon fork).
443 (void) write(sig_pipe
[1], &sig
, sizeof(sig
));
448 main(int argc
, char *argv
[])
450 int ch
, n
, reload
= 1;
452 while ((ch
= getopt(argc
, argv
,
481 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
487 syslog(LOG_ERR
, "kqueue: %m");
488 return (EXIT_FAILURE
);
491 if (pipe2(sig_pipe
, O_CLOEXEC
| O_NONBLOCK
) != 0) {
492 syslog(LOG_ERR
, "pipe2: %m");
493 return (EXIT_FAILURE
);
496 /* Block all signals until the first select() call.. just easier. */
497 sigfillset(&sig_mask
);
498 (void) sigprocmask(SIG_SETMASK
, &sig_mask
, &old_mask
);
502 if (getrlimit(RLIMIT_NOFILE
, &rlim_ofile
) < 0) {
503 syslog(LOG_ERR
, "getrlimit: %m");
505 rlim_ofile_cur
= rlim_ofile
.rlim_cur
;
506 if (rlim_ofile_cur
== RLIM_INFINITY
) /* ! */
507 rlim_ofile_cur
= OPEN_MAX
;
510 for (n
= 0; n
< (int)A_CNT(my_signals
); n
++) {
513 signum
= my_signals
[n
];
515 if (signum
!= SIGCHLD
)
516 (void) signal(signum
, SIG_IGN
);
518 if (signum
!= SIGPIPE
) {
522 EV_SET(ev
, signum
, EVFILT_SIGNAL
, EV_ADD
| EV_ENABLE
,
526 /* The above code ignores but does not "catch" SIGPIPE. */
527 if (signum
!= SIGPIPE
)
528 (void) signal(signum
, got_signal
);
530 (void) signal(signum
, SIG_IGN
);
531 sigaddset(&sig_mask
, signum
);
538 struct kevent eventbuf
[64], *ev
;
542 #endif /* !__minix */
552 FD_SET(sig_pipe
[0], &fds
);
553 highfd
= sig_pipe
[0];
555 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
556 if (sep
->se_fd
!= -1 && (unsigned)sep
->se_wait
<= 1) {
557 FD_SET(sep
->se_fd
, &fds
);
558 if (highfd
< sep
->se_fd
)
563 * Unblock all the signals we want to catch for the duration of
564 * the select() call. We do not yet have pselect(), but the
565 * lack of atomicity does not affect correctness here, because
566 * all the signals go through the pipe anyway--that is also why
567 * we reissue the select() even if we did catch a signal.
569 (void) sigprocmask(SIG_SETMASK
, &old_mask
, NULL
);
571 while (select(highfd
+ 1, &fds
, NULL
, NULL
, NULL
) == -1 &&
574 (void) sigprocmask(SIG_SETMASK
, &sig_mask
, NULL
);
576 if (FD_ISSET(sig_pipe
[0], &fds
)) {
577 while (read(sig_pipe
[0], &sig
, sizeof(sig
)) != -1) {
580 n
= my_kevent(changebuf
, changes
, eventbuf
, A_CNT(eventbuf
));
583 for (ev
= eventbuf
; n
> 0; ev
++, n
--) {
584 if (ev
->filter
== EVFILT_SIGNAL
) {
586 #endif /* !__minix */
606 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
607 if (sep
->se_fd
== -1 || (unsigned)sep
->se_wait
> 1 ||
608 !FD_ISSET(sep
->se_fd
, &fds
))
611 if (ev
->filter
!= EVFILT_READ
)
613 sep
= (struct servtab
*)ev
->udata
;
615 if ((int)ev
->ident
!= sep
->se_fd
)
617 #endif /* !__minix */
619 fprintf(stderr
, "someone wants %s\n",
621 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
) {
622 /* XXX here do the libwrap check-before-accept*/
623 ctrl
= accept(sep
->se_fd
, NULL
, NULL
);
625 fprintf(stderr
, "accept, ctrl %d\n",
630 "accept (for %s): %m",
642 spawn(struct servtab
*sep
, int ctrl
)
648 #ifdef LIBWRAP_INTERNAL
651 dofork
= (sep
->se_bi
== 0 || sep
->se_bi
->bi_fork
);
654 if (sep
->se_count
++ == 0)
655 (void)gettimeofday(&sep
->se_time
, NULL
);
656 else if (sep
->se_count
>= sep
->se_max
) {
659 (void)gettimeofday(&now
, NULL
);
660 if (now
.tv_sec
- sep
->se_time
.tv_sec
> CNT_INTVL
) {
665 "%s/%s max spawn rate (%d in %d seconds) "
666 "exceeded; service not started",
667 sep
->se_service
, sep
->se_proto
,
668 sep
->se_max
, CNT_INTVL
);
669 if (!sep
->se_wait
&& sep
->se_socktype
==
682 syslog(LOG_ERR
, "fork: %m");
683 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
)
688 if (pid
!= 0 && sep
->se_wait
) {
694 EV_SET(ev
, sep
->se_fd
, EVFILT_READ
,
696 #endif /* !__minix */
701 for (n
= 0; n
< A_CNT(my_signals
); n
++)
702 (void) signal(my_signals
[n
], SIG_DFL
);
707 (void) sigprocmask(SIG_SETMASK
, &old_mask
, NULL
);
714 run_service(ctrl
, sep
, dofork
);
718 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
)
723 run_service(int ctrl
, struct servtab
*sep
, int didfork
)
726 struct group
*grp
= NULL
; /* XXX gcc */
727 char buf
[NI_MAXSERV
];
731 struct request_info req
;
733 char *service
= NULL
; /* XXX gcc */
737 #ifndef LIBWRAP_INTERNAL
740 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
) {
741 request_init(&req
, RQ_DAEMON
, sep
->se_argv
[0] ?
742 sep
->se_argv
[0] : sep
->se_service
, RQ_FILE
, ctrl
, NULL
);
744 denied
= !hosts_access(&req
);
745 if (denied
|| lflag
) {
746 if (getnameinfo(&sep
->se_ctrladdr
,
747 (socklen_t
)sep
->se_ctrladdr
.sa_len
, NULL
, 0,
748 buf
, sizeof(buf
), 0) != 0) {
749 /* shouldn't happen */
750 (void)snprintf(buf
, sizeof buf
, "%d",
751 ntohs(sep
->se_ctrladdr_in
.sin_port
));
754 if (req
.client
->sin
) {
755 sockaddr_snprintf(abuf
, sizeof(abuf
), "%a",
758 strcpy(abuf
, "(null)");
762 syslog(deny_severity
,
763 "refused connection from %.500s(%s), service %s (%s)",
764 eval_client(&req
), abuf
, service
, sep
->se_proto
);
768 syslog(allow_severity
,
769 "connection from %.500s(%s), service %s (%s)",
770 eval_client(&req
), abuf
, service
, sep
->se_proto
);
777 for (s
= servtab
; s
; s
= s
->se_next
)
778 if (s
->se_fd
!= -1 && s
->se_fd
!= ctrl
) {
783 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
785 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
786 syslog(LOG_ERR
, "%s/%s: %s: No such user",
787 sep
->se_service
, sep
->se_proto
, sep
->se_user
);
791 (grp
= getgrnam(sep
->se_group
)) == NULL
) {
792 syslog(LOG_ERR
, "%s/%s: %s: No such group",
793 sep
->se_service
, sep
->se_proto
, sep
->se_group
);
798 pwd
->pw_gid
= grp
->gr_gid
;
799 if (setgid(pwd
->pw_gid
) < 0) {
801 "%s/%s: can't set gid %d: %m", sep
->se_service
,
802 sep
->se_proto
, pwd
->pw_gid
);
805 (void) initgroups(pwd
->pw_name
,
807 if (setuid(pwd
->pw_uid
) < 0) {
809 "%s/%s: can't set uid %d: %m", sep
->se_service
,
810 sep
->se_proto
, pwd
->pw_uid
);
813 } else if (sep
->se_group
) {
814 (void) setgid((gid_t
)grp
->gr_gid
);
817 fprintf(stderr
, "%d execl %s\n",
818 getpid(), sep
->se_server
);
819 /* Set our control descriptor to not close-on-exec... */
820 if (fcntl(ctrl
, F_SETFD
, 0) < 0)
821 syslog(LOG_ERR
, "fcntl (%d, F_SETFD, 0): %m", ctrl
);
822 /* ...and dup it to stdin, stdout, and stderr. */
830 if (rlim_ofile
.rlim_cur
!= rlim_ofile_cur
&&
831 setrlimit(RLIMIT_NOFILE
, &rlim_ofile
) < 0)
832 syslog(LOG_ERR
, "setrlimit: %m");
833 execv(sep
->se_server
, sep
->se_argv
);
834 syslog(LOG_ERR
, "cannot execute %s: %m", sep
->se_server
);
836 if (sep
->se_socktype
!= SOCK_STREAM
)
837 recv(ctrl
, buf
, sizeof (buf
), 0);
850 pid
= wait3(&status
, WNOHANG
, NULL
);
854 (void) fprintf(stderr
, "%d reaped, status %#x\n",
856 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
857 if (sep
->se_wait
== pid
) {
860 #endif /* !__minix */
862 if (WIFEXITED(status
) && WEXITSTATUS(status
))
864 "%s: exit status %u",
865 sep
->se_server
, WEXITSTATUS(status
));
866 else if (WIFSIGNALED(status
))
868 "%s: exit signal %u",
869 sep
->se_server
, WTERMSIG(status
));
873 EV_SET(ev
, sep
->se_fd
, EVFILT_READ
,
874 EV_ADD
| EV_ENABLE
, 0, 0, (intptr_t)sep
);
875 #endif /* !__minix */
877 fprintf(stderr
, "restored %s, fd %d\n",
878 sep
->se_service
, sep
->se_fd
);
886 struct servtab
*sep
, *cp
, **sepp
;
890 syslog(LOG_ERR
, "%s: %m", CONFIG
);
893 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
895 while ((cp
= getconfigent()) != NULL
) {
896 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
897 if (strcmp(sep
->se_service
, cp
->se_service
) == 0 &&
898 strcmp(sep
->se_hostaddr
, cp
->se_hostaddr
) == 0 &&
899 strcmp(sep
->se_proto
, cp
->se_proto
) == 0 &&
900 ISMUX(sep
) == ISMUX(cp
))
905 #define SWAP(type, a, b) {type c = a; a = b; b = c;}
908 * sep->se_wait may be holding the pid of a daemon
909 * that we're waiting for. If so, don't overwrite
910 * it unless the config file explicitly says don't
913 if (cp
->se_bi
== 0 &&
914 (sep
->se_wait
== 1 || cp
->se_wait
== 0))
915 sep
->se_wait
= cp
->se_wait
;
916 SWAP(char *, sep
->se_user
, cp
->se_user
);
917 SWAP(char *, sep
->se_group
, cp
->se_group
);
918 SWAP(char *, sep
->se_server
, cp
->se_server
);
919 for (i
= 0; i
< MAXARGV
; i
++)
920 SWAP(char *, sep
->se_argv
[i
], cp
->se_argv
[i
]);
922 SWAP(char *, sep
->se_policy
, cp
->se_policy
);
924 SWAP(int, cp
->se_type
, sep
->se_type
);
925 SWAP(int, cp
->se_max
, sep
->se_max
);
927 if (isrpcservice(sep
))
929 sep
->se_rpcversl
= cp
->se_rpcversl
;
930 sep
->se_rpcversh
= cp
->se_rpcversh
;
933 print_service("REDO", sep
);
937 print_service("ADD ", sep
);
941 switch (sep
->se_family
) {
943 if (sep
->se_fd
!= -1)
945 n
= strlen(sep
->se_service
);
946 if (n
>= sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
947 syslog(LOG_ERR
, "%s: address too long",
952 (void)unlink(sep
->se_service
);
953 strlcpy(sep
->se_ctrladdr_un
.sun_path
,
955 sep
->se_ctrladdr_un
.sun_family
= AF_LOCAL
;
956 sep
->se_ctrladdr_size
= (int)(n
+
957 sizeof(sep
->se_ctrladdr_un
) -
958 sizeof(sep
->se_ctrladdr_un
.sun_path
));
967 struct addrinfo hints
, *res
;
973 /* check if the family is supported */
974 s
= socket(sep
->se_family
, SOCK_DGRAM
, 0);
977 "%s/%s: %s: the address family is not "
978 "supported by the kernel",
979 sep
->se_service
, sep
->se_proto
,
986 memset(&hints
, 0, sizeof(hints
));
987 hints
.ai_family
= sep
->se_family
;
988 hints
.ai_socktype
= sep
->se_socktype
;
989 hints
.ai_flags
= AI_PASSIVE
;
990 if (!strcmp(sep
->se_hostaddr
, "*"))
993 host
= sep
->se_hostaddr
;
994 if (isrpcservice(sep
) || ISMUX(sep
))
997 port
= sep
->se_service
;
998 error
= getaddrinfo(host
, port
, &hints
, &res
);
1000 if (error
== EAI_SERVICE
) {
1001 /* gai_strerror not friendly enough */
1002 syslog(LOG_WARNING
, "%s/%s: "
1004 sep
->se_service
, sep
->se_proto
);
1006 syslog(LOG_ERR
, "%s/%s: %s: %s",
1007 sep
->se_service
, sep
->se_proto
,
1009 gai_strerror(error
));
1011 sep
->se_checked
= 0;
1016 "%s/%s: %s: resolved to multiple addr",
1017 sep
->se_service
, sep
->se_proto
,
1019 sep
->se_checked
= 0;
1023 memcpy(&sep
->se_ctrladdr
, res
->ai_addr
,
1030 sep
->se_ctrladdr_size
= res
->ai_addrlen
;
1033 if (isrpcservice(sep
)) {
1036 sep
->se_rpcprog
= atoi(sep
->se_service
);
1037 if (sep
->se_rpcprog
== 0) {
1038 rp
= getrpcbyname(sep
->se_service
);
1041 "%s/%s: unknown service",
1044 sep
->se_checked
= 0;
1047 sep
->se_rpcprog
= rp
->r_number
;
1049 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1051 if (sep
->se_fd
!= -1)
1056 if (sep
->se_fd
>= 0)
1058 if (sep
->se_fd
== -1 && !ISMUX(sep
))
1066 * Purge anything not looked at above.
1069 while ((sep
= *sepp
) != NULL
) {
1070 if (sep
->se_checked
) {
1071 sepp
= &sep
->se_next
;
1074 *sepp
= sep
->se_next
;
1075 if (sep
->se_fd
>= 0)
1077 if (isrpcservice(sep
))
1078 unregister_rpc(sep
);
1079 if (sep
->se_family
== AF_LOCAL
)
1080 (void)unlink(sep
->se_service
);
1082 print_service("FREE", sep
);
1091 struct servtab
*sep
;
1094 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
1095 if (sep
->se_fd
== -1 && !ISMUX(sep
)) {
1096 switch (sep
->se_family
) {
1103 if (sep
->se_fd
>= 0 && isrpcservice(sep
))
1114 struct servtab
*sep
;
1116 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
1117 if (sep
->se_fd
== -1)
1120 switch (sep
->se_family
) {
1122 (void)unlink(sep
->se_service
);
1128 if (sep
->se_wait
== 1 && isrpcservice(sep
))
1129 unregister_rpc(sep
);
1132 (void)close(sep
->se_fd
);
1139 setup(struct servtab
*sep
)
1147 #endif /* !__minix */
1149 if ((sep
->se_fd
= socket(sep
->se_family
, sep
->se_socktype
, 0)) < 0) {
1151 fprintf(stderr
, "socket failed on %s/%s: %s\n",
1152 sep
->se_service
, sep
->se_proto
, strerror(errno
));
1153 syslog(LOG_ERR
, "%s/%s: socket: %m",
1154 sep
->se_service
, sep
->se_proto
);
1157 /* Set all listening sockets to close-on-exec. */
1158 if (fcntl(sep
->se_fd
, F_SETFD
, FD_CLOEXEC
) < 0) {
1159 syslog(LOG_ERR
, "%s/%s: fcntl(F_SETFD, FD_CLOEXEC): %m",
1160 sep
->se_service
, sep
->se_proto
);
1166 #define turnon(fd, opt) \
1167 setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on))
1168 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1169 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1170 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1171 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1172 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1175 /* Set the socket buffer sizes, if specified. */
1176 if (sep
->se_sndbuf
!= 0 && setsockopt(sep
->se_fd
, SOL_SOCKET
,
1177 SO_SNDBUF
, &sep
->se_sndbuf
, (socklen_t
)sizeof(sep
->se_sndbuf
)) < 0)
1178 syslog(LOG_ERR
, "setsockopt (SO_SNDBUF %d): %m",
1180 if (sep
->se_rcvbuf
!= 0 && setsockopt(sep
->se_fd
, SOL_SOCKET
,
1181 SO_RCVBUF
, &sep
->se_rcvbuf
, (socklen_t
)sizeof(sep
->se_rcvbuf
)) < 0)
1182 syslog(LOG_ERR
, "setsockopt (SO_RCVBUF %d): %m",
1185 if (sep
->se_family
== AF_INET6
) {
1187 v
= (sep
->se_type
== FAITH_TYPE
) ? &on
: &off
;
1188 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_FAITH
,
1189 v
, (socklen_t
)sizeof(*v
)) < 0)
1190 syslog(LOG_ERR
, "setsockopt (IPV6_FAITH): %m");
1194 if (ipsecsetup(sep
->se_family
, sep
->se_fd
, sep
->se_policy
) < 0 &&
1196 syslog(LOG_ERR
, "%s/%s: ipsec setup failed",
1197 sep
->se_service
, sep
->se_proto
);
1198 (void)close(sep
->se_fd
);
1204 if (bind(sep
->se_fd
, &sep
->se_ctrladdr
,
1205 (socklen_t
)sep
->se_ctrladdr_size
) < 0) {
1207 fprintf(stderr
, "bind failed on %s/%s: %s\n",
1208 sep
->se_service
, sep
->se_proto
, strerror(errno
));
1209 syslog(LOG_ERR
, "%s/%s: bind: %m",
1210 sep
->se_service
, sep
->se_proto
);
1211 (void) close(sep
->se_fd
);
1219 if (sep
->se_socktype
== SOCK_STREAM
)
1220 listen(sep
->se_fd
, 10);
1222 /* Set the accept filter, if specified. To be done after listen.*/
1223 if (sep
->se_accf
.af_name
[0] != 0 && setsockopt(sep
->se_fd
, SOL_SOCKET
,
1224 SO_ACCEPTFILTER
, &sep
->se_accf
,
1225 (socklen_t
)sizeof(sep
->se_accf
)) < 0)
1226 syslog(LOG_ERR
, "setsockopt(SO_ACCEPTFILTER %s): %m",
1227 sep
->se_accf
.af_name
);
1231 EV_SET(ev
, sep
->se_fd
, EVFILT_READ
, EV_ADD
| EV_ENABLE
, 0, 0,
1233 #endif /* !__minix */
1234 if (sep
->se_fd
> maxsock
) {
1235 maxsock
= sep
->se_fd
;
1236 if (maxsock
> (int)(rlim_ofile_cur
- FD_MARGIN
))
1240 fprintf(stderr
, "registered %s on %d\n",
1241 sep
->se_server
, sep
->se_fd
);
1245 * Finish with a service and its socket.
1248 close_sep(struct servtab
*sep
)
1250 if (sep
->se_fd
>= 0) {
1251 (void) close(sep
->se_fd
);
1258 register_rpc(struct servtab
*sep
)
1262 struct sockaddr_storage ss
;
1263 struct netconfig
*nconf
;
1267 if ((nconf
= getnetconfigent(sep
->se_proto
+4)) == NULL
) {
1268 syslog(LOG_ERR
, "%s: getnetconfigent failed",
1272 socklen
= sizeof ss
;
1273 if (getsockname(sep
->se_fd
, (struct sockaddr
*)(void *)&ss
, &socklen
) < 0) {
1274 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1275 sep
->se_service
, sep
->se_proto
);
1280 nbuf
.len
= ss
.ss_len
;
1281 nbuf
.maxlen
= sizeof (struct sockaddr_storage
);
1282 for (n
= sep
->se_rpcversl
; n
<= sep
->se_rpcversh
; n
++) {
1284 fprintf(stderr
, "rpcb_set: %u %d %s %s\n",
1285 sep
->se_rpcprog
, n
, nconf
->nc_netid
,
1286 taddr2uaddr(nconf
, &nbuf
));
1287 (void)rpcb_unset((unsigned int)sep
->se_rpcprog
, (unsigned int)n
, nconf
);
1288 if (!rpcb_set((unsigned int)sep
->se_rpcprog
, (unsigned int)n
, nconf
, &nbuf
))
1289 syslog(LOG_ERR
, "rpcb_set: %u %d %s %s%s",
1290 sep
->se_rpcprog
, n
, nconf
->nc_netid
,
1291 taddr2uaddr(nconf
, &nbuf
), clnt_spcreateerror(""));
1297 unregister_rpc(struct servtab
*sep
)
1301 struct netconfig
*nconf
;
1303 if ((nconf
= getnetconfigent(sep
->se_proto
+4)) == NULL
) {
1304 syslog(LOG_ERR
, "%s: getnetconfigent failed",
1309 for (n
= sep
->se_rpcversl
; n
<= sep
->se_rpcversh
; n
++) {
1311 fprintf(stderr
, "rpcb_unset(%u, %d, %s)\n",
1312 sep
->se_rpcprog
, n
, nconf
->nc_netid
);
1313 if (!rpcb_unset((unsigned int)sep
->se_rpcprog
, (unsigned int)n
, nconf
))
1314 syslog(LOG_ERR
, "rpcb_unset(%u, %d, %s) failed\n",
1315 sep
->se_rpcprog
, n
, nconf
->nc_netid
);
1321 static struct servtab
*
1322 enter(struct servtab
*cp
)
1324 struct servtab
*sep
;
1326 sep
= malloc(sizeof (*sep
));
1328 syslog(LOG_ERR
, "Out of memory.");
1333 sep
->se_rpcprog
= -1;
1334 sep
->se_next
= servtab
;
1339 FILE *fconfig
= NULL
;
1340 struct servtab serv
;
1341 char line
[LINE_MAX
];
1344 static char *policy
= NULL
;
1352 defhost
= newstr("*");
1358 if (fconfig
!= NULL
) {
1359 fseek(fconfig
, 0L, SEEK_SET
);
1362 fconfig
= fopen(CONFIG
, "r");
1363 return (fconfig
!= NULL
);
1369 if (fconfig
!= NULL
) {
1370 (void) fclose(fconfig
);
1373 if (defhost
!= NULL
) {
1379 static struct servtab
*
1382 struct servtab
*sep
= &serv
;
1384 char *cp
, *cp0
, *arg
, *buf0
, *buf1
, *sz0
, *sz1
;
1385 static char TCPMUX_TOKEN
[] = "tcpmux/";
1386 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1390 while ((cp
= nextline(fconfig
)) != NULL
) {
1392 /* lines starting with #@ is not a comment, but the policy */
1393 if (cp
[0] == '#' && cp
[1] == '@') {
1395 for (p
= cp
+ 2; p
&& *p
&& isspace((unsigned char)*p
); p
++)
1402 if (ipsecsetup_test(p
) < 0) {
1404 "%s: invalid ipsec policy \"%s\"",
1415 if (*cp
== '#' || *cp
== '\0')
1422 * clear the static buffer, since some fields (se_ctrladdr,
1423 * for example) don't get initialized here.
1425 memset(sep
, 0, sizeof *sep
);
1428 /* got an empty line containing just blanks/tabs. */
1431 /* Check for a host name. */
1432 hostdelim
= strrchr(arg
, ':');
1435 if (arg
[0] == '[' && hostdelim
> arg
&& hostdelim
[-1] == ']') {
1436 hostdelim
[-1] = '\0';
1437 sep
->se_hostaddr
= newstr(arg
+ 1);
1439 sep
->se_hostaddr
= newstr(arg
);
1440 arg
= hostdelim
+ 1;
1442 * If the line is of the form `host:', then just change the
1443 * default host for the following lines.
1449 defhost
= sep
->se_hostaddr
;
1454 sep
->se_hostaddr
= newstr(defhost
);
1455 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1456 char *c
= arg
+ MUX_LEN
;
1458 sep
->se_type
= MUXPLUS_TYPE
;
1461 sep
->se_type
= MUX_TYPE
;
1462 sep
->se_service
= newstr(c
);
1464 sep
->se_service
= newstr(arg
);
1465 sep
->se_type
= NORM_TYPE
;
1469 if (strncmp(arg
, "stream", sizeof("stream") - 1) == 0) {
1470 char *accf
, *accf_arg
;
1472 sep
->se_socktype
= SOCK_STREAM
;
1474 /* one and only one accept filter */
1475 accf
= strchr(arg
, ':');
1477 if (accf
!= strrchr(arg
, ':') ||/* more than one */
1478 *(accf
+ 1) == '\0') { /* nothing beyond */
1479 sep
->se_socktype
= -1;
1481 accf
++; /* skip delimiter */
1482 strlcpy(sep
->se_accf
.af_name
, accf
,
1483 sizeof(sep
->se_accf
.af_name
));
1484 accf_arg
= strchr(accf
, ',');
1485 if (accf_arg
) { /* zero or one arg, no more */
1486 if (strrchr(accf
, ',') != accf_arg
) {
1487 sep
->se_socktype
= -1;
1490 strlcpy(sep
->se_accf
.af_arg
,
1492 sizeof(sep
->se_accf
.af_arg
));
1499 else if (strcmp(arg
, "dgram") == 0)
1500 sep
->se_socktype
= SOCK_DGRAM
;
1501 else if (strcmp(arg
, "rdm") == 0)
1502 sep
->se_socktype
= SOCK_RDM
;
1503 else if (strcmp(arg
, "seqpacket") == 0)
1504 sep
->se_socktype
= SOCK_SEQPACKET
;
1505 else if (strcmp(arg
, "raw") == 0)
1506 sep
->se_socktype
= SOCK_RAW
;
1508 sep
->se_socktype
= -1;
1511 if (sep
->se_type
== NORM_TYPE
&&
1512 strncmp(arg
, "faith/", strlen("faith/")) == 0) {
1513 arg
+= strlen("faith/");
1514 sep
->se_type
= FAITH_TYPE
;
1516 sep
->se_proto
= newstr(arg
);
1518 #define MALFORMED(arg) \
1520 syslog(LOG_ERR, "%s: malformed buffer size option `%s'", \
1521 sep->se_service, (arg)); \
1524 } while (/*CONSTCOND*/0)
1526 #define GETVAL(arg) \
1528 if (!isdigit((unsigned char)*(arg))) \
1530 val = (int)strtol((arg), &cp0, 10); \
1531 if (cp0 != NULL) { \
1532 if (cp0[1] != '\0') \
1534 if (cp0[0] == 'k') \
1536 if (cp0[0] == 'm') \
1537 val *= 1024 * 1024; \
1540 syslog(LOG_ERR, "%s: invalid buffer size `%s'", \
1541 sep->se_service, (arg)); \
1545 } while (/*CONSTCOND*/0)
1547 #define ASSIGN(arg) \
1549 if (strcmp((arg), "sndbuf") == 0) \
1550 sep->se_sndbuf = val; \
1551 else if (strcmp((arg), "rcvbuf") == 0) \
1552 sep->se_rcvbuf = val; \
1555 } while (/*CONSTCOND*/0)
1558 * Extract the send and receive buffer sizes before parsing
1561 sep
->se_sndbuf
= sep
->se_rcvbuf
= 0;
1562 buf0
= buf1
= sz0
= sz1
= NULL
;
1563 if ((buf0
= strchr(sep
->se_proto
, ',')) != NULL
) {
1564 /* Not meaningful for Tcpmux services. */
1566 syslog(LOG_ERR
, "%s: can't specify buffer sizes for "
1567 "tcpmux services", sep
->se_service
);
1574 /* Check to see if another socket buffer size was specified. */
1575 if ((buf1
= strchr(buf0
, ',')) != NULL
) {
1579 /* Make sure a 3rd one wasn't specified. */
1580 if (strchr(buf1
, ',') != NULL
) {
1581 syslog(LOG_ERR
, "%s: too many buffer sizes",
1586 /* Locate the size. */
1587 if ((sz1
= strchr(buf1
, '=')) == NULL
)
1594 /* Locate the size. */
1595 if ((sz0
= strchr(buf0
, '=')) == NULL
)
1614 if (strcmp(sep
->se_proto
, "unix") == 0) {
1615 sep
->se_family
= AF_LOCAL
;
1617 val
= (int)strlen(sep
->se_proto
);
1619 syslog(LOG_ERR
, "%s: invalid protocol specified",
1623 val
= sep
->se_proto
[val
- 1];
1625 case '4': /*tcp4 or udp4*/
1626 sep
->se_family
= AF_INET
;
1629 case '6': /*tcp6 or udp6*/
1630 sep
->se_family
= AF_INET6
;
1634 sep
->se_family
= AF_INET
; /*will become AF_INET6*/
1637 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1640 cp1
= strchr(sep
->se_service
, '/');
1642 syslog(LOG_ERR
, "%s: no rpc version",
1647 sep
->se_rpcversl
= sep
->se_rpcversh
=
1648 (int)strtol(cp1
, &ccp
, 0);
1651 syslog(LOG_ERR
, "%s/%s: bad rpc version",
1652 sep
->se_service
, cp1
);
1657 sep
->se_rpcversh
= (int)strtol(cp1
, &ccp
, 0);
1662 syslog(LOG_ERR
, "%s: rpc services not suported",
1671 if ((cp1
= strchr(arg
, ':')) == NULL
)
1672 cp1
= strchr(arg
, '.');
1675 sep
->se_max
= atoi(cp1
);
1677 sep
->se_max
= TOOMANY
;
1679 sep
->se_wait
= strcmp(arg
, "wait") == 0;
1682 * Silently enforce "nowait" for TCPMUX services since
1683 * they don't have an assigned port to listen on.
1687 if (strncmp(sep
->se_proto
, "tcp", 3)) {
1689 "%s: bad protocol for tcpmux service %s",
1690 CONFIG
, sep
->se_service
);
1693 if (sep
->se_socktype
!= SOCK_STREAM
) {
1695 "%s: bad socket type for tcpmux service %s",
1696 CONFIG
, sep
->se_service
);
1700 sep
->se_user
= newstr(sskip(&cp
));
1701 if ((sep
->se_group
= strchr(sep
->se_user
, ':')) != NULL
)
1702 *sep
->se_group
++ = '\0';
1703 else if ((sep
->se_group
= strchr(sep
->se_user
, '.')) != NULL
)
1704 *sep
->se_group
++ = '\0';
1706 sep
->se_server
= newstr(sskip(&cp
));
1707 if (strcmp(sep
->se_server
, "internal") == 0) {
1710 for (bi
= biltins
; bi
->bi_service
; bi
++)
1711 if (bi
->bi_socktype
== sep
->se_socktype
&&
1712 strcmp(bi
->bi_service
, sep
->se_service
) == 0)
1714 if (bi
->bi_service
== 0) {
1715 syslog(LOG_ERR
, "internal service %s unknown",
1720 sep
->se_wait
= bi
->bi_wait
;
1724 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
)) {
1726 sep
->se_argv
[argc
++] = newstr(arg
);
1728 while (argc
<= MAXARGV
)
1729 sep
->se_argv
[argc
++] = NULL
;
1731 sep
->se_policy
= policy
? newstr(policy
) : NULL
;
1737 freeconfig(struct servtab
*cp
)
1741 if (cp
->se_hostaddr
)
1742 free(cp
->se_hostaddr
);
1744 free(cp
->se_service
);
1749 /* Note: se_group is part of the newstr'ed se_user */
1751 free(cp
->se_server
);
1752 for (i
= 0; i
< MAXARGV
; i
++)
1754 free(cp
->se_argv
[i
]);
1757 free(cp
->se_policy
);
1763 * Safe skip - if skip returns null, log a syntax error in the
1764 * configuration file and exit.
1773 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
1790 while (*cp
== ' ' || *cp
== '\t')
1796 (void) ungetc(c
, fconfig
);
1797 if (c
== ' ' || c
== '\t')
1798 if ((cp
= nextline(fconfig
)) != NULL
)
1805 while (*cp
&& (quote
|| (*cp
!= ' ' && *cp
!= '\t'))) {
1806 if (*cp
== '\'' || *cp
== '"') {
1807 if (quote
&& *cp
!= quote
)
1814 memmove(cp
, cp
+1, strlen(cp
));
1830 if (fgets(line
, (int)sizeof(line
), fd
) == NULL
)
1832 cp
= strchr(line
, '\n');
1839 newstr(const char *cp
)
1842 if ((dp
= strdup((cp
!= NULL
) ? cp
: "")) != NULL
)
1844 syslog(LOG_ERR
, "strdup: %m");
1850 inetd_setproctitle(char *a
, int s
)
1853 struct sockaddr_storage ss
;
1854 char hbuf
[NI_MAXHOST
];
1856 struct sockaddr
*sa
;
1859 sa
= (struct sockaddr
*)(void *)&ss
;
1860 if (getpeername(s
, sa
, &size
) == 0) {
1861 if (getnameinfo(sa
, size
, hbuf
, (socklen_t
)sizeof(hbuf
), NULL
,
1866 setproctitle("-%s [%s]", a
, hp
);
1868 setproctitle("-%s", a
);
1877 if (getrlimit(RLIMIT_NOFILE
, &rl
) < 0) {
1878 syslog(LOG_ERR
, "getrlimit: %m");
1881 rl
.rlim_cur
= MIN(rl
.rlim_max
, rl
.rlim_cur
+ FD_CHUNK
);
1882 if (rl
.rlim_cur
<= rlim_ofile_cur
) {
1884 "bump_nofile: cannot extend file limit, max = %d",
1889 if (setrlimit(RLIMIT_NOFILE
, &rl
) < 0) {
1890 syslog(LOG_ERR
, "setrlimit: %m");
1894 rlim_ofile_cur
= rl
.rlim_cur
;
1899 * Internet services provided internally by inetd:
1901 #define BUFSIZE 4096
1905 echo_stream(int s
, struct servtab
*sep
) /* Echo service -- echo data back */
1907 char buffer
[BUFSIZE
];
1910 inetd_setproctitle(sep
->se_service
, s
);
1911 while ((i
= read(s
, buffer
, sizeof(buffer
))) > 0 &&
1912 write(s
, buffer
, (size_t)i
) > 0)
1918 echo_dg(int s
, struct servtab
*sep
) /* Echo service -- echo data back */
1920 char buffer
[BUFSIZE
];
1923 struct sockaddr_storage ss
;
1924 struct sockaddr
*sa
;
1926 sa
= (struct sockaddr
*)(void *)&ss
;
1928 if ((i
= recvfrom(s
, buffer
, sizeof(buffer
), 0, sa
, &size
)) < 0)
1930 if (port_good_dg(sa
))
1931 (void) sendto(s
, buffer
, (size_t)i
, 0, sa
, size
);
1936 discard_stream(int s
, struct servtab
*sep
) /* Discard service -- ignore data */
1938 char buffer
[BUFSIZE
];
1940 inetd_setproctitle(sep
->se_service
, s
);
1941 while ((errno
= 0, read(s
, buffer
, sizeof(buffer
)) > 0) ||
1948 discard_dg(int s
, struct servtab
*sep
) /* Discard service -- ignore data */
1951 char buffer
[BUFSIZE
];
1953 (void) read(s
, buffer
, sizeof(buffer
));
1967 for (i
= 0; i
<= 128; ++i
)
1974 chargen_stream(int s
,struct servtab
*sep
) /* Character generator */
1977 char *rs
, text
[LINESIZ
+2];
1979 inetd_setproctitle(sep
->se_service
, s
);
1986 text
[LINESIZ
] = '\r';
1987 text
[LINESIZ
+ 1] = '\n';
1989 if ((len
= endring
- rs
) >= LINESIZ
)
1990 memmove(text
, rs
, LINESIZ
);
1992 memmove(text
, rs
, len
);
1993 memmove(text
+ len
, ring
, LINESIZ
- len
);
1995 if (++rs
== endring
)
1997 if (write(s
, text
, sizeof(text
)) != sizeof(text
))
2004 chargen_dg(int s
, struct servtab
*sep
) /* Character generator */
2006 struct sockaddr_storage ss
;
2007 struct sockaddr
*sa
;
2011 char text
[LINESIZ
+2];
2018 sa
= (struct sockaddr
*)(void *)&ss
;
2020 if (recvfrom(s
, text
, sizeof(text
), 0, sa
, &size
) < 0)
2023 if (!port_good_dg(sa
))
2026 if ((len
= endring
- rs
) >= LINESIZ
)
2027 memmove(text
, rs
, LINESIZ
);
2029 memmove(text
, rs
, len
);
2030 memmove(text
+ len
, ring
, LINESIZ
- len
);
2032 if (++rs
== endring
)
2034 text
[LINESIZ
] = '\r';
2035 text
[LINESIZ
+ 1] = '\n';
2036 (void) sendto(s
, text
, sizeof(text
), 0, sa
, size
);
2040 * Return a machine readable date and time, in the form of the
2041 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
2042 * returns the number of seconds since midnight, Jan 1, 1970,
2043 * we must add 2208988800 seconds to this figure to make up for
2044 * some seventy years Bell Labs was asleep.
2052 if (gettimeofday(&tv
, NULL
) < 0) {
2054 fprintf(stderr
, "Unable to get time of day\n");
2057 #define OFFSET ((uint32_t)25567 * 24*60*60)
2058 return (htonl((uint32_t)(tv
.tv_sec
+ OFFSET
)));
2064 machtime_stream(int s
, struct servtab
*sep
)
2068 result
= machtime();
2069 (void) write(s
, &result
, sizeof(result
));
2074 machtime_dg(int s
, struct servtab
*sep
)
2077 struct sockaddr_storage ss
;
2078 struct sockaddr
*sa
;
2081 sa
= (struct sockaddr
*)(void *)&ss
;
2083 if (recvfrom(s
, &result
, sizeof(result
), 0, sa
, &size
) < 0)
2085 if (!port_good_dg(sa
))
2087 result
= machtime();
2088 (void)sendto(s
, &result
, sizeof(result
), 0, sa
, size
);
2093 daytime_stream(int s
,struct servtab
*sep
)
2094 /* Return human-readable time of day */
2100 clk
= time((time_t *) 0);
2102 len
= snprintf(buffer
, sizeof buffer
, "%.24s\r\n", ctime(&clk
));
2103 (void) write(s
, buffer
, len
);
2108 daytime_dg(int s
, struct servtab
*sep
)
2109 /* Return human-readable time of day */
2113 struct sockaddr_storage ss
;
2114 struct sockaddr
*sa
;
2118 clk
= time((time_t *) 0);
2120 sa
= (struct sockaddr
*)(void *)&ss
;
2122 if (recvfrom(s
, buffer
, sizeof(buffer
), 0, sa
, &size
) < 0)
2124 if (!port_good_dg(sa
))
2126 len
= snprintf(buffer
, sizeof buffer
, "%.24s\r\n", ctime(&clk
));
2127 (void) sendto(s
, buffer
, len
, 0, sa
, size
);
2132 * Dump relevant information to stderr
2135 print_service(const char *action
, struct servtab
*sep
)
2138 if (isrpcservice(sep
))
2140 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2145 action
, sep
->se_service
,
2146 sep
->se_rpcprog
, sep
->se_rpcversh
, sep
->se_rpcversl
, sep
->se_proto
,
2147 sep
->se_wait
, sep
->se_max
, sep
->se_user
, sep
->se_group
,
2148 (long)sep
->se_bi
, sep
->se_server
2150 , (sep
->se_policy
? sep
->se_policy
: "")
2155 "%s: %s proto=%s%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2160 action
, sep
->se_service
,
2161 sep
->se_type
== FAITH_TYPE
? "faith/" : "",
2163 sep
->se_wait
, sep
->se_max
, sep
->se_user
, sep
->se_group
,
2164 (long)sep
->se_bi
, sep
->se_server
2166 , (sep
->se_policy
? sep
->se_policy
: "")
2175 (void)fprintf(stderr
, "usage: %s [-dl] [conf]\n", getprogname());
2177 (void)fprintf(stderr
, "usage: %s [-d] [conf]\n", getprogname());
2184 * Based on TCPMUX.C by Mark K. Lottor November 1988
2185 * sri-nic::ps:<mkl>tcpmux.c
2188 static int /* # of characters upto \r,\n or \0 */
2189 get_line(int fd
, char *buf
, int len
)
2195 n
= read(fd
, buf
, len
-count
);
2201 if (*buf
== '\r' || *buf
== '\n' || *buf
== '\0')
2206 } while (count
< len
);
2210 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */
2212 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)
2215 tcpmux(int ctrl
, struct servtab
*sep
)
2217 char service
[MAX_SERV_LEN
+1];
2220 /* Get requested service name */
2221 if ((len
= get_line(ctrl
, service
, MAX_SERV_LEN
)) < 0) {
2222 strwrite(ctrl
, "-Error reading service name\r\n");
2225 service
[len
] = '\0';
2228 fprintf(stderr
, "tcpmux: someone wants %s\n", service
);
2231 * Help is a required command, and lists available services,
2234 if (!strcasecmp(service
, "help")) {
2235 strwrite(ctrl
, "+Available services:\r\n");
2236 strwrite(ctrl
, "help\r\n");
2237 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
2240 (void)write(ctrl
, sep
->se_service
,
2241 strlen(sep
->se_service
));
2242 strwrite(ctrl
, "\r\n");
2247 /* Try matching a service in inetd.conf with the request */
2248 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
2251 if (!strcasecmp(service
, sep
->se_service
)) {
2253 strwrite(ctrl
, "+Go\r\n");
2254 run_service(ctrl
, sep
, 1 /* forked */);
2258 strwrite(ctrl
, "-Service not available\r\n");
2264 * check if the address/port where send data to is one of the obvious ports
2265 * that are used for denial of service attacks like two echo ports
2266 * just echoing data between them
2269 port_good_dg(struct sockaddr
*sa
)
2272 struct sockaddr_in
*sin
;
2274 struct in6_addr
*in6
;
2275 struct sockaddr_in6
*sin6
;
2279 char hbuf
[NI_MAXHOST
];
2281 switch (sa
->sa_family
) {
2283 sin
= (struct sockaddr_in
*)(void *)sa
;
2284 in
.s_addr
= ntohl(sin
->sin_addr
.s_addr
);
2285 port
= ntohs(sin
->sin_port
);
2289 if (IN_MULTICAST(in
.s_addr
))
2291 switch ((in
.s_addr
& 0xff000000) >> 24) {
2292 case 0: case 127: case 255:
2295 if (dg_broadcast(&in
))
2300 sin6
= (struct sockaddr_in6
*)(void *)sa
;
2301 in6
= &sin6
->sin6_addr
;
2302 port
= ntohs(sin6
->sin6_port
);
2303 if (IN6_IS_ADDR_MULTICAST(in6
) || IN6_IS_ADDR_UNSPECIFIED(in6
))
2305 if (IN6_IS_ADDR_V4MAPPED(in6
) || IN6_IS_ADDR_V4COMPAT(in6
)) {
2306 memcpy(&in
, &in6
->s6_addr
[12], sizeof(in
));
2307 in
.s_addr
= ntohl(in
.s_addr
);
2313 /* XXX unsupported af, is it safe to assume it to be safe? */
2317 for (i
= 0; bad_ports
[i
] != 0; i
++) {
2318 if (port
== bad_ports
[i
])
2325 if (getnameinfo(sa
, sa
->sa_len
, hbuf
, (socklen_t
)sizeof(hbuf
), NULL
, 0,
2327 strlcpy(hbuf
, "?", sizeof(hbuf
));
2328 syslog(LOG_WARNING
,"Possible DoS attack from %s, Port %d",
2333 /* XXX need optimization */
2335 dg_broadcast(struct in_addr
*in
)
2337 struct ifaddrs
*ifa
, *ifap
;
2338 struct sockaddr_in
*sin
;
2340 if (getifaddrs(&ifap
) < 0)
2342 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
2343 if (ifa
->ifa_addr
->sa_family
!= AF_INET
||
2344 (ifa
->ifa_flags
& IFF_BROADCAST
) == 0)
2346 sin
= (struct sockaddr_in
*)(void *)ifa
->ifa_broadaddr
;
2347 if (sin
->sin_addr
.s_addr
== in
->s_addr
) {
2358 my_kevent(const struct kevent
*changelist
, size_t nchanges
,
2359 struct kevent
*eventlist
, size_t nevents
)
2363 while ((result
= kevent(kq
, changelist
, nchanges
, eventlist
, nevents
,
2365 if (errno
!= EINTR
) {
2366 syslog(LOG_ERR
, "kevent: %m");
2373 static struct kevent
*
2376 if (changes
== A_CNT(changebuf
)) {
2377 (void) my_kevent(changebuf
, A_CNT(changebuf
), NULL
, 0);
2381 return (&changebuf
[changes
++]);
2383 #endif /* !__minix */