1 /* $NetBSD: inetd.c,v 1.113 2009/07/13 19:05:41 roy 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.113 2009/07/13 19:05:41 roy 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>
197 #ifndef RLIMIT_NOFILE
198 #define RLIMIT_NOFILE RLIMIT_OFILE
207 #include <netinet/in.h>
208 #include <arpa/inet.h>
211 #include <rpc/rpcb_clnt.h>
212 #include <netconfig.h>
230 #include "pathnames.h"
233 #include <netinet6/ipsec.h>
234 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
242 #ifndef LIBWRAP_ALLOW_FACILITY
243 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
245 #ifndef LIBWRAP_ALLOW_SEVERITY
246 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
248 #ifndef LIBWRAP_DENY_FACILITY
249 # define LIBWRAP_DENY_FACILITY LOG_AUTH
251 #ifndef LIBWRAP_DENY_SEVERITY
252 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
254 int allow_severity
= LIBWRAP_ALLOW_FACILITY
|LIBWRAP_ALLOW_SEVERITY
;
255 int deny_severity
= LIBWRAP_DENY_FACILITY
|LIBWRAP_DENY_SEVERITY
;
258 #define TOOMANY 40 /* don't start more than TOOMANY */
259 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
260 #define RETRYTIME (60*10) /* retry after bind or server fail */
262 #define A_CNT(a) (sizeof (a) / sizeof (a[0]))
272 const int niflags
= NI_NUMERICHOST
| NI_NUMERICSERV
;
278 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
279 #define FD_MARGIN (8)
280 rlim_t rlim_ofile_cur
= OPEN_MAX
;
283 struct rlimit rlim_ofile
;
286 struct kevent changebuf
[64];
290 char *se_hostaddr
; /* host address to listen on */
291 char *se_service
; /* name of service */
292 int se_socktype
; /* type of socket to use */
293 int se_family
; /* address family */
294 char *se_proto
; /* protocol used */
295 int se_sndbuf
; /* sndbuf size */
296 int se_rcvbuf
; /* rcvbuf size */
297 int se_rpcprog
; /* rpc program number */
298 int se_rpcversl
; /* rpc program lowest version */
299 int se_rpcversh
; /* rpc program highest version */
300 #define isrpcservice(sep) ((sep)->se_rpcversl != 0)
301 pid_t se_wait
; /* single threaded server */
302 short se_checked
; /* looked at during merge */
303 char *se_user
; /* user name to run as */
304 char *se_group
; /* group name to run as */
305 struct biltin
*se_bi
; /* if built-in, description */
306 char *se_server
; /* server program */
308 char *se_argv
[MAXARGV
+1]; /* program arguments */
310 char *se_policy
; /* IPsec poilcy string */
312 struct accept_filter_arg se_accf
; /* accept filter for stream service */
313 int se_fd
; /* open descriptor */
314 int se_type
; /* type */
316 struct sockaddr se_un_ctrladdr
;
317 struct sockaddr_in se_un_ctrladdr_in
;
318 struct sockaddr_in6 se_un_ctrladdr_in6
;
319 struct sockaddr_un se_un_ctrladdr_un
;
320 } se_un
; /* bound address */
321 #define se_ctrladdr se_un.se_un_ctrladdr
322 #define se_ctrladdr_in se_un.se_un_ctrladdr_in
323 #define se_ctrladdr_un se_un.se_un_ctrladdr_un
324 int se_ctrladdr_size
;
325 int se_max
; /* max # of instances of this service */
326 int se_count
; /* number started since se_time */
327 struct timeval se_time
; /* start of se_count */
330 #define MULOG_RFC931 0x40000000
332 struct servtab
*se_next
;
337 #define MUXPLUS_TYPE 2
339 #define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \
340 ((sep)->se_type == MUXPLUS_TYPE))
341 #define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE)
344 static void chargen_dg(int, struct servtab
*);
345 static void chargen_stream(int, struct servtab
*);
346 static void close_sep(struct servtab
*);
347 static void config(void);
348 static void daytime_dg(int, struct servtab
*);
349 static void daytime_stream(int, struct servtab
*);
350 static void discard_dg(int, struct servtab
*);
351 static void discard_stream(int, struct servtab
*);
352 static void echo_dg(int, struct servtab
*);
353 static void echo_stream(int, struct servtab
*);
354 static void endconfig(void);
355 static struct servtab
*enter(struct servtab
*);
356 static void freeconfig(struct servtab
*);
357 static struct servtab
*getconfigent(void);
358 static void goaway(void);
359 static void machtime_dg(int, struct servtab
*);
360 static void machtime_stream(int, struct servtab
*);
361 static char *newstr(const char *);
362 static char *nextline(FILE *);
363 static void print_service(const char *, struct servtab
*);
364 static void reapchild(void);
365 static void retry(void);
366 static void run_service(int, struct servtab
*, int);
367 static int setconfig(void);
368 static void setup(struct servtab
*);
369 static char *sskip(char **);
370 static char *skip(char **);
371 static void tcpmux(int, struct servtab
*);
372 static void usage(void);
373 static void register_rpc(struct servtab
*);
374 static void unregister_rpc(struct servtab
*);
375 static void bump_nofile(void);
376 static void inetd_setproctitle(char *, int);
377 static void initring(void);
378 static uint32_t machtime(void);
379 static int port_good_dg(struct sockaddr
*);
380 static int dg_broadcast(struct in_addr
*);
381 static int my_kevent(const struct kevent
*, size_t, struct kevent
*,
383 static struct kevent
* allocchange(void);
384 static int get_line(int, char *, int);
385 static void spawn(struct servtab
*, int);
387 static void dolog(struct servtab
*, int);
388 static void timeout(int);
389 static char *rfc931_name(struct sockaddr
*, int);
393 const char *bi_service
; /* internally provided service name */
394 int bi_socktype
; /* type of socket supported */
395 short bi_fork
; /* 1 if should fork before call */
396 short bi_wait
; /* 1 if should wait for child */
397 void (*bi_fn
)(int, struct servtab
*);
398 /* function which performs it */
400 /* Echo received data */
401 { "echo", SOCK_STREAM
, 1, 0, echo_stream
},
402 { "echo", SOCK_DGRAM
, 0, 0, echo_dg
},
404 /* Internet /dev/null */
405 { "discard", SOCK_STREAM
, 1, 0, discard_stream
},
406 { "discard", SOCK_DGRAM
, 0, 0, discard_dg
},
408 /* Return 32 bit time since 1970 */
409 { "time", SOCK_STREAM
, 0, 0, machtime_stream
},
410 { "time", SOCK_DGRAM
, 0, 0, machtime_dg
},
412 /* Return human-readable time */
413 { "daytime", SOCK_STREAM
, 0, 0, daytime_stream
},
414 { "daytime", SOCK_DGRAM
, 0, 0, daytime_dg
},
416 /* Familiar character generator */
417 { "chargen", SOCK_STREAM
, 1, 0, chargen_stream
},
418 { "chargen", SOCK_DGRAM
, 0, 0, chargen_dg
},
420 { "tcpmux", SOCK_STREAM
, 1, 0, tcpmux
},
422 { NULL
, 0, 0, 0, NULL
}
425 /* list of "bad" ports. I.e. ports that are most obviously used for
426 * "cycling packets" denial of service attacks. See /etc/services.
427 * List must end with port number "0".
430 u_int16_t bad_ports
[] = { 7, 9, 13, 19, 37, 0 };
433 #define NUMINT (sizeof(intab) / sizeof(struct inent))
434 const char *CONFIG
= _PATH_INETDCONF
;
436 static int my_signals
[] =
437 { SIGALRM
, SIGHUP
, SIGCHLD
, SIGTERM
, SIGINT
, SIGPIPE
};
440 main(int argc
, char *argv
[])
442 int ch
, n
, reload
= 1;
444 while ((ch
= getopt(argc
, argv
,
473 openlog("inetd", LOG_PID
| LOG_NOWAIT
, LOG_DAEMON
);
478 syslog(LOG_ERR
, "kqueue: %m");
479 return (EXIT_FAILURE
);
483 if (getrlimit(RLIMIT_NOFILE
, &rlim_ofile
) < 0) {
484 syslog(LOG_ERR
, "getrlimit: %m");
486 rlim_ofile_cur
= rlim_ofile
.rlim_cur
;
487 if (rlim_ofile_cur
== RLIM_INFINITY
) /* ! */
488 rlim_ofile_cur
= OPEN_MAX
;
492 for (n
= 0; n
< (int)A_CNT(my_signals
); n
++) {
495 signum
= my_signals
[n
];
496 if (signum
!= SIGCHLD
)
497 (void) signal(signum
, SIG_IGN
);
499 if (signum
!= SIGPIPE
) {
503 EV_SET(ev
, signum
, EVFILT_SIGNAL
, EV_ADD
| EV_ENABLE
,
510 struct kevent eventbuf
[64], *ev
;
518 n
= my_kevent(changebuf
, changes
, eventbuf
, A_CNT(eventbuf
));
521 for (ev
= eventbuf
; n
> 0; ev
++, n
--) {
522 if (ev
->filter
== EVFILT_SIGNAL
) {
540 if (ev
->filter
!= EVFILT_READ
)
542 sep
= (struct servtab
*)ev
->udata
;
544 if ((int)ev
->ident
!= sep
->se_fd
)
547 fprintf(stderr
, "someone wants %s\n",
549 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
) {
550 /* XXX here do the libwrap check-before-accept*/
551 ctrl
= accept(sep
->se_fd
, NULL
, NULL
);
553 fprintf(stderr
, "accept, ctrl %d\n",
558 "accept (for %s): %m",
570 spawn(struct servtab
*sep
, int ctrl
)
576 #ifdef LIBWRAP_INTERNAL
579 dofork
= (sep
->se_bi
== 0 || sep
->se_bi
->bi_fork
);
582 if (sep
->se_count
++ == 0)
583 (void)gettimeofday(&sep
->se_time
, NULL
);
584 else if (sep
->se_count
>= sep
->se_max
) {
587 (void)gettimeofday(&now
, NULL
);
588 if (now
.tv_sec
- sep
->se_time
.tv_sec
> CNT_INTVL
) {
593 "%s/%s max spawn rate (%d in %d seconds) "
594 "exceeded; service not started",
595 sep
->se_service
, sep
->se_proto
,
596 sep
->se_max
, CNT_INTVL
);
597 if (!sep
->se_wait
&& sep
->se_socktype
==
610 syslog(LOG_ERR
, "fork: %m");
611 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
)
616 if (pid
!= 0 && sep
->se_wait
) {
621 EV_SET(ev
, sep
->se_fd
, EVFILT_READ
,
627 for (n
= 0; n
< A_CNT(my_signals
); n
++)
628 (void) signal(my_signals
[n
], SIG_DFL
);
634 run_service(ctrl
, sep
, dofork
);
638 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
)
643 run_service(int ctrl
, struct servtab
*sep
, int didfork
)
646 struct group
*grp
= NULL
; /* XXX gcc */
647 char buf
[NI_MAXSERV
];
651 struct request_info req
;
653 char *service
= NULL
; /* XXX gcc */
657 #ifndef LIBWRAP_INTERNAL
660 if (!sep
->se_wait
&& sep
->se_socktype
== SOCK_STREAM
) {
661 request_init(&req
, RQ_DAEMON
, sep
->se_argv
[0] ?
662 sep
->se_argv
[0] : sep
->se_service
, RQ_FILE
, ctrl
, NULL
);
664 denied
= !hosts_access(&req
);
665 if (denied
|| lflag
) {
666 if (getnameinfo(&sep
->se_ctrladdr
,
667 (socklen_t
)sep
->se_ctrladdr
.sa_len
, NULL
, 0,
668 buf
, sizeof(buf
), 0) != 0) {
669 /* shouldn't happen */
670 (void)snprintf(buf
, sizeof buf
, "%d",
671 ntohs(sep
->se_ctrladdr_in
.sin_port
));
674 sockaddr_snprintf(abuf
, sizeof(abuf
), "%a",
678 syslog(deny_severity
,
679 "refused connection from %.500s(%s), service %s (%s)",
680 eval_client(&req
), abuf
, service
, sep
->se_proto
);
684 syslog(allow_severity
,
685 "connection from %.500s(%s), service %s (%s)",
686 eval_client(&req
), abuf
, service
, sep
->se_proto
);
693 for (s
= servtab
; s
; s
= s
->se_next
)
694 if (s
->se_fd
!= -1 && s
->se_fd
!= ctrl
) {
699 (*sep
->se_bi
->bi_fn
)(ctrl
, sep
);
701 if ((pwd
= getpwnam(sep
->se_user
)) == NULL
) {
702 syslog(LOG_ERR
, "%s/%s: %s: No such user",
703 sep
->se_service
, sep
->se_proto
, sep
->se_user
);
707 (grp
= getgrnam(sep
->se_group
)) == NULL
) {
708 syslog(LOG_ERR
, "%s/%s: %s: No such group",
709 sep
->se_service
, sep
->se_proto
, sep
->se_group
);
714 pwd
->pw_gid
= grp
->gr_gid
;
715 if (setgid(pwd
->pw_gid
) < 0) {
717 "%s/%s: can't set gid %d: %m", sep
->se_service
,
718 sep
->se_proto
, pwd
->pw_gid
);
721 (void) initgroups(pwd
->pw_name
,
723 if (setuid(pwd
->pw_uid
) < 0) {
725 "%s/%s: can't set uid %d: %m", sep
->se_service
,
726 sep
->se_proto
, pwd
->pw_uid
);
729 } else if (sep
->se_group
) {
730 (void) setgid((gid_t
)grp
->gr_gid
);
733 fprintf(stderr
, "%d execl %s\n",
734 getpid(), sep
->se_server
);
739 /* Set our control descriptor to not close-on-exec... */
740 if (fcntl(ctrl
, F_SETFD
, 0) < 0)
741 syslog(LOG_ERR
, "fcntl (%d, F_SETFD, 0): %m", ctrl
);
742 /* ...and dup it to stdin, stdout, and stderr. */
751 if (rlim_ofile
.rlim_cur
!= rlim_ofile_cur
&&
752 setrlimit(RLIMIT_NOFILE
, &rlim_ofile
) < 0)
753 syslog(LOG_ERR
, "setrlimit: %m");
755 execv(sep
->se_server
, sep
->se_argv
);
756 syslog(LOG_ERR
, "cannot execute %s: %m", sep
->se_server
);
758 if (sep
->se_socktype
!= SOCK_STREAM
)
759 recv(ctrl
, buf
, sizeof (buf
), 0);
772 pid
= wait3(&status
, WNOHANG
, NULL
);
776 (void) fprintf(stderr
, "%d reaped, status %#x\n",
778 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
779 if (sep
->se_wait
== pid
) {
782 if (WIFEXITED(status
) && WEXITSTATUS(status
))
784 "%s: exit status 0x%x",
785 sep
->se_server
, WEXITSTATUS(status
));
786 else if (WIFSIGNALED(status
))
788 "%s: exit signal 0x%x",
789 sep
->se_server
, WTERMSIG(status
));
792 EV_SET(ev
, sep
->se_fd
, EVFILT_READ
,
793 EV_ADD
| EV_ENABLE
, 0, 0, (intptr_t)sep
);
795 fprintf(stderr
, "restored %s, fd %d\n",
796 sep
->se_service
, sep
->se_fd
);
804 struct servtab
*sep
, *cp
, **sepp
;
808 syslog(LOG_ERR
, "%s: %m", CONFIG
);
811 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
813 while ((cp
= getconfigent()) != NULL
) {
814 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
)
815 if (strcmp(sep
->se_service
, cp
->se_service
) == 0 &&
816 strcmp(sep
->se_hostaddr
, cp
->se_hostaddr
) == 0 &&
817 strcmp(sep
->se_proto
, cp
->se_proto
) == 0 &&
818 ISMUX(sep
) == ISMUX(cp
))
823 #define SWAP(type, a, b) {type c = a; a = b; b = c;}
826 * sep->se_wait may be holding the pid of a daemon
827 * that we're waiting for. If so, don't overwrite
828 * it unless the config file explicitly says don't
831 if (cp
->se_bi
== 0 &&
832 (sep
->se_wait
== 1 || cp
->se_wait
== 0))
833 sep
->se_wait
= cp
->se_wait
;
834 SWAP(char *, sep
->se_user
, cp
->se_user
);
835 SWAP(char *, sep
->se_group
, cp
->se_group
);
836 SWAP(char *, sep
->se_server
, cp
->se_server
);
837 for (i
= 0; i
< MAXARGV
; i
++)
838 SWAP(char *, sep
->se_argv
[i
], cp
->se_argv
[i
]);
840 SWAP(char *, sep
->se_policy
, cp
->se_policy
);
842 SWAP(int, cp
->se_type
, sep
->se_type
);
843 SWAP(int, cp
->se_max
, sep
->se_max
);
845 if (isrpcservice(sep
))
847 sep
->se_rpcversl
= cp
->se_rpcversl
;
848 sep
->se_rpcversh
= cp
->se_rpcversh
;
851 print_service("REDO", sep
);
855 print_service("ADD ", sep
);
859 switch (sep
->se_family
) {
861 if (sep
->se_fd
!= -1)
863 n
= strlen(sep
->se_service
);
864 if (n
> sizeof(sep
->se_ctrladdr_un
.sun_path
)) {
865 syslog(LOG_ERR
, "%s: address too long",
870 (void)unlink(sep
->se_service
);
871 strncpy(sep
->se_ctrladdr_un
.sun_path
,
873 sep
->se_ctrladdr_un
.sun_family
= AF_LOCAL
;
874 sep
->se_ctrladdr_size
= (int)(n
+
875 sizeof(sep
->se_ctrladdr_un
) -
876 sizeof(sep
->se_ctrladdr_un
.sun_path
));
885 struct addrinfo hints
, *res
;
891 /* check if the family is supported */
892 s
= socket(sep
->se_family
, SOCK_DGRAM
, 0);
895 "%s/%s: %s: the address family is not "
896 "supported by the kernel",
897 sep
->se_service
, sep
->se_proto
,
904 memset(&hints
, 0, sizeof(hints
));
905 hints
.ai_family
= sep
->se_family
;
906 hints
.ai_socktype
= sep
->se_socktype
;
907 hints
.ai_flags
= AI_PASSIVE
;
908 if (!strcmp(sep
->se_hostaddr
, "*"))
911 host
= sep
->se_hostaddr
;
912 if (isrpcservice(sep
) || ISMUX(sep
))
915 port
= sep
->se_service
;
916 error
= getaddrinfo(host
, port
, &hints
, &res
);
918 if (error
== EAI_SERVICE
) {
919 /* gai_strerror not friendly enough */
920 syslog(LOG_WARNING
, "%s/%s: "
922 sep
->se_service
, sep
->se_proto
);
924 syslog(LOG_ERR
, "%s/%s: %s: %s",
925 sep
->se_service
, sep
->se_proto
,
927 gai_strerror(error
));
934 "%s/%s: %s: resolved to multiple addr",
935 sep
->se_service
, sep
->se_proto
,
941 memcpy(&sep
->se_ctrladdr
, res
->ai_addr
,
948 sep
->se_ctrladdr_size
= res
->ai_addrlen
;
951 if (isrpcservice(sep
)) {
954 sep
->se_rpcprog
= atoi(sep
->se_service
);
955 if (sep
->se_rpcprog
== 0) {
956 rp
= getrpcbyname(sep
->se_service
);
959 "%s/%s: unknown service",
965 sep
->se_rpcprog
= rp
->r_number
;
967 if (sep
->se_fd
== -1 && !ISMUX(sep
))
969 if (sep
->se_fd
!= -1)
976 if (sep
->se_fd
== -1 && !ISMUX(sep
))
984 * Purge anything not looked at above.
987 while ((sep
= *sepp
) != NULL
) {
988 if (sep
->se_checked
) {
989 sepp
= &sep
->se_next
;
992 *sepp
= sep
->se_next
;
995 if (isrpcservice(sep
))
997 if (sep
->se_family
== AF_LOCAL
)
998 (void)unlink(sep
->se_service
);
1000 print_service("FREE", sep
);
1009 struct servtab
*sep
;
1012 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
1013 if (sep
->se_fd
== -1 && !ISMUX(sep
)) {
1014 switch (sep
->se_family
) {
1021 if (sep
->se_fd
>= 0 && isrpcservice(sep
))
1032 struct servtab
*sep
;
1034 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
1035 if (sep
->se_fd
== -1)
1038 switch (sep
->se_family
) {
1040 (void)unlink(sep
->se_service
);
1046 if (sep
->se_wait
== 1 && isrpcservice(sep
))
1047 unregister_rpc(sep
);
1050 (void)close(sep
->se_fd
);
1057 setup(struct servtab
*sep
)
1065 if ((sep
->se_fd
= socket(sep
->se_family
, sep
->se_socktype
, 0)) < 0) {
1067 fprintf(stderr
, "socket failed on %s/%s: %s\n",
1068 sep
->se_service
, sep
->se_proto
, strerror(errno
));
1069 syslog(LOG_ERR
, "%s/%s: socket: %m",
1070 sep
->se_service
, sep
->se_proto
);
1073 /* Set all listening sockets to close-on-exec. */
1074 if (fcntl(sep
->se_fd
, F_SETFD
, FD_CLOEXEC
) < 0) {
1075 syslog(LOG_ERR
, "%s/%s: fcntl(F_SETFD, FD_CLOEXEC): %m",
1076 sep
->se_service
, sep
->se_proto
);
1082 #define turnon(fd, opt) \
1083 setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on))
1084 if (strcmp(sep
->se_proto
, "tcp") == 0 && (options
& SO_DEBUG
) &&
1085 turnon(sep
->se_fd
, SO_DEBUG
) < 0)
1086 syslog(LOG_ERR
, "setsockopt (SO_DEBUG): %m");
1087 if (turnon(sep
->se_fd
, SO_REUSEADDR
) < 0)
1088 syslog(LOG_ERR
, "setsockopt (SO_REUSEADDR): %m");
1091 /* Set the socket buffer sizes, if specified. */
1092 if (sep
->se_sndbuf
!= 0 && setsockopt(sep
->se_fd
, SOL_SOCKET
,
1093 SO_SNDBUF
, &sep
->se_sndbuf
, (socklen_t
)sizeof(sep
->se_sndbuf
)) < 0)
1094 syslog(LOG_ERR
, "setsockopt (SO_SNDBUF %d): %m",
1096 if (sep
->se_rcvbuf
!= 0 && setsockopt(sep
->se_fd
, SOL_SOCKET
,
1097 SO_RCVBUF
, &sep
->se_rcvbuf
, (socklen_t
)sizeof(sep
->se_rcvbuf
)) < 0)
1098 syslog(LOG_ERR
, "setsockopt (SO_RCVBUF %d): %m",
1101 if (sep
->se_family
== AF_INET6
) {
1103 v
= (sep
->se_type
== FAITH_TYPE
) ? &on
: &off
;
1104 if (setsockopt(sep
->se_fd
, IPPROTO_IPV6
, IPV6_FAITH
,
1105 v
, (socklen_t
)sizeof(*v
)) < 0)
1106 syslog(LOG_ERR
, "setsockopt (IPV6_FAITH): %m");
1110 if (ipsecsetup(sep
->se_family
, sep
->se_fd
, sep
->se_policy
) < 0 &&
1112 syslog(LOG_ERR
, "%s/%s: ipsec setup failed",
1113 sep
->se_service
, sep
->se_proto
);
1114 (void)close(sep
->se_fd
);
1120 if (bind(sep
->se_fd
, &sep
->se_ctrladdr
,
1121 (socklen_t
)sep
->se_ctrladdr_size
) < 0) {
1123 fprintf(stderr
, "bind failed on %s/%s: %s\n",
1124 sep
->se_service
, sep
->se_proto
, strerror(errno
));
1125 syslog(LOG_ERR
, "%s/%s: bind: %m",
1126 sep
->se_service
, sep
->se_proto
);
1127 (void) close(sep
->se_fd
);
1135 if (sep
->se_socktype
== SOCK_STREAM
)
1136 listen(sep
->se_fd
, 10);
1138 /* Set the accept filter, if specified. To be done after listen.*/
1139 if (sep
->se_accf
.af_name
[0] != 0 && setsockopt(sep
->se_fd
, SOL_SOCKET
,
1140 SO_ACCEPTFILTER
, &sep
->se_accf
,
1141 (socklen_t
)sizeof(sep
->se_accf
)) < 0)
1142 syslog(LOG_ERR
, "setsockopt(SO_ACCEPTFILTER %s): %m",
1143 sep
->se_accf
.af_name
);
1146 EV_SET(ev
, sep
->se_fd
, EVFILT_READ
, EV_ADD
| EV_ENABLE
, 0, 0,
1148 if (sep
->se_fd
> maxsock
) {
1149 maxsock
= sep
->se_fd
;
1150 if (maxsock
> (int)(rlim_ofile_cur
- FD_MARGIN
))
1154 fprintf(stderr
, "registered %s on %d\n",
1155 sep
->se_server
, sep
->se_fd
);
1159 * Finish with a service and its socket.
1162 close_sep(struct servtab
*sep
)
1164 if (sep
->se_fd
>= 0) {
1165 (void) close(sep
->se_fd
);
1172 register_rpc(struct servtab
*sep
)
1176 struct sockaddr_storage ss
;
1177 struct netconfig
*nconf
;
1181 if ((nconf
= getnetconfigent(sep
->se_proto
+4)) == NULL
) {
1182 syslog(LOG_ERR
, "%s: getnetconfigent failed",
1186 socklen
= sizeof ss
;
1187 if (getsockname(sep
->se_fd
, (struct sockaddr
*)(void *)&ss
, &socklen
) < 0) {
1188 syslog(LOG_ERR
, "%s/%s: getsockname: %m",
1189 sep
->se_service
, sep
->se_proto
);
1194 nbuf
.len
= ss
.ss_len
;
1195 nbuf
.maxlen
= sizeof (struct sockaddr_storage
);
1196 for (n
= sep
->se_rpcversl
; n
<= sep
->se_rpcversh
; n
++) {
1198 fprintf(stderr
, "rpcb_set: %u %d %s %s\n",
1199 sep
->se_rpcprog
, n
, nconf
->nc_netid
,
1200 taddr2uaddr(nconf
, &nbuf
));
1201 (void)rpcb_unset((unsigned int)sep
->se_rpcprog
, (unsigned int)n
, nconf
);
1202 if (!rpcb_set((unsigned int)sep
->se_rpcprog
, (unsigned int)n
, nconf
, &nbuf
))
1203 syslog(LOG_ERR
, "rpcb_set: %u %d %s %s%s",
1204 sep
->se_rpcprog
, n
, nconf
->nc_netid
,
1205 taddr2uaddr(nconf
, &nbuf
), clnt_spcreateerror(""));
1211 unregister_rpc(struct servtab
*sep
)
1215 struct netconfig
*nconf
;
1217 if ((nconf
= getnetconfigent(sep
->se_proto
+4)) == NULL
) {
1218 syslog(LOG_ERR
, "%s: getnetconfigent failed",
1223 for (n
= sep
->se_rpcversl
; n
<= sep
->se_rpcversh
; n
++) {
1225 fprintf(stderr
, "rpcb_unset(%u, %d, %s)\n",
1226 sep
->se_rpcprog
, n
, nconf
->nc_netid
);
1227 if (!rpcb_unset((unsigned int)sep
->se_rpcprog
, (unsigned int)n
, nconf
))
1228 syslog(LOG_ERR
, "rpcb_unset(%u, %d, %s) failed\n",
1229 sep
->se_rpcprog
, n
, nconf
->nc_netid
);
1235 static struct servtab
*
1236 enter(struct servtab
*cp
)
1238 struct servtab
*sep
;
1240 sep
= malloc(sizeof (*sep
));
1242 syslog(LOG_ERR
, "Out of memory.");
1247 sep
->se_rpcprog
= -1;
1248 sep
->se_next
= servtab
;
1253 FILE *fconfig
= NULL
;
1254 struct servtab serv
;
1255 char line
[LINE_MAX
];
1258 static char *policy
= NULL
;
1266 defhost
= newstr("*");
1272 if (fconfig
!= NULL
) {
1273 fseek(fconfig
, 0L, SEEK_SET
);
1276 fconfig
= fopen(CONFIG
, "r");
1277 return (fconfig
!= NULL
);
1283 if (fconfig
!= NULL
) {
1284 (void) fclose(fconfig
);
1287 if (defhost
!= NULL
) {
1293 static struct servtab
*
1296 struct servtab
*sep
= &serv
;
1298 char *cp
, *cp0
, *arg
, *buf0
, *buf1
, *sz0
, *sz1
;
1299 static char TCPMUX_TOKEN
[] = "tcpmux/";
1300 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1304 while ((cp
= nextline(fconfig
)) != NULL
) {
1306 /* lines starting with #@ is not a comment, but the policy */
1307 if (cp
[0] == '#' && cp
[1] == '@') {
1309 for (p
= cp
+ 2; p
&& *p
&& isspace((unsigned char)*p
); p
++)
1316 if (ipsecsetup_test(p
) < 0) {
1318 "%s: invalid ipsec policy \"%s\"",
1329 if (*cp
== '#' || *cp
== '\0')
1332 /* Avoid use of `skip' if there is a danger of it looking
1333 * at continuation lines.
1337 } while (*cp
== ' ' || *cp
== '\t');
1340 if ((arg
= skip(&cp
)) == NULL
)
1342 if (strcmp(arg
, "DOMAIN"))
1347 while (*cp
== ' ' || *cp
== '\t')
1352 while (*cp
&& *cp
!= ' ' && *cp
!= '\t')
1356 curdom
= newstr(arg
);
1363 * clear the static buffer, since some fields (se_ctrladdr,
1364 * for example) don't get initialized here.
1366 memset(sep
, 0, sizeof *sep
);
1369 /* got an empty line containing just blanks/tabs. */
1372 /* Check for a host name. */
1373 hostdelim
= strrchr(arg
, ':');
1376 if (arg
[0] == '[' && hostdelim
> arg
&& hostdelim
[-1] == ']') {
1377 hostdelim
[-1] = '\0';
1378 sep
->se_hostaddr
= newstr(arg
+ 1);
1380 sep
->se_hostaddr
= newstr(arg
);
1381 arg
= hostdelim
+ 1;
1383 * If the line is of the form `host:', then just change the
1384 * default host for the following lines.
1390 defhost
= sep
->se_hostaddr
;
1395 sep
->se_hostaddr
= newstr(defhost
);
1396 if (strncmp(arg
, TCPMUX_TOKEN
, MUX_LEN
) == 0) {
1397 char *c
= arg
+ MUX_LEN
;
1399 sep
->se_type
= MUXPLUS_TYPE
;
1402 sep
->se_type
= MUX_TYPE
;
1403 sep
->se_service
= newstr(c
);
1405 sep
->se_service
= newstr(arg
);
1406 sep
->se_type
= NORM_TYPE
;
1410 if (strncmp(arg
, "stream", sizeof("stream") - 1) == 0) {
1411 char *accf
, *accf_arg
;
1413 sep
->se_socktype
= SOCK_STREAM
;
1415 /* one and only one accept filter */
1416 accf
= index(arg
, ':');
1418 if (accf
!= rindex(arg
, ':') || /* more than one */
1419 *(accf
+ 1) == '\0') { /* nothing beyond */
1420 sep
->se_socktype
= -1;
1422 accf
++; /* skip delimiter */
1423 strncpy(sep
->se_accf
.af_name
, accf
,
1424 sizeof(sep
->se_accf
.af_name
));
1425 accf_arg
= index(accf
, ',');
1426 if (accf_arg
) { /* zero or one arg, no more */
1427 if ((rindex(accf
, ',') != accf_arg
)) {
1428 sep
->se_socktype
= -1;
1431 strncpy(sep
->se_accf
.af_arg
,
1433 sizeof(sep
->se_accf
.af_arg
));
1440 else if (strcmp(arg
, "dgram") == 0)
1441 sep
->se_socktype
= SOCK_DGRAM
;
1442 else if (strcmp(arg
, "rdm") == 0)
1443 sep
->se_socktype
= SOCK_RDM
;
1444 else if (strcmp(arg
, "seqpacket") == 0)
1445 sep
->se_socktype
= SOCK_SEQPACKET
;
1446 else if (strcmp(arg
, "raw") == 0)
1447 sep
->se_socktype
= SOCK_RAW
;
1449 sep
->se_socktype
= -1;
1452 if (sep
->se_type
== NORM_TYPE
&&
1453 strncmp(arg
, "faith/", strlen("faith/")) == 0) {
1454 arg
+= strlen("faith/");
1455 sep
->se_type
= FAITH_TYPE
;
1457 sep
->se_proto
= newstr(arg
);
1459 #define MALFORMED(arg) \
1461 syslog(LOG_ERR, "%s: malformed buffer size option `%s'", \
1462 sep->se_service, (arg)); \
1465 } while (/*CONSTCOND*/0)
1467 #define GETVAL(arg) \
1469 if (!isdigit((unsigned char)*(arg))) \
1471 val = (int)strtol((arg), &cp0, 10); \
1472 if (cp0 != NULL) { \
1473 if (cp0[1] != '\0') \
1475 if (cp0[0] == 'k') \
1477 if (cp0[0] == 'm') \
1478 val *= 1024 * 1024; \
1481 syslog(LOG_ERR, "%s: invalid buffer size `%s'", \
1482 sep->se_service, (arg)); \
1486 } while (/*CONSTCOND*/0)
1488 #define ASSIGN(arg) \
1490 if (strcmp((arg), "sndbuf") == 0) \
1491 sep->se_sndbuf = val; \
1492 else if (strcmp((arg), "rcvbuf") == 0) \
1493 sep->se_rcvbuf = val; \
1496 } while (/*CONSTCOND*/0)
1499 * Extract the send and receive buffer sizes before parsing
1502 sep
->se_sndbuf
= sep
->se_rcvbuf
= 0;
1503 buf0
= buf1
= sz0
= sz1
= NULL
;
1504 if ((buf0
= strchr(sep
->se_proto
, ',')) != NULL
) {
1505 /* Not meaningful for Tcpmux services. */
1507 syslog(LOG_ERR
, "%s: can't specify buffer sizes for "
1508 "tcpmux services", sep
->se_service
);
1515 /* Check to see if another socket buffer size was specified. */
1516 if ((buf1
= strchr(buf0
, ',')) != NULL
) {
1520 /* Make sure a 3rd one wasn't specified. */
1521 if (strchr(buf1
, ',') != NULL
) {
1522 syslog(LOG_ERR
, "%s: too many buffer sizes",
1527 /* Locate the size. */
1528 if ((sz1
= strchr(buf1
, '=')) == NULL
)
1535 /* Locate the size. */
1536 if ((sz0
= strchr(buf0
, '=')) == NULL
)
1555 if (strcmp(sep
->se_proto
, "unix") == 0) {
1556 sep
->se_family
= AF_LOCAL
;
1558 val
= (int)strlen(sep
->se_proto
);
1560 syslog(LOG_ERR
, "%s: invalid protocol specified",
1564 val
= sep
->se_proto
[val
- 1];
1566 case '4': /*tcp4 or udp4*/
1567 sep
->se_family
= AF_INET
;
1570 case '6': /*tcp6 or udp6*/
1571 sep
->se_family
= AF_INET6
;
1575 sep
->se_family
= AF_INET
; /*will become AF_INET6*/
1578 if (strncmp(sep
->se_proto
, "rpc/", 4) == 0) {
1581 cp1
= strchr(sep
->se_service
, '/');
1583 syslog(LOG_ERR
, "%s: no rpc version",
1588 sep
->se_rpcversl
= sep
->se_rpcversh
=
1589 (int)strtol(cp1
, &ccp
, 0);
1592 syslog(LOG_ERR
, "%s/%s: bad rpc version",
1593 sep
->se_service
, cp1
);
1598 sep
->se_rpcversh
= (int)strtol(cp1
, &ccp
, 0);
1603 syslog(LOG_ERR
, "%s: rpc services not suported",
1612 if ((cp1
= strchr(arg
, ':')) == NULL
)
1613 cp1
= strchr(arg
, '.');
1616 sep
->se_max
= atoi(cp1
);
1618 sep
->se_max
= TOOMANY
;
1620 sep
->se_wait
= strcmp(arg
, "wait") == 0;
1623 * Silently enforce "nowait" for TCPMUX services since
1624 * they don't have an assigned port to listen on.
1628 if (strncmp(sep
->se_proto
, "tcp", 3)) {
1630 "%s: bad protocol for tcpmux service %s",
1631 CONFIG
, sep
->se_service
);
1634 if (sep
->se_socktype
!= SOCK_STREAM
) {
1636 "%s: bad socket type for tcpmux service %s",
1637 CONFIG
, sep
->se_service
);
1641 sep
->se_user
= newstr(sskip(&cp
));
1642 if ((sep
->se_group
= strchr(sep
->se_user
, ':')) != NULL
)
1643 *sep
->se_group
++ = '\0';
1644 else if ((sep
->se_group
= strchr(sep
->se_user
, '.')) != NULL
)
1645 *sep
->se_group
++ = '\0';
1647 sep
->se_server
= newstr(sskip(&cp
));
1648 if (strcmp(sep
->se_server
, "internal") == 0) {
1651 for (bi
= biltins
; bi
->bi_service
; bi
++)
1652 if (bi
->bi_socktype
== sep
->se_socktype
&&
1653 strcmp(bi
->bi_service
, sep
->se_service
) == 0)
1655 if (bi
->bi_service
== 0) {
1656 syslog(LOG_ERR
, "internal service %s unknown",
1661 sep
->se_wait
= bi
->bi_wait
;
1665 for (arg
= skip(&cp
); cp
; arg
= skip(&cp
)) {
1669 if (argc
== 0 && (colon
= strrchr(arg
, ':'))) {
1670 while (arg
< colon
) {
1677 if (isdigit(*arg
)) {
1678 x
= strtol(arg
, &ccp
, 0);
1683 sep
->se_log
&= ~MULOG_RFC931
;
1687 sep
->se_log
|= MULOG_RFC931
;
1697 sep
->se_argv
[argc
++] = newstr(arg
);
1699 while (argc
<= MAXARGV
)
1700 sep
->se_argv
[argc
++] = NULL
;
1702 sep
->se_policy
= policy
? newstr(policy
) : NULL
;
1708 freeconfig(struct servtab
*cp
)
1712 if (cp
->se_hostaddr
)
1713 free(cp
->se_hostaddr
);
1715 free(cp
->se_service
);
1720 /* Note: se_group is part of the newstr'ed se_user */
1722 free(cp
->se_server
);
1723 for (i
= 0; i
< MAXARGV
; i
++)
1725 free(cp
->se_argv
[i
]);
1728 free(cp
->se_policy
);
1734 * Safe skip - if skip returns null, log a syntax error in the
1735 * configuration file and exit.
1744 syslog(LOG_ERR
, "%s: syntax error", CONFIG
);
1761 while (*cp
== ' ' || *cp
== '\t')
1767 (void) ungetc(c
, fconfig
);
1768 if (c
== ' ' || c
== '\t')
1769 if ((cp
= nextline(fconfig
)) != NULL
)
1776 while (*cp
&& (quote
|| (*cp
!= ' ' && *cp
!= '\t'))) {
1777 if (*cp
== '\'' || *cp
== '"') {
1778 if (quote
&& *cp
!= quote
)
1785 memmove(cp
, cp
+1, strlen(cp
));
1801 if (fgets(line
, (int)sizeof(line
), fd
) == NULL
)
1803 cp
= strchr(line
, '\n');
1810 newstr(const char *cp
)
1813 if ((dp
= strdup((cp
!= NULL
) ? cp
: "")) != NULL
)
1815 syslog(LOG_ERR
, "strdup: %m");
1821 inetd_setproctitle(char *a
, int s
)
1824 struct sockaddr_storage ss
;
1825 char hbuf
[NI_MAXHOST
];
1827 struct sockaddr
*sa
;
1830 sa
= (struct sockaddr
*)(void *)&ss
;
1831 if (getpeername(s
, sa
, &size
) == 0) {
1832 if (getnameinfo(sa
, size
, hbuf
, (socklen_t
)sizeof(hbuf
), NULL
,
1837 setproctitle("-%s [%s]", a
, hp
);
1839 setproctitle("-%s", a
);
1845 #ifdef RLIMIT_NOFILE
1851 if (getrlimit(RLIMIT_NOFILE
, &rl
) < 0) {
1852 syslog(LOG_ERR
, "getrlimit: %m");
1855 rl
.rlim_cur
= MIN(rl
.rlim_max
, rl
.rlim_cur
+ FD_CHUNK
);
1856 if (rl
.rlim_cur
<= rlim_ofile_cur
) {
1858 "bump_nofile: cannot extend file limit, max = %d",
1863 if (setrlimit(RLIMIT_NOFILE
, &rl
) < 0) {
1864 syslog(LOG_ERR
, "setrlimit: %m");
1868 rlim_ofile_cur
= rl
.rlim_cur
;
1872 syslog(LOG_ERR
, "bump_nofile: cannot extend file limit");
1878 * Internet services provided internally by inetd:
1880 #define BUFSIZE 4096
1884 echo_stream(int s
, struct servtab
*sep
) /* Echo service -- echo data back */
1886 char buffer
[BUFSIZE
];
1889 inetd_setproctitle(sep
->se_service
, s
);
1890 while ((i
= read(s
, buffer
, sizeof(buffer
))) > 0 &&
1891 write(s
, buffer
, (size_t)i
) > 0)
1897 echo_dg(int s
, struct servtab
*sep
) /* Echo service -- echo data back */
1899 char buffer
[BUFSIZE
];
1902 struct sockaddr_storage ss
;
1903 struct sockaddr
*sa
;
1905 sa
= (struct sockaddr
*)(void *)&ss
;
1907 if ((i
= recvfrom(s
, buffer
, sizeof(buffer
), 0, sa
, &size
)) < 0)
1909 if (port_good_dg(sa
))
1910 (void) sendto(s
, buffer
, (size_t)i
, 0, sa
, size
);
1915 discard_stream(int s
, struct servtab
*sep
) /* Discard service -- ignore data */
1917 char buffer
[BUFSIZE
];
1919 inetd_setproctitle(sep
->se_service
, s
);
1920 while ((errno
= 0, read(s
, buffer
, sizeof(buffer
)) > 0) ||
1927 discard_dg(int s
, struct servtab
*sep
) /* Discard service -- ignore data */
1930 char buffer
[BUFSIZE
];
1932 (void) read(s
, buffer
, sizeof(buffer
));
1946 for (i
= 0; i
<= 128; ++i
)
1953 chargen_stream(int s
,struct servtab
*sep
) /* Character generator */
1956 char *rs
, text
[LINESIZ
+2];
1958 inetd_setproctitle(sep
->se_service
, s
);
1965 text
[LINESIZ
] = '\r';
1966 text
[LINESIZ
+ 1] = '\n';
1968 if ((len
= endring
- rs
) >= LINESIZ
)
1969 memmove(text
, rs
, LINESIZ
);
1971 memmove(text
, rs
, len
);
1972 memmove(text
+ len
, ring
, LINESIZ
- len
);
1974 if (++rs
== endring
)
1976 if (write(s
, text
, sizeof(text
)) != sizeof(text
))
1983 chargen_dg(int s
, struct servtab
*sep
) /* Character generator */
1985 struct sockaddr_storage ss
;
1986 struct sockaddr
*sa
;
1990 char text
[LINESIZ
+2];
1997 sa
= (struct sockaddr
*)(void *)&ss
;
1999 if (recvfrom(s
, text
, sizeof(text
), 0, sa
, &size
) < 0)
2002 if (!port_good_dg(sa
))
2005 if ((len
= endring
- rs
) >= LINESIZ
)
2006 memmove(text
, rs
, LINESIZ
);
2008 memmove(text
, rs
, len
);
2009 memmove(text
+ len
, ring
, LINESIZ
- len
);
2011 if (++rs
== endring
)
2013 text
[LINESIZ
] = '\r';
2014 text
[LINESIZ
+ 1] = '\n';
2015 (void) sendto(s
, text
, sizeof(text
), 0, sa
, size
);
2019 * Return a machine readable date and time, in the form of the
2020 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
2021 * returns the number of seconds since midnight, Jan 1, 1970,
2022 * we must add 2208988800 seconds to this figure to make up for
2023 * some seventy years Bell Labs was asleep.
2031 if (gettimeofday(&tv
, NULL
) < 0) {
2033 fprintf(stderr
, "Unable to get time of day\n");
2036 #define OFFSET ((uint32_t)25567 * 24*60*60)
2037 return (htonl((uint32_t)(tv
.tv_sec
+ OFFSET
)));
2043 machtime_stream(int s
, struct servtab
*sep
)
2047 result
= machtime();
2048 (void) write(s
, &result
, sizeof(result
));
2053 machtime_dg(int s
, struct servtab
*sep
)
2056 struct sockaddr_storage ss
;
2057 struct sockaddr
*sa
;
2060 sa
= (struct sockaddr
*)(void *)&ss
;
2062 if (recvfrom(s
, &result
, sizeof(result
), 0, sa
, &size
) < 0)
2064 if (!port_good_dg(sa
))
2066 result
= machtime();
2067 (void)sendto(s
, &result
, sizeof(result
), 0, sa
, size
);
2072 daytime_stream(int s
,struct servtab
*sep
)
2073 /* Return human-readable time of day */
2079 clk
= time((time_t *) 0);
2081 len
= snprintf(buffer
, sizeof buffer
, "%.24s\r\n", ctime(&clk
));
2082 (void) write(s
, buffer
, len
);
2087 daytime_dg(int s
, struct servtab
*sep
)
2088 /* Return human-readable time of day */
2092 struct sockaddr_storage ss
;
2093 struct sockaddr
*sa
;
2097 clk
= time((time_t *) 0);
2099 sa
= (struct sockaddr
*)(void *)&ss
;
2101 if (recvfrom(s
, buffer
, sizeof(buffer
), 0, sa
, &size
) < 0)
2103 if (!port_good_dg(sa
))
2105 len
= snprintf(buffer
, sizeof buffer
, "%.24s\r\n", ctime(&clk
));
2106 (void) sendto(s
, buffer
, len
, 0, sa
, size
);
2111 * Dump relevant information to stderr
2114 print_service(const char *action
, struct servtab
*sep
)
2117 if (isrpcservice(sep
))
2119 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2124 action
, sep
->se_service
,
2125 sep
->se_rpcprog
, sep
->se_rpcversh
, sep
->se_rpcversl
, sep
->se_proto
,
2126 sep
->se_wait
, sep
->se_max
, sep
->se_user
, sep
->se_group
,
2127 (long)sep
->se_bi
, sep
->se_server
2129 , (sep
->se_policy
? sep
->se_policy
: "")
2134 "%s: %s proto=%s%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2139 action
, sep
->se_service
,
2140 sep
->se_type
== FAITH_TYPE
? "faith/" : "",
2142 sep
->se_wait
, sep
->se_max
, sep
->se_user
, sep
->se_group
,
2143 (long)sep
->se_bi
, sep
->se_server
2145 , (sep
->se_policy
? sep
->se_policy
: "")
2154 (void)fprintf(stderr
, "usage: %s [-dl] [conf]\n", getprogname());
2156 (void)fprintf(stderr
, "usage: %s [-d] [conf]\n", getprogname());
2163 * Based on TCPMUX.C by Mark K. Lottor November 1988
2164 * sri-nic::ps:<mkl>tcpmux.c
2167 static int /* # of characters upto \r,\n or \0 */
2168 get_line(int fd
, char *buf
, int len
)
2174 n
= read(fd
, buf
, len
-count
);
2180 if (*buf
== '\r' || *buf
== '\n' || *buf
== '\0')
2185 } while (count
< len
);
2189 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */
2191 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)
2194 tcpmux(int ctrl
, struct servtab
*sep
)
2196 char service
[MAX_SERV_LEN
+1];
2199 /* Get requested service name */
2200 if ((len
= get_line(ctrl
, service
, MAX_SERV_LEN
)) < 0) {
2201 strwrite(ctrl
, "-Error reading service name\r\n");
2204 service
[len
] = '\0';
2207 fprintf(stderr
, "tcpmux: someone wants %s\n", service
);
2210 * Help is a required command, and lists available services,
2213 if (!strcasecmp(service
, "help")) {
2214 strwrite(ctrl
, "+Available services:\r\n");
2215 strwrite(ctrl
, "help\r\n");
2216 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
2219 (void)write(ctrl
, sep
->se_service
,
2220 strlen(sep
->se_service
));
2221 strwrite(ctrl
, "\r\n");
2226 /* Try matching a service in inetd.conf with the request */
2227 for (sep
= servtab
; sep
!= NULL
; sep
= sep
->se_next
) {
2230 if (!strcasecmp(service
, sep
->se_service
)) {
2232 strwrite(ctrl
, "+Go\r\n");
2233 run_service(ctrl
, sep
, 1 /* forked */);
2237 strwrite(ctrl
, "-Service not available\r\n");
2244 dolog(struct servtab
*sep
, int ctrl
)
2246 struct sockaddr_storage ss
;
2247 struct sockaddr
*sa
= (struct sockaddr
*)&ss
;
2248 socklen_t len
= sizeof(ss
);
2249 char *host
, *dp
, buf
[BUFSIZ
], abuf
[BUFSIZ
];
2252 switch (sep
->se_family
) {
2262 if (getpeername(ctrl
, sa
, &len
) < 0) {
2263 if (errno
!= ENOTCONN
) {
2264 syslog(LOG_ERR
, "getpeername: %m");
2267 if (recvfrom(ctrl
, buf
, sizeof(buf
), MSG_PEEK
, sa
, &len
) < 0) {
2268 syslog(LOG_ERR
, "recvfrom: %m");
2273 switch (sa
->sa_family
) {
2280 syslog(LOG_ERR
, "unexpected address family %u", sa
->sa_family
);
2284 if (getnameinfo(sa
, len
, buf
, sizeof(buf
), NULL
, 0, 0) != 0)
2285 strlcpy(buf
, "?", sizeof(buf
));
2288 switch (sep
->se_log
& ~MULOG_RFC931
) {
2292 if (curdom
== NULL
|| *curdom
== '\0')
2294 dp
= host
+ strlen(host
) - strlen(curdom
);
2298 fprintf(stderr
, "check \"%s\" against curdom \"%s\"\n",
2300 if (strcasecmp(dp
, curdom
) == 0)
2308 openlog("", LOG_NOWAIT
, MULOG
);
2310 sockaddr_snprintf(abuf
, sizeof(abuf
), "%a", sa
);
2311 if (connected
&& (sep
->se_log
& MULOG_RFC931
))
2312 syslog(LOG_INFO
, "%s@%s(%s) wants %s",
2313 rfc931_name(sa
, ctrl
), host
, abuf
, sep
->se_service
);
2315 syslog(LOG_INFO
, "%s(%s) wants %s",
2316 host
, abuf
, sep
->se_service
);
2321 * Wietse Venema, Eindhoven University of Technology, The Netherlands.
2324 static char sccsid
[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46";
2329 #define RFC931_PORT 113 /* Semi-well-known port */
2333 static jmp_buf timebuf
;
2335 /* timeout - handle timeouts */
2340 longjmp(timebuf
, sig
);
2343 /* rfc931_name - return remote user name */
2346 rfc931_name(struct sockaddr
*there
, /* remote link information */
2349 struct sockaddr_storage here
; /* local link information */
2350 struct sockaddr_storage sin
; /* for talking to RFC931 daemon */
2355 static char user
[256]; /* XXX */
2358 char *result
= "USER_UNKNOWN";
2360 u_int16_t myport
, hisport
;
2362 /* Find out local port number of our stdin. */
2364 length
= sizeof(here
);
2365 if (getsockname(ctrl
, (struct sockaddr
*) &here
, &length
) == -1) {
2366 syslog(LOG_ERR
, "getsockname: %m");
2369 switch (here
.ss_family
) {
2371 myport
= ((struct sockaddr_in
*)&here
)->sin_port
;
2375 myport
= ((struct sockaddr_in6
*)&here
)->sin6_port
;
2379 switch (there
->sa_family
) {
2381 hisport
= ((struct sockaddr_in
*)&there
)->sin_port
;
2385 hisport
= ((struct sockaddr_in6
*)&there
)->sin6_port
;
2389 /* Set up timer so we won't get stuck. */
2391 if ((s
= socket(here
.ss_family
, SOCK_STREAM
, 0)) == -1) {
2392 syslog(LOG_ERR
, "socket: %m");
2397 switch (sin
.ss_family
) {
2399 ((struct sockaddr_in
*)&sin
)->sin_port
= htons(0);
2403 ((struct sockaddr_in6
*)&sin
)->sin6_port
= htons(0);
2407 if (bind(s
, (struct sockaddr
*) &sin
, sin
.ss_len
) == -1) {
2408 syslog(LOG_ERR
, "bind: %m");
2412 signal(SIGALRM
, timeout
);
2413 if (setjmp(timebuf
)) {
2414 close(s
); /* not: fclose(fp) */
2419 /* Connect to the RFC931 daemon. */
2421 memcpy(&sin
, there
, there
->sa_len
);
2422 switch (sin
.ss_family
) {
2424 ((struct sockaddr_in
*)&sin
)->sin_port
= htons(RFC931_PORT
);
2428 ((struct sockaddr_in6
*)&sin
)->sin6_port
= htons(RFC931_PORT
);
2432 if (connect(s
, (struct sockaddr
*) &sin
, sin
.ss_len
) == -1) {
2438 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
2439 (void)snprintf(buf
, sizeof buf
, "%u,%u\r\n", ntohs(hisport
),
2442 for (len
= 0, cp
= buf
; len
< strlen(buf
); ) {
2445 if ((n
= write(s
, cp
, strlen(buf
) - len
)) == -1) {
2455 for (cp
= buf
; cp
< buf
+ sizeof(buf
) - 1; ) {
2457 if (read(s
, &c
, 1) != 1) {
2468 if (sscanf(buf
, "%u , %u : USERID :%*[^:]:%255s", &remote
, &local
,
2469 user
) == 3 && ntohs(hisport
) == remote
&& ntohs(myport
) == local
) {
2470 /* Strip trailing carriage return. */
2471 if ((cp
= strchr(user
, '\r')) != NULL
)
2483 * check if the address/port where send data to is one of the obvious ports
2484 * that are used for denial of service attacks like two echo ports
2485 * just echoing data between them
2488 port_good_dg(struct sockaddr
*sa
)
2491 struct sockaddr_in
*sin
;
2493 struct in6_addr
*in6
;
2494 struct sockaddr_in6
*sin6
;
2498 char hbuf
[NI_MAXHOST
];
2500 switch (sa
->sa_family
) {
2502 sin
= (struct sockaddr_in
*)(void *)sa
;
2503 in
.s_addr
= ntohl(sin
->sin_addr
.s_addr
);
2504 port
= ntohs(sin
->sin_port
);
2508 if (IN_MULTICAST(in
.s_addr
))
2510 switch ((in
.s_addr
& 0xff000000) >> 24) {
2511 case 0: case 127: case 255:
2514 if (dg_broadcast(&in
))
2519 sin6
= (struct sockaddr_in6
*)(void *)sa
;
2520 in6
= &sin6
->sin6_addr
;
2521 port
= ntohs(sin6
->sin6_port
);
2522 if (IN6_IS_ADDR_MULTICAST(in6
) || IN6_IS_ADDR_UNSPECIFIED(in6
))
2524 if (IN6_IS_ADDR_V4MAPPED(in6
) || IN6_IS_ADDR_V4COMPAT(in6
)) {
2525 memcpy(&in
, &in6
->s6_addr
[12], sizeof(in
));
2526 in
.s_addr
= ntohl(in
.s_addr
);
2532 /* XXX unsupported af, is it safe to assume it to be safe? */
2536 for (i
= 0; bad_ports
[i
] != 0; i
++) {
2537 if (port
== bad_ports
[i
])
2544 if (getnameinfo(sa
, sa
->sa_len
, hbuf
, (socklen_t
)sizeof(hbuf
), NULL
, 0,
2546 strlcpy(hbuf
, "?", sizeof(hbuf
));
2547 syslog(LOG_WARNING
,"Possible DoS attack from %s, Port %d",
2552 /* XXX need optimization */
2554 dg_broadcast(struct in_addr
*in
)
2556 struct ifaddrs
*ifa
, *ifap
;
2557 struct sockaddr_in
*sin
;
2559 if (getifaddrs(&ifap
) < 0)
2561 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
2562 if (ifa
->ifa_addr
->sa_family
!= AF_INET
||
2563 (ifa
->ifa_flags
& IFF_BROADCAST
) == 0)
2565 sin
= (struct sockaddr_in
*)(void *)ifa
->ifa_broadaddr
;
2566 if (sin
->sin_addr
.s_addr
== in
->s_addr
) {
2576 my_kevent(const struct kevent
*changelist
, size_t nchanges
,
2577 struct kevent
*eventlist
, size_t nevents
)
2581 while ((result
= kevent(kq
, changelist
, nchanges
, eventlist
, nevents
,
2583 if (errno
!= EINTR
) {
2584 syslog(LOG_ERR
, "kevent: %m");
2591 static struct kevent
*
2594 if (changes
== A_CNT(changebuf
)) {
2595 (void) my_kevent(changebuf
, A_CNT(changebuf
), NULL
, 0);
2599 return (&changebuf
[changes
++]);