etc/services - sync with NetBSD-8
[minix.git] / usr.sbin / inetd / inetd.c
blob92ff381c3fe917a1dcfa219e426eadb36ec580fa
1 /* $NetBSD: inetd.c,v 1.122 2014/04/05 23:36:10 khorben Exp $ */
3 /*-
4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
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
13 * are met:
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
39 * are met:
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
59 * SUCH DAMAGE.
62 #include <sys/cdefs.h>
63 #ifndef lint
64 __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\
65 The Regents of the University of California. All rights reserved.");
66 #if 0
67 static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94";
68 #else
69 __RCSID("$NetBSD: inetd.c,v 1.122 2014/04/05 23:36:10 khorben Exp $");
70 #endif
71 #endif /* not lint */
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)
106 * For RPC services
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
121 * hostaddress:
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
127 * *:
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
152 * for new requests.
154 * Comment lines are indicated by a `#' in column 1.
156 * #ifdef IPSEC
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.
161 * #endif
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
171 * b) other: setuid()
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)
179 * NO initgroups()
181 * b) other: setuid()
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>
191 #include <sys/un.h>
192 #include <sys/wait.h>
193 #include <sys/time.h>
194 #include <sys/resource.h>
195 #include <sys/event.h>
197 #ifndef NO_RPC
198 #define RPC
199 #endif
201 #include <net/if.h>
203 #include <netinet/in.h>
204 #include <arpa/inet.h>
205 #ifdef RPC
206 #include <rpc/rpc.h>
207 #include <rpc/rpcb_clnt.h>
208 #include <netconfig.h>
209 #endif
211 #include <ctype.h>
212 #include <errno.h>
213 #include <fcntl.h>
214 #include <grp.h>
215 #include <netdb.h>
216 #include <pwd.h>
217 #include <signal.h>
218 #include <stdio.h>
219 #include <stdlib.h>
220 #include <string.h>
221 #include <syslog.h>
222 #include <unistd.h>
223 #include <util.h>
224 #include <ifaddrs.h>
226 #include "pathnames.h"
228 #ifdef IPSEC
229 #include <netipsec/ipsec.h>
230 #ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
231 #undef IPSEC
232 #endif
233 #include "ipsec.h"
234 #endif
236 #ifdef LIBWRAP
237 # include <tcpd.h>
238 #ifndef LIBWRAP_ALLOW_FACILITY
239 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
240 #endif
241 #ifndef LIBWRAP_ALLOW_SEVERITY
242 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
243 #endif
244 #ifndef LIBWRAP_DENY_FACILITY
245 # define LIBWRAP_DENY_FACILITY LOG_AUTH
246 #endif
247 #ifndef LIBWRAP_DENY_SEVERITY
248 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
249 #endif
250 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
251 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
252 #endif
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]))
260 int debug;
261 #ifdef LIBWRAP
262 int lflag;
263 #endif
264 int maxsock;
265 #ifndef __minix
266 int kq;
267 #else /* __minix */
268 int sig_pipe[2];
269 sigset_t sig_mask, old_mask;
270 #endif /* __minix */
271 int options;
272 int timingout;
273 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
275 #ifndef OPEN_MAX
276 #define OPEN_MAX 64
277 #endif
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];
286 size_t changes;
288 struct servtab {
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 */
306 #define MAXARGV 20
307 char *se_argv[MAXARGV+1]; /* program arguments */
308 #ifdef IPSEC
309 char *se_policy; /* IPsec poilcy string */
310 #endif
311 struct accept_filter_arg se_accf; /* accept filter for stream service */
312 int se_fd; /* open descriptor */
313 int se_type; /* type */
314 union {
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;
328 } *servtab;
330 #define NORM_TYPE 0
331 #define MUX_TYPE 1
332 #define MUXPLUS_TYPE 2
333 #define FAITH_TYPE 3
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 *);
376 #ifndef __minix
377 static int my_kevent(const struct kevent *, size_t, struct kevent *,
378 size_t);
379 static struct kevent * allocchange(void);
380 #endif /* !__minix */
381 static int get_line(int, char *, int);
382 static void spawn(struct servtab *, int);
384 struct biltin {
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 */
391 } biltins[] = {
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 };
431 #ifdef __minix
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).
439 static void
440 got_signal(int sig)
443 (void) write(sig_pipe[1], &sig, sizeof(sig));
445 #endif /* __minix */
448 main(int argc, char *argv[])
450 int ch, n, reload = 1;
452 while ((ch = getopt(argc, argv,
453 #ifdef LIBWRAP
454 "dl"
455 #else
457 #endif
458 )) != -1)
459 switch(ch) {
460 case 'd':
461 debug = 1;
462 options |= SO_DEBUG;
463 break;
464 #ifdef LIBWRAP
465 case 'l':
466 lflag = 1;
467 break;
468 #endif
469 case '?':
470 default:
471 usage();
473 argc -= optind;
474 argv += optind;
476 if (argc > 0)
477 CONFIG = argv[0];
479 if (!debug)
480 daemon(0, 0);
481 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
482 pidfile(NULL);
484 #ifndef __minix
485 kq = kqueue();
486 if (kq < 0) {
487 syslog(LOG_ERR, "kqueue: %m");
488 return (EXIT_FAILURE);
490 #else /* __minix */
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);
499 sig_mask = old_mask;
500 #endif /* __minix */
502 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
503 syslog(LOG_ERR, "getrlimit: %m");
504 } else {
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++) {
511 int signum;
513 signum = my_signals[n];
514 #ifndef __minix
515 if (signum != SIGCHLD)
516 (void) signal(signum, SIG_IGN);
518 if (signum != SIGPIPE) {
519 struct kevent *ev;
521 ev = allocchange();
522 EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE,
523 0, 0, 0);
525 #else /* __minix */
526 /* The above code ignores but does not "catch" SIGPIPE. */
527 if (signum != SIGPIPE)
528 (void) signal(signum, got_signal);
529 else
530 (void) signal(signum, SIG_IGN);
531 sigaddset(&sig_mask, signum);
532 #endif /* __minix */
535 for (;;) {
536 int ctrl;
537 #ifndef __minix
538 struct kevent eventbuf[64], *ev;
539 #else
540 fd_set fds;
541 int sig, highfd;
542 #endif /* !__minix */
543 struct servtab *sep;
545 if (reload) {
546 reload = 0;
547 config();
550 #ifdef __minix
551 FD_ZERO(&fds);
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)
559 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 &&
572 errno == EINTR);
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) {
578 switch (sig) {
579 #else /* !__minix */
580 n = my_kevent(changebuf, changes, eventbuf, A_CNT(eventbuf));
581 changes = 0;
583 for (ev = eventbuf; n > 0; ev++, n--) {
584 if (ev->filter == EVFILT_SIGNAL) {
585 switch (ev->ident) {
586 #endif /* !__minix */
587 case SIGALRM:
588 retry();
589 break;
590 case SIGCHLD:
591 reapchild();
592 break;
593 case SIGTERM:
594 case SIGINT:
595 goaway();
596 break;
597 case SIGHUP:
598 reload = 1;
599 break;
601 continue;
603 #ifdef __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))
609 continue;
610 #else /* !__minix */
611 if (ev->filter != EVFILT_READ)
612 continue;
613 sep = (struct servtab *)ev->udata;
614 /* Paranoia */
615 if ((int)ev->ident != sep->se_fd)
616 continue;
617 #endif /* !__minix */
618 if (debug)
619 fprintf(stderr, "someone wants %s\n",
620 sep->se_service);
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);
624 if (debug)
625 fprintf(stderr, "accept, ctrl %d\n",
626 ctrl);
627 if (ctrl < 0) {
628 if (errno != EINTR)
629 syslog(LOG_WARNING,
630 "accept (for %s): %m",
631 sep->se_service);
632 continue;
634 } else
635 ctrl = sep->se_fd;
636 spawn(sep, ctrl);
641 static void
642 spawn(struct servtab *sep, int ctrl)
644 int dofork;
645 pid_t pid;
647 pid = 0;
648 #ifdef LIBWRAP_INTERNAL
649 dofork = 1;
650 #else
651 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
652 #endif
653 if (dofork) {
654 if (sep->se_count++ == 0)
655 (void)gettimeofday(&sep->se_time, NULL);
656 else if (sep->se_count >= sep->se_max) {
657 struct timeval now;
659 (void)gettimeofday(&now, NULL);
660 if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
661 sep->se_time = now;
662 sep->se_count = 1;
663 } else {
664 syslog(LOG_ERR,
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 ==
670 SOCK_STREAM)
671 close(ctrl);
672 close_sep(sep);
673 if (!timingout) {
674 timingout = 1;
675 alarm(RETRYTIME);
677 return;
680 pid = fork();
681 if (pid < 0) {
682 syslog(LOG_ERR, "fork: %m");
683 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
684 close(ctrl);
685 sleep(1);
686 return;
688 if (pid != 0 && sep->se_wait) {
689 #ifndef __minix
690 struct kevent *ev;
692 sep->se_wait = pid;
693 ev = allocchange();
694 EV_SET(ev, sep->se_fd, EVFILT_READ,
695 EV_DELETE, 0, 0, 0);
696 #endif /* !__minix */
698 if (pid == 0) {
699 size_t n;
701 for (n = 0; n < A_CNT(my_signals); n++)
702 (void) signal(my_signals[n], SIG_DFL);
703 #ifdef __minix
704 close(sig_pipe[0]);
705 close(sig_pipe[1]);
707 (void) sigprocmask(SIG_SETMASK, &old_mask, NULL);
708 #endif /* __minix */
709 if (debug)
710 setsid();
713 if (pid == 0) {
714 run_service(ctrl, sep, dofork);
715 if (dofork)
716 exit(0);
718 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
719 close(ctrl);
722 static void
723 run_service(int ctrl, struct servtab *sep, int didfork)
725 struct passwd *pwd;
726 struct group *grp = NULL; /* XXX gcc */
727 char buf[NI_MAXSERV];
728 struct servtab *s;
729 #ifdef LIBWRAP
730 char abuf[BUFSIZ];
731 struct request_info req;
732 int denied;
733 char *service = NULL; /* XXX gcc */
734 #endif
736 #ifdef LIBWRAP
737 #ifndef LIBWRAP_INTERNAL
738 if (sep->se_bi == 0)
739 #endif
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);
743 fromhost(&req);
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));
753 service = buf;
754 if (req.client->sin) {
755 sockaddr_snprintf(abuf, sizeof(abuf), "%a",
756 req.client->sin);
757 } else {
758 strcpy(abuf, "(null)");
761 if (denied) {
762 syslog(deny_severity,
763 "refused connection from %.500s(%s), service %s (%s)",
764 eval_client(&req), abuf, service, sep->se_proto);
765 goto reject;
767 if (lflag) {
768 syslog(allow_severity,
769 "connection from %.500s(%s), service %s (%s)",
770 eval_client(&req), abuf, service, sep->se_proto);
773 #endif /* LIBWRAP */
775 if (sep->se_bi) {
776 if (didfork) {
777 for (s = servtab; s; s = s->se_next)
778 if (s->se_fd != -1 && s->se_fd != ctrl) {
779 close(s->se_fd);
780 s->se_fd = -1;
783 (*sep->se_bi->bi_fn)(ctrl, sep);
784 } else {
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);
788 goto reject;
790 if (sep->se_group &&
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);
794 goto reject;
796 if (pwd->pw_uid) {
797 if (sep->se_group)
798 pwd->pw_gid = grp->gr_gid;
799 if (setgid(pwd->pw_gid) < 0) {
800 syslog(LOG_ERR,
801 "%s/%s: can't set gid %d: %m", sep->se_service,
802 sep->se_proto, pwd->pw_gid);
803 goto reject;
805 (void) initgroups(pwd->pw_name,
806 pwd->pw_gid);
807 if (setuid(pwd->pw_uid) < 0) {
808 syslog(LOG_ERR,
809 "%s/%s: can't set uid %d: %m", sep->se_service,
810 sep->se_proto, pwd->pw_uid);
811 goto reject;
813 } else if (sep->se_group) {
814 (void) setgid((gid_t)grp->gr_gid);
816 if (debug)
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. */
823 if (ctrl != 0) {
824 dup2(ctrl, 0);
825 close(ctrl);
826 ctrl = 0;
828 dup2(0, 1);
829 dup2(0, 2);
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);
835 reject:
836 if (sep->se_socktype != SOCK_STREAM)
837 recv(ctrl, buf, sizeof (buf), 0);
838 _exit(1);
842 static void
843 reapchild(void)
845 int status;
846 pid_t pid;
847 struct servtab *sep;
849 for (;;) {
850 pid = wait3(&status, WNOHANG, NULL);
851 if (pid <= 0)
852 break;
853 if (debug)
854 (void) fprintf(stderr, "%d reaped, status %#x\n",
855 pid, status);
856 for (sep = servtab; sep != NULL; sep = sep->se_next)
857 if (sep->se_wait == pid) {
858 #ifndef __minix
859 struct kevent *ev;
860 #endif /* !__minix */
862 if (WIFEXITED(status) && WEXITSTATUS(status))
863 syslog(LOG_WARNING,
864 "%s: exit status %u",
865 sep->se_server, WEXITSTATUS(status));
866 else if (WIFSIGNALED(status))
867 syslog(LOG_WARNING,
868 "%s: exit signal %u",
869 sep->se_server, WTERMSIG(status));
870 sep->se_wait = 1;
871 #ifndef __minix
872 ev = allocchange();
873 EV_SET(ev, sep->se_fd, EVFILT_READ,
874 EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep);
875 #endif /* !__minix */
876 if (debug)
877 fprintf(stderr, "restored %s, fd %d\n",
878 sep->se_service, sep->se_fd);
883 static void
884 config(void)
886 struct servtab *sep, *cp, **sepp;
887 size_t n;
889 if (!setconfig()) {
890 syslog(LOG_ERR, "%s: %m", CONFIG);
891 return;
893 for (sep = servtab; sep != NULL; sep = sep->se_next)
894 sep->se_checked = 0;
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))
901 break;
902 if (sep != NULL) {
903 int i;
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
911 * wait.
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]);
921 #ifdef IPSEC
922 SWAP(char *, sep->se_policy, cp->se_policy);
923 #endif
924 SWAP(int, cp->se_type, sep->se_type);
925 SWAP(int, cp->se_max, sep->se_max);
926 #undef SWAP
927 if (isrpcservice(sep))
928 unregister_rpc(sep);
929 sep->se_rpcversl = cp->se_rpcversl;
930 sep->se_rpcversh = cp->se_rpcversh;
931 freeconfig(cp);
932 if (debug)
933 print_service("REDO", sep);
934 } else {
935 sep = enter(cp);
936 if (debug)
937 print_service("ADD ", sep);
939 sep->se_checked = 1;
941 switch (sep->se_family) {
942 case AF_LOCAL:
943 if (sep->se_fd != -1)
944 break;
945 n = strlen(sep->se_service);
946 if (n >= sizeof(sep->se_ctrladdr_un.sun_path)) {
947 syslog(LOG_ERR, "%s: address too long",
948 sep->se_service);
949 sep->se_checked = 0;
950 continue;
952 (void)unlink(sep->se_service);
953 strlcpy(sep->se_ctrladdr_un.sun_path,
954 sep->se_service, n);
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));
959 if (!ISMUX(sep))
960 setup(sep);
961 break;
962 case AF_INET:
963 #ifdef INET6
964 case AF_INET6:
965 #endif
967 struct addrinfo hints, *res;
968 char *host;
969 const char *port;
970 int error;
971 int s;
973 /* check if the family is supported */
974 s = socket(sep->se_family, SOCK_DGRAM, 0);
975 if (s < 0) {
976 syslog(LOG_WARNING,
977 "%s/%s: %s: the address family is not "
978 "supported by the kernel",
979 sep->se_service, sep->se_proto,
980 sep->se_hostaddr);
981 sep->se_checked = 0;
982 continue;
984 close(s);
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, "*"))
991 host = NULL;
992 else
993 host = sep->se_hostaddr;
994 if (isrpcservice(sep) || ISMUX(sep))
995 port = "0";
996 else
997 port = sep->se_service;
998 error = getaddrinfo(host, port, &hints, &res);
999 if (error) {
1000 if (error == EAI_SERVICE) {
1001 /* gai_strerror not friendly enough */
1002 syslog(LOG_WARNING, "%s/%s: "
1003 "unknown service",
1004 sep->se_service, sep->se_proto);
1005 } else {
1006 syslog(LOG_ERR, "%s/%s: %s: %s",
1007 sep->se_service, sep->se_proto,
1008 sep->se_hostaddr,
1009 gai_strerror(error));
1011 sep->se_checked = 0;
1012 continue;
1014 if (res->ai_next) {
1015 syslog(LOG_ERR,
1016 "%s/%s: %s: resolved to multiple addr",
1017 sep->se_service, sep->se_proto,
1018 sep->se_hostaddr);
1019 sep->se_checked = 0;
1020 freeaddrinfo(res);
1021 continue;
1023 memcpy(&sep->se_ctrladdr, res->ai_addr,
1024 res->ai_addrlen);
1025 if (ISMUX(sep)) {
1026 sep->se_fd = -1;
1027 freeaddrinfo(res);
1028 continue;
1030 sep->se_ctrladdr_size = res->ai_addrlen;
1031 freeaddrinfo(res);
1032 #ifdef RPC
1033 if (isrpcservice(sep)) {
1034 struct rpcent *rp;
1036 sep->se_rpcprog = atoi(sep->se_service);
1037 if (sep->se_rpcprog == 0) {
1038 rp = getrpcbyname(sep->se_service);
1039 if (rp == 0) {
1040 syslog(LOG_ERR,
1041 "%s/%s: unknown service",
1042 sep->se_service,
1043 sep->se_proto);
1044 sep->se_checked = 0;
1045 continue;
1047 sep->se_rpcprog = rp->r_number;
1049 if (sep->se_fd == -1 && !ISMUX(sep))
1050 setup(sep);
1051 if (sep->se_fd != -1)
1052 register_rpc(sep);
1053 } else
1054 #endif
1056 if (sep->se_fd >= 0)
1057 close_sep(sep);
1058 if (sep->se_fd == -1 && !ISMUX(sep))
1059 setup(sep);
1064 endconfig();
1066 * Purge anything not looked at above.
1068 sepp = &servtab;
1069 while ((sep = *sepp) != NULL) {
1070 if (sep->se_checked) {
1071 sepp = &sep->se_next;
1072 continue;
1074 *sepp = sep->se_next;
1075 if (sep->se_fd >= 0)
1076 close_sep(sep);
1077 if (isrpcservice(sep))
1078 unregister_rpc(sep);
1079 if (sep->se_family == AF_LOCAL)
1080 (void)unlink(sep->se_service);
1081 if (debug)
1082 print_service("FREE", sep);
1083 freeconfig(sep);
1084 free(sep);
1088 static void
1089 retry(void)
1091 struct servtab *sep;
1093 timingout = 0;
1094 for (sep = servtab; sep != NULL; sep = sep->se_next) {
1095 if (sep->se_fd == -1 && !ISMUX(sep)) {
1096 switch (sep->se_family) {
1097 case AF_LOCAL:
1098 case AF_INET:
1099 #ifdef INET6
1100 case AF_INET6:
1101 #endif
1102 setup(sep);
1103 if (sep->se_fd >= 0 && isrpcservice(sep))
1104 register_rpc(sep);
1105 break;
1111 static void
1112 goaway(void)
1114 struct servtab *sep;
1116 for (sep = servtab; sep != NULL; sep = sep->se_next) {
1117 if (sep->se_fd == -1)
1118 continue;
1120 switch (sep->se_family) {
1121 case AF_LOCAL:
1122 (void)unlink(sep->se_service);
1123 break;
1124 case AF_INET:
1125 #ifdef INET6
1126 case AF_INET6:
1127 #endif
1128 if (sep->se_wait == 1 && isrpcservice(sep))
1129 unregister_rpc(sep);
1130 break;
1132 (void)close(sep->se_fd);
1133 sep->se_fd = -1;
1135 exit(0);
1138 static void
1139 setup(struct servtab *sep)
1141 int on = 1;
1142 #ifdef INET6
1143 int off = 0;
1144 #endif
1145 #ifndef __minix
1146 struct kevent *ev;
1147 #endif /* !__minix */
1149 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1150 if (debug)
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);
1155 return;
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);
1161 close(sep->se_fd);
1162 sep->se_fd = -1;
1163 return;
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");
1173 #undef turnon
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",
1179 sep->se_sndbuf);
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",
1183 sep->se_rcvbuf);
1184 #ifdef INET6
1185 if (sep->se_family == AF_INET6) {
1186 int *v;
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");
1192 #endif
1193 #ifdef IPSEC
1194 if (ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy) < 0 &&
1195 sep->se_policy) {
1196 syslog(LOG_ERR, "%s/%s: ipsec setup failed",
1197 sep->se_service, sep->se_proto);
1198 (void)close(sep->se_fd);
1199 sep->se_fd = -1;
1200 return;
1202 #endif
1204 if (bind(sep->se_fd, &sep->se_ctrladdr,
1205 (socklen_t)sep->se_ctrladdr_size) < 0) {
1206 if (debug)
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);
1212 sep->se_fd = -1;
1213 if (!timingout) {
1214 timingout = 1;
1215 alarm(RETRYTIME);
1217 return;
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);
1229 #ifndef __minix
1230 ev = allocchange();
1231 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
1232 (intptr_t)sep);
1233 #endif /* !__minix */
1234 if (sep->se_fd > maxsock) {
1235 maxsock = sep->se_fd;
1236 if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
1237 bump_nofile();
1239 if (debug)
1240 fprintf(stderr, "registered %s on %d\n",
1241 sep->se_server, sep->se_fd);
1245 * Finish with a service and its socket.
1247 static void
1248 close_sep(struct servtab *sep)
1250 if (sep->se_fd >= 0) {
1251 (void) close(sep->se_fd);
1252 sep->se_fd = -1;
1254 sep->se_count = 0;
1257 static void
1258 register_rpc(struct servtab *sep)
1260 #ifdef RPC
1261 struct netbuf nbuf;
1262 struct sockaddr_storage ss;
1263 struct netconfig *nconf;
1264 socklen_t socklen;
1265 int n;
1267 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1268 syslog(LOG_ERR, "%s: getnetconfigent failed",
1269 sep->se_proto);
1270 return;
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);
1276 return;
1279 nbuf.buf = &ss;
1280 nbuf.len = ss.ss_len;
1281 nbuf.maxlen = sizeof (struct sockaddr_storage);
1282 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1283 if (debug)
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(""));
1293 #endif /* RPC */
1296 static void
1297 unregister_rpc(struct servtab *sep)
1299 #ifdef RPC
1300 int n;
1301 struct netconfig *nconf;
1303 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1304 syslog(LOG_ERR, "%s: getnetconfigent failed",
1305 sep->se_proto);
1306 return;
1309 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1310 if (debug)
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);
1317 #endif /* RPC */
1321 static struct servtab *
1322 enter(struct servtab *cp)
1324 struct servtab *sep;
1326 sep = malloc(sizeof (*sep));
1327 if (sep == NULL) {
1328 syslog(LOG_ERR, "Out of memory.");
1329 exit(1);
1331 *sep = *cp;
1332 sep->se_fd = -1;
1333 sep->se_rpcprog = -1;
1334 sep->se_next = servtab;
1335 servtab = sep;
1336 return (sep);
1339 FILE *fconfig = NULL;
1340 struct servtab serv;
1341 char line[LINE_MAX];
1342 char *defhost;
1343 #ifdef IPSEC
1344 static char *policy = NULL;
1345 #endif
1347 static int
1348 setconfig(void)
1350 if (defhost)
1351 free(defhost);
1352 defhost = newstr("*");
1353 #ifdef IPSEC
1354 if (policy)
1355 free(policy);
1356 policy = NULL;
1357 #endif
1358 if (fconfig != NULL) {
1359 fseek(fconfig, 0L, SEEK_SET);
1360 return (1);
1362 fconfig = fopen(CONFIG, "r");
1363 return (fconfig != NULL);
1366 static void
1367 endconfig(void)
1369 if (fconfig != NULL) {
1370 (void) fclose(fconfig);
1371 fconfig = NULL;
1373 if (defhost != NULL) {
1374 free(defhost);
1375 defhost = NULL;
1379 static struct servtab *
1380 getconfigent(void)
1382 struct servtab *sep = &serv;
1383 int argc, val;
1384 char *cp, *cp0, *arg, *buf0, *buf1, *sz0, *sz1;
1385 static char TCPMUX_TOKEN[] = "tcpmux/";
1386 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1387 char *hostdelim;
1389 more:
1390 while ((cp = nextline(fconfig)) != NULL) {
1391 #ifdef IPSEC
1392 /* lines starting with #@ is not a comment, but the policy */
1393 if (cp[0] == '#' && cp[1] == '@') {
1394 char *p;
1395 for (p = cp + 2; p && *p && isspace((unsigned char)*p); p++)
1397 if (*p == '\0') {
1398 if (policy)
1399 free(policy);
1400 policy = NULL;
1401 } else {
1402 if (ipsecsetup_test(p) < 0) {
1403 syslog(LOG_ERR,
1404 "%s: invalid ipsec policy \"%s\"",
1405 CONFIG, p);
1406 exit(1);
1407 } else {
1408 if (policy)
1409 free(policy);
1410 policy = newstr(p);
1414 #endif
1415 if (*cp == '#' || *cp == '\0')
1416 continue;
1417 break;
1419 if (cp == NULL)
1420 return (NULL);
1422 * clear the static buffer, since some fields (se_ctrladdr,
1423 * for example) don't get initialized here.
1425 memset(sep, 0, sizeof *sep);
1426 arg = skip(&cp);
1427 if (cp == NULL) {
1428 /* got an empty line containing just blanks/tabs. */
1429 goto more;
1431 /* Check for a host name. */
1432 hostdelim = strrchr(arg, ':');
1433 if (hostdelim) {
1434 *hostdelim = '\0';
1435 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1436 hostdelim[-1] = '\0';
1437 sep->se_hostaddr = newstr(arg + 1);
1438 } else
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.
1445 if (*arg == '\0') {
1446 arg = skip(&cp);
1447 if (cp == NULL) {
1448 free(defhost);
1449 defhost = sep->se_hostaddr;
1450 goto more;
1453 } else
1454 sep->se_hostaddr = newstr(defhost);
1455 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1456 char *c = arg + MUX_LEN;
1457 if (*c == '+') {
1458 sep->se_type = MUXPLUS_TYPE;
1459 c++;
1460 } else
1461 sep->se_type = MUX_TYPE;
1462 sep->se_service = newstr(c);
1463 } else {
1464 sep->se_service = newstr(arg);
1465 sep->se_type = NORM_TYPE;
1468 arg = sskip(&cp);
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, ':');
1476 if (accf) {
1477 if (accf != strrchr(arg, ':') ||/* more than one */
1478 *(accf + 1) == '\0') { /* nothing beyond */
1479 sep->se_socktype = -1;
1480 } else {
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;
1488 } else {
1489 accf_arg++;
1490 strlcpy(sep->se_accf.af_arg,
1491 accf_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;
1507 else
1508 sep->se_socktype = -1;
1510 arg = sskip(&cp);
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) \
1519 do { \
1520 syslog(LOG_ERR, "%s: malformed buffer size option `%s'", \
1521 sep->se_service, (arg)); \
1522 goto more; \
1523 /*NOTREACHED*/ \
1524 } while (/*CONSTCOND*/0)
1526 #define GETVAL(arg) \
1527 do { \
1528 if (!isdigit((unsigned char)*(arg))) \
1529 MALFORMED(arg); \
1530 val = (int)strtol((arg), &cp0, 10); \
1531 if (cp0 != NULL) { \
1532 if (cp0[1] != '\0') \
1533 MALFORMED((arg)); \
1534 if (cp0[0] == 'k') \
1535 val *= 1024; \
1536 if (cp0[0] == 'm') \
1537 val *= 1024 * 1024; \
1539 if (val < 1) { \
1540 syslog(LOG_ERR, "%s: invalid buffer size `%s'", \
1541 sep->se_service, (arg)); \
1542 goto more; \
1544 /*NOTREACHED*/ \
1545 } while (/*CONSTCOND*/0)
1547 #define ASSIGN(arg) \
1548 do { \
1549 if (strcmp((arg), "sndbuf") == 0) \
1550 sep->se_sndbuf = val; \
1551 else if (strcmp((arg), "rcvbuf") == 0) \
1552 sep->se_rcvbuf = val; \
1553 else \
1554 MALFORMED((arg)); \
1555 } while (/*CONSTCOND*/0)
1558 * Extract the send and receive buffer sizes before parsing
1559 * the protocol.
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. */
1565 if (ISMUX(sep)) {
1566 syslog(LOG_ERR, "%s: can't specify buffer sizes for "
1567 "tcpmux services", sep->se_service);
1568 goto more;
1571 /* Skip the , */
1572 *buf0++ = '\0';
1574 /* Check to see if another socket buffer size was specified. */
1575 if ((buf1 = strchr(buf0, ',')) != NULL) {
1576 /* Skip the , */
1577 *buf1++ = '\0';
1579 /* Make sure a 3rd one wasn't specified. */
1580 if (strchr(buf1, ',') != NULL) {
1581 syslog(LOG_ERR, "%s: too many buffer sizes",
1582 sep->se_service);
1583 goto more;
1586 /* Locate the size. */
1587 if ((sz1 = strchr(buf1, '=')) == NULL)
1588 MALFORMED(buf1);
1590 /* Skip the = */
1591 *sz1++ = '\0';
1594 /* Locate the size. */
1595 if ((sz0 = strchr(buf0, '=')) == NULL)
1596 MALFORMED(buf0);
1598 /* Skip the = */
1599 *sz0++ = '\0';
1601 GETVAL(sz0);
1602 ASSIGN(buf0);
1604 if (buf1 != NULL) {
1605 GETVAL(sz1);
1606 ASSIGN(buf1);
1610 #undef ASSIGN
1611 #undef GETVAL
1612 #undef MALFORMED
1614 if (strcmp(sep->se_proto, "unix") == 0) {
1615 sep->se_family = AF_LOCAL;
1616 } else {
1617 val = (int)strlen(sep->se_proto);
1618 if (!val) {
1619 syslog(LOG_ERR, "%s: invalid protocol specified",
1620 sep->se_service);
1621 goto more;
1623 val = sep->se_proto[val - 1];
1624 switch (val) {
1625 case '4': /*tcp4 or udp4*/
1626 sep->se_family = AF_INET;
1627 break;
1628 #ifdef INET6
1629 case '6': /*tcp6 or udp6*/
1630 sep->se_family = AF_INET6;
1631 break;
1632 #endif
1633 default:
1634 sep->se_family = AF_INET; /*will become AF_INET6*/
1635 break;
1637 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1638 #ifdef RPC
1639 char *cp1, *ccp;
1640 cp1 = strchr(sep->se_service, '/');
1641 if (cp1 == 0) {
1642 syslog(LOG_ERR, "%s: no rpc version",
1643 sep->se_service);
1644 goto more;
1646 *cp1++ = '\0';
1647 sep->se_rpcversl = sep->se_rpcversh =
1648 (int)strtol(cp1, &ccp, 0);
1649 if (ccp == cp1) {
1650 badafterall:
1651 syslog(LOG_ERR, "%s/%s: bad rpc version",
1652 sep->se_service, cp1);
1653 goto more;
1655 if (*ccp == '-') {
1656 cp1 = ccp + 1;
1657 sep->se_rpcversh = (int)strtol(cp1, &ccp, 0);
1658 if (ccp == cp1)
1659 goto badafterall;
1661 #else
1662 syslog(LOG_ERR, "%s: rpc services not suported",
1663 sep->se_service);
1664 goto more;
1665 #endif /* RPC */
1668 arg = sskip(&cp);
1670 char *cp1;
1671 if ((cp1 = strchr(arg, ':')) == NULL)
1672 cp1 = strchr(arg, '.');
1673 if (cp1 != NULL) {
1674 *cp1++ = '\0';
1675 sep->se_max = atoi(cp1);
1676 } else
1677 sep->se_max = TOOMANY;
1679 sep->se_wait = strcmp(arg, "wait") == 0;
1680 if (ISMUX(sep)) {
1682 * Silently enforce "nowait" for TCPMUX services since
1683 * they don't have an assigned port to listen on.
1685 sep->se_wait = 0;
1687 if (strncmp(sep->se_proto, "tcp", 3)) {
1688 syslog(LOG_ERR,
1689 "%s: bad protocol for tcpmux service %s",
1690 CONFIG, sep->se_service);
1691 goto more;
1693 if (sep->se_socktype != SOCK_STREAM) {
1694 syslog(LOG_ERR,
1695 "%s: bad socket type for tcpmux service %s",
1696 CONFIG, sep->se_service);
1697 goto more;
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) {
1708 struct biltin *bi;
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)
1713 break;
1714 if (bi->bi_service == 0) {
1715 syslog(LOG_ERR, "internal service %s unknown",
1716 sep->se_service);
1717 goto more;
1719 sep->se_bi = bi;
1720 sep->se_wait = bi->bi_wait;
1721 } else
1722 sep->se_bi = NULL;
1723 argc = 0;
1724 for (arg = skip(&cp); cp; arg = skip(&cp)) {
1725 if (argc < MAXARGV)
1726 sep->se_argv[argc++] = newstr(arg);
1728 while (argc <= MAXARGV)
1729 sep->se_argv[argc++] = NULL;
1730 #ifdef IPSEC
1731 sep->se_policy = policy ? newstr(policy) : NULL;
1732 #endif
1733 return (sep);
1736 static void
1737 freeconfig(struct servtab *cp)
1739 int i;
1741 if (cp->se_hostaddr)
1742 free(cp->se_hostaddr);
1743 if (cp->se_service)
1744 free(cp->se_service);
1745 if (cp->se_proto)
1746 free(cp->se_proto);
1747 if (cp->se_user)
1748 free(cp->se_user);
1749 /* Note: se_group is part of the newstr'ed se_user */
1750 if (cp->se_server)
1751 free(cp->se_server);
1752 for (i = 0; i < MAXARGV; i++)
1753 if (cp->se_argv[i])
1754 free(cp->se_argv[i]);
1755 #ifdef IPSEC
1756 if (cp->se_policy)
1757 free(cp->se_policy);
1758 #endif
1763 * Safe skip - if skip returns null, log a syntax error in the
1764 * configuration file and exit.
1766 static char *
1767 sskip(char **cpp)
1769 char *cp;
1771 cp = skip(cpp);
1772 if (cp == NULL) {
1773 syslog(LOG_ERR, "%s: syntax error", CONFIG);
1774 exit(1);
1776 return (cp);
1779 static char *
1780 skip(char **cpp)
1782 char *cp = *cpp;
1783 char *start;
1784 char quote;
1786 if (*cpp == NULL)
1787 return (NULL);
1789 again:
1790 while (*cp == ' ' || *cp == '\t')
1791 cp++;
1792 if (*cp == '\0') {
1793 int c;
1795 c = getc(fconfig);
1796 (void) ungetc(c, fconfig);
1797 if (c == ' ' || c == '\t')
1798 if ((cp = nextline(fconfig)) != NULL)
1799 goto again;
1800 *cpp = NULL;
1801 return (NULL);
1803 start = cp;
1804 quote = '\0';
1805 while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) {
1806 if (*cp == '\'' || *cp == '"') {
1807 if (quote && *cp != quote)
1808 cp++;
1809 else {
1810 if (quote)
1811 quote = '\0';
1812 else
1813 quote = *cp;
1814 memmove(cp, cp+1, strlen(cp));
1816 } else
1817 cp++;
1819 if (*cp != '\0')
1820 *cp++ = '\0';
1821 *cpp = cp;
1822 return (start);
1825 static char *
1826 nextline(FILE *fd)
1828 char *cp;
1830 if (fgets(line, (int)sizeof(line), fd) == NULL)
1831 return (NULL);
1832 cp = strchr(line, '\n');
1833 if (cp)
1834 *cp = '\0';
1835 return (line);
1838 static char *
1839 newstr(const char *cp)
1841 char *dp;
1842 if ((dp = strdup((cp != NULL) ? cp : "")) != NULL)
1843 return (dp);
1844 syslog(LOG_ERR, "strdup: %m");
1845 exit(1);
1846 /*NOTREACHED*/
1849 static void
1850 inetd_setproctitle(char *a, int s)
1852 socklen_t size;
1853 struct sockaddr_storage ss;
1854 char hbuf[NI_MAXHOST];
1855 const char *hp;
1856 struct sockaddr *sa;
1858 size = sizeof(ss);
1859 sa = (struct sockaddr *)(void *)&ss;
1860 if (getpeername(s, sa, &size) == 0) {
1861 if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
1862 0, niflags) != 0)
1863 hp = "?";
1864 else
1865 hp = hbuf;
1866 setproctitle("-%s [%s]", a, hp);
1867 } else
1868 setproctitle("-%s", a);
1871 static void
1872 bump_nofile(void)
1874 #define FD_CHUNK 32
1875 struct rlimit rl;
1877 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1878 syslog(LOG_ERR, "getrlimit: %m");
1879 return;
1881 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1882 if (rl.rlim_cur <= rlim_ofile_cur) {
1883 syslog(LOG_ERR,
1884 "bump_nofile: cannot extend file limit, max = %d",
1885 (int)rl.rlim_cur);
1886 return;
1889 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1890 syslog(LOG_ERR, "setrlimit: %m");
1891 return;
1894 rlim_ofile_cur = rl.rlim_cur;
1895 return;
1899 * Internet services provided internally by inetd:
1901 #define BUFSIZE 4096
1903 /* ARGSUSED */
1904 static void
1905 echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */
1907 char buffer[BUFSIZE];
1908 ssize_t i;
1910 inetd_setproctitle(sep->se_service, s);
1911 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1912 write(s, buffer, (size_t)i) > 0)
1916 /* ARGSUSED */
1917 static void
1918 echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */
1920 char buffer[BUFSIZE];
1921 ssize_t i;
1922 socklen_t size;
1923 struct sockaddr_storage ss;
1924 struct sockaddr *sa;
1926 sa = (struct sockaddr *)(void *)&ss;
1927 size = sizeof(ss);
1928 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1929 return;
1930 if (port_good_dg(sa))
1931 (void) sendto(s, buffer, (size_t)i, 0, sa, size);
1934 /* ARGSUSED */
1935 static void
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) ||
1942 errno == EINTR)
1946 /* ARGSUSED */
1947 static void
1948 discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */
1951 char buffer[BUFSIZE];
1953 (void) read(s, buffer, sizeof(buffer));
1956 #define LINESIZ 72
1957 char ring[128];
1958 char *endring;
1960 static void
1961 initring(void)
1963 int i;
1965 endring = ring;
1967 for (i = 0; i <= 128; ++i)
1968 if (isprint(i))
1969 *endring++ = i;
1972 /* ARGSUSED */
1973 static void
1974 chargen_stream(int s,struct servtab *sep) /* Character generator */
1976 size_t len;
1977 char *rs, text[LINESIZ+2];
1979 inetd_setproctitle(sep->se_service, s);
1981 if (!endring) {
1982 initring();
1983 rs = ring;
1986 text[LINESIZ] = '\r';
1987 text[LINESIZ + 1] = '\n';
1988 for (rs = ring;;) {
1989 if ((len = endring - rs) >= LINESIZ)
1990 memmove(text, rs, LINESIZ);
1991 else {
1992 memmove(text, rs, len);
1993 memmove(text + len, ring, LINESIZ - len);
1995 if (++rs == endring)
1996 rs = ring;
1997 if (write(s, text, sizeof(text)) != sizeof(text))
1998 break;
2002 /* ARGSUSED */
2003 static void
2004 chargen_dg(int s, struct servtab *sep) /* Character generator */
2006 struct sockaddr_storage ss;
2007 struct sockaddr *sa;
2008 static char *rs;
2009 size_t len;
2010 socklen_t size;
2011 char text[LINESIZ+2];
2013 if (endring == 0) {
2014 initring();
2015 rs = ring;
2018 sa = (struct sockaddr *)(void *)&ss;
2019 size = sizeof(ss);
2020 if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
2021 return;
2023 if (!port_good_dg(sa))
2024 return;
2026 if ((len = endring - rs) >= LINESIZ)
2027 memmove(text, rs, LINESIZ);
2028 else {
2029 memmove(text, rs, len);
2030 memmove(text + len, ring, LINESIZ - len);
2032 if (++rs == endring)
2033 rs = ring;
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.
2047 static uint32_t
2048 machtime(void)
2050 struct timeval tv;
2052 if (gettimeofday(&tv, NULL) < 0) {
2053 if (debug)
2054 fprintf(stderr, "Unable to get time of day\n");
2055 return (0);
2057 #define OFFSET ((uint32_t)25567 * 24*60*60)
2058 return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
2059 #undef OFFSET
2062 /* ARGSUSED */
2063 static void
2064 machtime_stream(int s, struct servtab *sep)
2066 uint32_t result;
2068 result = machtime();
2069 (void) write(s, &result, sizeof(result));
2072 /* ARGSUSED */
2073 void
2074 machtime_dg(int s, struct servtab *sep)
2076 uint32_t result;
2077 struct sockaddr_storage ss;
2078 struct sockaddr *sa;
2079 socklen_t size;
2081 sa = (struct sockaddr *)(void *)&ss;
2082 size = sizeof(ss);
2083 if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0)
2084 return;
2085 if (!port_good_dg(sa))
2086 return;
2087 result = machtime();
2088 (void)sendto(s, &result, sizeof(result), 0, sa, size);
2091 /* ARGSUSED */
2092 static void
2093 daytime_stream(int s,struct servtab *sep)
2094 /* Return human-readable time of day */
2096 char buffer[256];
2097 time_t clk;
2098 int len;
2100 clk = time((time_t *) 0);
2102 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
2103 (void) write(s, buffer, len);
2106 /* ARGSUSED */
2107 void
2108 daytime_dg(int s, struct servtab *sep)
2109 /* Return human-readable time of day */
2111 char buffer[256];
2112 time_t clk;
2113 struct sockaddr_storage ss;
2114 struct sockaddr *sa;
2115 socklen_t size;
2116 int len;
2118 clk = time((time_t *) 0);
2120 sa = (struct sockaddr *)(void *)&ss;
2121 size = sizeof(ss);
2122 if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
2123 return;
2124 if (!port_good_dg(sa))
2125 return;
2126 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
2127 (void) sendto(s, buffer, len, 0, sa, size);
2131 * print_service:
2132 * Dump relevant information to stderr
2134 static void
2135 print_service(const char *action, struct servtab *sep)
2138 if (isrpcservice(sep))
2139 fprintf(stderr,
2140 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2141 #ifdef IPSEC
2142 " policy=\"%s\""
2143 #endif
2144 "\n",
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
2149 #ifdef IPSEC
2150 , (sep->se_policy ? sep->se_policy : "")
2151 #endif
2153 else
2154 fprintf(stderr,
2155 "%s: %s proto=%s%s, wait.max=%d.%d, user:group=%s:%s builtin=%lx server=%s"
2156 #ifdef IPSEC
2157 " policy=%s"
2158 #endif
2159 "\n",
2160 action, sep->se_service,
2161 sep->se_type == FAITH_TYPE ? "faith/" : "",
2162 sep->se_proto,
2163 sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
2164 (long)sep->se_bi, sep->se_server
2165 #ifdef IPSEC
2166 , (sep->se_policy ? sep->se_policy : "")
2167 #endif
2171 static void
2172 usage(void)
2174 #ifdef LIBWRAP
2175 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2176 #else
2177 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2178 #endif
2179 exit(1);
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)
2191 int count = 0;
2192 ssize_t n;
2194 do {
2195 n = read(fd, buf, len-count);
2196 if (n == 0)
2197 return (count);
2198 if (n < 0)
2199 return (-1);
2200 while (--n >= 0) {
2201 if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2202 return (count);
2203 count++;
2204 buf++;
2206 } while (count < len);
2207 return (count);
2210 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */
2212 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)
2214 static void
2215 tcpmux(int ctrl, struct servtab *sep)
2217 char service[MAX_SERV_LEN+1];
2218 int len;
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");
2223 goto reject;
2225 service[len] = '\0';
2227 if (debug)
2228 fprintf(stderr, "tcpmux: someone wants %s\n", service);
2231 * Help is a required command, and lists available services,
2232 * one per line.
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) {
2238 if (!ISMUX(sep))
2239 continue;
2240 (void)write(ctrl, sep->se_service,
2241 strlen(sep->se_service));
2242 strwrite(ctrl, "\r\n");
2244 goto reject;
2247 /* Try matching a service in inetd.conf with the request */
2248 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2249 if (!ISMUX(sep))
2250 continue;
2251 if (!strcasecmp(service, sep->se_service)) {
2252 if (ISMUXPLUS(sep))
2253 strwrite(ctrl, "+Go\r\n");
2254 run_service(ctrl, sep, 1 /* forked */);
2255 return;
2258 strwrite(ctrl, "-Service not available\r\n");
2259 reject:
2260 _exit(1);
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
2268 static int
2269 port_good_dg(struct sockaddr *sa)
2271 struct in_addr in;
2272 struct sockaddr_in *sin;
2273 #ifdef INET6
2274 struct in6_addr *in6;
2275 struct sockaddr_in6 *sin6;
2276 #endif
2277 u_int16_t port;
2278 int i;
2279 char hbuf[NI_MAXHOST];
2281 switch (sa->sa_family) {
2282 case AF_INET:
2283 sin = (struct sockaddr_in *)(void *)sa;
2284 in.s_addr = ntohl(sin->sin_addr.s_addr);
2285 port = ntohs(sin->sin_port);
2286 #ifdef INET6
2287 v4chk:
2288 #endif
2289 if (IN_MULTICAST(in.s_addr))
2290 goto bad;
2291 switch ((in.s_addr & 0xff000000) >> 24) {
2292 case 0: case 127: case 255:
2293 goto bad;
2295 if (dg_broadcast(&in))
2296 goto bad;
2297 break;
2298 #ifdef INET6
2299 case AF_INET6:
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))
2304 goto bad;
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);
2308 goto v4chk;
2310 break;
2311 #endif
2312 default:
2313 /* XXX unsupported af, is it safe to assume it to be safe? */
2314 return (1);
2317 for (i = 0; bad_ports[i] != 0; i++) {
2318 if (port == bad_ports[i])
2319 goto bad;
2322 return (1);
2324 bad:
2325 if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
2326 niflags) != 0)
2327 strlcpy(hbuf, "?", sizeof(hbuf));
2328 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2329 hbuf, port);
2330 return (0);
2333 /* XXX need optimization */
2334 static int
2335 dg_broadcast(struct in_addr *in)
2337 struct ifaddrs *ifa, *ifap;
2338 struct sockaddr_in *sin;
2340 if (getifaddrs(&ifap) < 0)
2341 return (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)
2345 continue;
2346 sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
2347 if (sin->sin_addr.s_addr == in->s_addr) {
2348 freeifaddrs(ifap);
2349 return (1);
2352 freeifaddrs(ifap);
2353 return (0);
2356 #ifndef __minix
2357 static int
2358 my_kevent(const struct kevent *changelist, size_t nchanges,
2359 struct kevent *eventlist, size_t nevents)
2361 int result;
2363 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2364 NULL)) < 0)
2365 if (errno != EINTR) {
2366 syslog(LOG_ERR, "kevent: %m");
2367 exit(EXIT_FAILURE);
2370 return (result);
2373 static struct kevent *
2374 allocchange(void)
2376 if (changes == A_CNT(changebuf)) {
2377 (void) my_kevent(changebuf, A_CNT(changebuf), NULL, 0);
2378 changes = 0;
2381 return (&changebuf[changes++]);
2383 #endif /* !__minix */