summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2013-03-14 11:08:21 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2013-03-14 11:08:21 +0000
commit98260b7afb3fd0b4d628a36a1aa46eaebe4b72ca (patch)
tree3acca6237e111faf7672747c2ba30e4c91bc1228 /usr.sbin
parent924cf907d1385e13d36db11a3b3f5880fd8aa673 (diff)
tedu faithd(8), suggested by todd@ some weeks ago after a submission by
dhill. ok krw@, mikeb@, tedu@ (implicit)
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/Makefile4
-rw-r--r--usr.sbin/faithd/Makefile13
-rw-r--r--usr.sbin/faithd/README148
-rw-r--r--usr.sbin/faithd/faithd.8330
-rw-r--r--usr.sbin/faithd/faithd.c885
-rw-r--r--usr.sbin/faithd/faithd.h67
-rw-r--r--usr.sbin/faithd/ftp.c953
-rw-r--r--usr.sbin/faithd/prefix.c349
-rw-r--r--usr.sbin/faithd/prefix.h52
-rw-r--r--usr.sbin/faithd/tcp.c327
10 files changed, 2 insertions, 3126 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index d56781f62ce..147fd4d7c80 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.165 2012/11/21 12:21:10 kettenis Exp $
+# $OpenBSD: Makefile,v 1.166 2013/03/14 11:08:20 mpi Exp $
.include <bsd.own.mk>
SUBDIR= ac accton acpidump adduser amd apm apmd arp \
authpf bgpctl bgpd bind chroot config cron crunchgen dev_mkdb \
- dhcpd dhcrelay dvmrpctl dvmrpd edquota eeprom faithd fdformat \
+ dhcpd dhcrelay dvmrpctl dvmrpd edquota eeprom fdformat \
ftp-proxy fw_update gpioctl hostapd hotplugd httpd ifstated ikectl \
inetd iostat iscsictl iscsid kgmon kvm_mkdb \
ldapd ldapctl ldomctl ldomd ldpd ldpctl lpr mailwrapper map-mbone \
diff --git a/usr.sbin/faithd/Makefile b/usr.sbin/faithd/Makefile
deleted file mode 100644
index 139044900fe..00000000000
--- a/usr.sbin/faithd/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $OpenBSD: Makefile,v 1.5 2002/09/08 01:23:22 deraadt Exp $
-
-PROG= faithd
-SRCS= faithd.c tcp.c ftp.c prefix.c
-
-MAN= faithd.8
-
-#CPPFLAGS+= -DFAITH4
-
-LDADD+= -lutil
-DPADD+= ${LIBUTIL}
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/faithd/README b/usr.sbin/faithd/README
deleted file mode 100644
index 3e4e9e94f02..00000000000
--- a/usr.sbin/faithd/README
+++ /dev/null
@@ -1,148 +0,0 @@
-Configuring FAITH IPv6-to-IPv4 TCP relay
-
-Kazu Yamamoto and Jun-ichiro itojun Hagino
-$OpenBSD: README,v 1.13 2008/07/19 10:35:31 reyk Exp $
-$KAME: README,v 1.9 2002/05/09 14:10:06 itojun Exp $
-
-
-Introduction
-============
-
-FAITH is a IPv6-to-IPv4 TCP relay. It performs tcp relay just as some of
-firewall-oriented gateway does, but between IPv6 and IPv4 with address
-translation.
-TCP connections has to be made from IPv6 node to IPv4 node. FAITH will
-not relay connections for the opposite direction.
-To perform relays, FAITH daemon needs to be executed on a router between
-your local IPv6 site and outside IPv4 network. The daemon needs to be
-invoked per each TCP services (TCP port number).
-
- IPv4 node "dest" = 123.4.5.6
- |
- [[[[ outside IPv4 ocean ]]]]
- |
- node that runs FAITH-daemon (usually a router)
- |
- ==+=====+===+==== IPv6, or IPv4/v6 network in your site ^
- | | | connection
- clients IPv6 node "src" |
-
-You will have to allocate an IPv6 address prefix to map IPv4 addresses into.
-The following description uses 2001:db8:ffff:0000:: as example.
-Please use a prefix which belongs to your site.
-FAITH will make it possible to make a IPv6 TCP connection From IPv6 node
-"src", toward IPv4 node "dest", by specifying FAITH-mapped address
-2001:db8:ffff:0000::123.4.5.6
-(which is, 2001:db8:ffff:0000:0000:0000:7b04:0506).
-The address mapping can be performed by hand:-), by special nameserver on
-the network, or by special resolver on the source node.
-
-
-Setup
-=====
-
-The following example assumes:
-- You have assigned 2001:db8:ffff:0000:: as FAITH address prefix.
-- You are willing to provide IPv6-to IPv4 TCP relay for telnet.
-
-<<On the translating router on which faithd runs>>
-
-(1) If you have IPv6 TCP server for the "telnet" service, i.e. telnetd via
- inet6d, disable that daemon. Comment out the line from "inet6d.conf"
- and send the HUP signal to "inet6d".
-
-(2) Execute sysctl as root to enable FAITH support in the kernel.
-
- # sysctl net.inet6.ip6.keepfaith=1
-
-(3) Route packets toward FAITH prefix into "faith0" interface.
-
- # ifconfig faith0 up
- # route add -inet6 2001:db8:ffff:0000:: -prefixlen 64 ::1
- # route change -inet6 2001:db8:ffff:0000:: -prefixlen 64 -ifp faith0
-
-(4) Execute "faithd" by root as follows:
-
- # faithd telnet /usr/libexec/telnetd telnetd
-
- 1st argument is a service name you are willing to provide TCP relay.
- (it can be specified either by number "23" or by string "telnet")
- 2nd argument is a path name for local IPv6 TCP server. If there is a
- connection toward the router itself, this program will be invoked.
- 3rd and the following arguments are arguments for the local IPv6 TCP
- server. (3rd argument is typically the program name without its path.)
-
- More examples:
-
- # faithd ftpd /usr/libexec/ftpd ftpd -l
- # faithd sshd
-
-If inetd(8) on your platform have special support for faithd, it is possible
-to setup faithd services via inetd(8). Consult manpage for details.
-
-
-<<Routing>>
-
-(4) Make sure that packets whose destinations match the prefix can
-reach from the IPv6 host to the translating router.
-
-<<On the IPv6 host>>
-
-There are two ways to translate IPv4 address to IPv6 address:
- (a) Faked by DNS
- (b) Faked by /etc/hosts.
-
-(5.a) Install "newbie" and set up FAITH mode. See kit/ports/newbie.
-
-(5.b) Add an entry into /etc/hosts so that you can resolve hostname into
-faked IPv6 address. For example, add the following line for www.netbsd.org:
-
- 2001:db8:ffff:0000::140.160.140.252 www.netbsd.org
-
-<<On the translating router on which faithd runs.>>
-
-(6) To see if "faithd" works, watch "/var/log/daemon". Note: please
-setup "/etc/syslog.conf" so that LOG_DAEMON messages are to be stored
-in "/var/log/daemon".
-
- <e.g.>
- daemon.* /var/log/daemon
-
-
-Access control
-==============
-
-Since faithd implements TCP relaying service, it is critical to implement
-proper access control to cope with malicious use. Bad guy may try to
-use your relay router to circumvent access controls, or may try to
-abuse your network (like sending SPAMs from IPv4 address that belong to you).
-Install IPv6 packet filter directives that would reject traffic from
-unwanted source. If you are using inetd-based setup, you may be able to
-use access control mechanisms in inetd.
-
-
-Advanced configuration
-======================
-
-If you would like to restrict IPv4 destination for translation, you may
-want to do the following:
-
- # route add -inet6 2001:db8:ffff:0000::123.0.0.0 -prefixlen 104 ::1
- # route change -inet6 2001:db8:ffff:0000::123.0.0.0 -prefixlen 104 \
- -ifp faith0
-
-By this way, you can restrict IPv4 destination to 123.0.0.0/8.
-You may also want to reject packets toward 2001:db8:ffff:0000::/64 which
-is not in 2001:db8:ffff:0000::123.0.0.0/104. This will be left as excerside
-for the reader.
-
-By doing this, you will be able to provide your IPv4 web server to outside
-IPv6 customers, without risks of unwanted open relays.
-
- [[[[ IPv6 network outside ]]]] |
- | | connection
- node that runs FAITH-daemon (usually a router) v
- |
- ========+======== IPv4/v6 network in your site
- | (123.0.0.0/8)
- IPv4 web server
diff --git a/usr.sbin/faithd/faithd.8 b/usr.sbin/faithd/faithd.8
deleted file mode 100644
index 2dd68180ffb..00000000000
--- a/usr.sbin/faithd/faithd.8
+++ /dev/null
@@ -1,330 +0,0 @@
-.\" $OpenBSD: faithd.8,v 1.37 2012/09/26 16:19:44 jmc Exp $
-.\" $KAME: faithd.8,v 1.36 2002/05/09 13:59:16 itojun Exp $
-.\"
-.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. Neither the name of the project nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.Dd $Mdocdate: September 26 2012 $
-.Dt FAITHD 8
-.Os
-.Sh NAME
-.Nm faithd
-.Nd FAITH IPv6/v4 translator daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl dp
-.Op Fl f Ar configfile
-.Ar service
-.Op Ar serverpath Op Ar serverargs
-.\".Nm ""
-.Sh DESCRIPTION
-.Nm
-provides an IPv6-to-IPv4 TCP relay.
-.Nm
-must be used on an IPv4/v6 dual stack router.
-.Pp
-When
-.Nm
-receives
-.Tn TCPv6
-traffic,
-.Nm
-will relay the
-.Tn TCPv6
-traffic to
-.Tn TCPv4 .
-The destination for the relayed
-.Tn TCPv4
-connection is determined by the last 4 octets of the original
-.Tn IPv6
-destination.
-For example, if
-.Li 2001:db8:4819:ffff::
-is reserved for
-.Nm faithd ,
-and the
-.Tn TCPv6
-destination address is
-.Li 2001:db8:4819:ffff::0a01:0101 ,
-the traffic is relayed to IPv4 destination
-.Li 10.1.1.1 .
-.Pp
-To use the
-.Nm
-translation service,
-an IPv6 address prefix must be reserved for mapping IPv4 addresses onto.
-The kernel must be properly configured to route all the TCP connections
-toward the reserved IPv6 address prefix into the
-.Xr faith 4
-pseudo interface, by using the
-.Xr route 8
-command.
-Also,
-.Xr sysctl 8
-should be used to configure
-.Dv net.inet6.ip6.keepfaith
-to
-.Dv 1 .
-.Pp
-The router must be configured to capture all the TCP traffic
-for a given reserved
-.Tn IPv6
-address prefix, by using the
-.Xr route 8
-and
-.Xr sysctl 8
-commands.
-.Pp
-.Nm
-needs a special name-to-address translation logic, so that
-hostnames get resolved into a special
-.Tn IPv6
-address prefix.
-For small-scale installation, use
-.Xr hosts 5 .
-For large-scale installation, it is useful to have
-a DNS server with special address translation support.
-An implementation called
-.Nm totd
-is available
-at
-.Lk http://www.dillema.net/software/totd.html .
-Make sure you do not propagate translated DNS records to normal DNS cloud,
-it is highly harmful.
-.\".Ss Daemon mode
-When
-.Nm
-.\"is invoked as a stand-alone program,
-is invoked,
-.Nm
-will daemonize itself.
-.Nm
-will listen to
-.Tn TCPv6
-port
-.Ar service .
-If
-.Tn TCPv6
-traffic to port
-.Ar service
-is found, it relays the connection.
-.Pp
-Since
-.Nm
-listens to TCP port
-.Ar service ,
-it is not possible to run local TCP daemons for port
-.Ar service
-on the router, using
-.Xr inetd 8
-or other standard mechanisms.
-Local daemons can be run on the router
-by specifying a
-.Ar serverpath
-to
-.Nm faithd .
-.Nm
-will invoke a local daemon at
-.Ar serverpath
-if the destination address is a local interface address,
-and will perform translation to IPv4 TCP in other cases.
-.Ar serverargs
-can also be specified as
-arguments for the local daemon.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl d
-Debugging information will be generated using
-.Xr syslog 3 .
-.It Fl f Ar configfile
-Specify a configuration file for access control.
-See below.
-.It Fl p
-Use the privileged TCP port number as a source port,
-for an IPv4 TCP connection toward the final destination.
-For relaying
-.Xr ftp 1
-this flag is not necessary as special program code is supplied.
-.El
-.Pp
-.Nm
-will relay both normal and out-of-band TCP data.
-It is capable of emulating TCP half close as well.
-.Nm
-includes special support for protocols used by
-.Xr ftp 1 .
-When translating FTP protocol,
-.Nm
-translates network level addresses in
-.Li PORT/LPRT/EPRT
-and
-.Li PASV/LPSV/EPSV
-commands.
-.Pp
-Inactive sessions will be disconnected in 30 minutes,
-to avoid stale sessions from chewing up resources.
-This may be inappropriate for some of the services
-.Pq should this be configurable? .
-.Ss Access control
-To prevent malicious access,
-.Nm
-implements a simple address-based access control.
-With
-.Pa /etc/faithd.conf
-.Po
-or
-.Ar configfile
-specified by
-.Fl f
-.Pc ,
-.Nm
-will avoid relaying unwanted traffic.
-.Pa faithd.conf
-contains directives with the following format:
-.Bl -bullet
-.It
-.Xo
-.Ar src/slen Li deny Ar dst/dlen
-.Xc
-.Pp
-If the source address of a query matches
-.Ar src/slen ,
-and the translated destination address matches
-.Ar dst/dlen ,
-deny the connection.
-.It
-.Xo
-.Ar src/slen Li permit Ar dst/dlen
-.Xc
-.Pp
-If the source address of a query matches
-.Ar src/slen ,
-and the translated destination address matches
-.Ar dst/dlen ,
-permit the connection.
-.El
-.Pp
-The directives are evaluated in sequence,
-and the first matching entry will be effective.
-If there is no match
-.Pq the end of the ruleset has been reached ,
-the traffic is denied.
-.\".Pp
-.\"With inetd mode,
-.\"traffic may be filtered by using access control functionality in
-.\".Xr inetd 8 .
-.Sh RETURN VALUES
-.Nm
-exits with
-.Dv EXIT_SUCCESS
-.Pq 0
-on success, and
-.Dv EXIT_FAILURE
-.Pq 1
-on error.
-.Sh EXAMPLES
-Before invoking
-.Nm faithd ,
-the
-.Xr faith 4
-interface has to be configured properly:
-.Bd -literal -offset indent
-# sysctl net.inet6.ip6.accept_rtadv=0
-# sysctl net.inet6.ip6.forwarding=1
-# sysctl net.inet6.ip6.keepfaith=1
-# ifconfig faith0 up
-# route add -inet6 2001:db8:4819:ffff:: -prefixlen 96 ::1
-# route change -inet6 2001:db8:4819:ffff:: -prefixlen 96 -ifp faith0
-.Ed
-.\".Ss Daemon mode samples
-.Pp
-To translate
-.Li telnet
-service, and provide no local telnet service, invoke
-.Nm
-as follows:
-.Pp
-.Dl # faithd telnet
-.Pp
-Pass extra arguments to the local daemon:
-.Pp
-.Dl # faithd ftp /usr/libexec/ftpd ftpd -l
-.Ss Access control samples
-The following illustrates a simple
-.Pa faithd.conf
-setting.
-.Bd -literal -offset indent
-# Permit anyone from 2001:db8:ffff::/48 to use the translator,
-# to connect to the following IPv4 destinations:
-# - any location except 10.0.0.0/8 and 127.0.0.0/8.
-# Permit no other connections.
-#
-2001:db8:ffff::/48 deny 10.0.0.0/8
-2001:db8:ffff::/48 deny 127.0.0.0/8
-2001:db8:ffff::/48 permit 0.0.0.0/0
-.Ed
-.Sh SEE ALSO
-.Xr faith 4 ,
-.Xr route 8 ,
-.Xr sysctl 8
-.Sh STANDARDS
-.Rs
-.%A J. Hagino
-.%A K. Yamamoto
-.%D June 2001
-.%R RFC 3142
-.%T "An IPv6-to-IPv4 Transport Relay Translator"
-.Re
-.\"
-.Sh HISTORY
-The
-.Nm
-command first appeared in the WIDE Hydrangea IPv6 protocol stack kit.
-.\"
-.Sh SECURITY CONSIDERATIONS
-It is very insecure to use IP-address-based authentication
-for connections relayed by
-.Nm .
-.Pp
-Administrators are advised to limit access to
-.Nm
-using
-.Pa faithd.conf ,
-or by using IPv6 packet filters,
-to protect the
-.Nm
-service from malicious parties and avoid theft of service/bandwidth.
-IPv6 destination addresses can be limited by
-carefully configuring routing entries that point to
-.Xr faith 4 ,
-using
-.Xr route 8 .
-IPv6 source addresses need to be filtered using a packet filter.
-The documents listed in
-.Sx SEE ALSO
-have more discussions on this topic.
diff --git a/usr.sbin/faithd/faithd.c b/usr.sbin/faithd/faithd.c
deleted file mode 100644
index 8d0df583a06..00000000000
--- a/usr.sbin/faithd/faithd.c
+++ /dev/null
@@ -1,885 +0,0 @@
-/* $OpenBSD: faithd.c,v 1.31 2011/03/02 04:56:59 deraadt Exp $ */
-/* $KAME: faithd.c,v 1.58 2002/09/08 01:12:30 itojun Exp $ */
-
-/*
- * Copyright (C) 1997 and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * User level translator from IPv6 to IPv4.
- *
- * Usage: faithd [<port> <progpath> <arg1(progname)> <arg2> ...]
- * e.g. faithd telnet /usr/libexec/telnetd telnetd
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#ifdef __FreeBSD__
-#include <libutil.h>
-#endif
-
-#include <poll.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <termios.h>
-
-#include <net/if_types.h>
-#ifdef IFT_FAITH
-# define USE_ROUTE
-# include <net/if.h>
-# include <net/route.h>
-# include <net/if_dl.h>
-#endif
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <ifaddrs.h>
-
-#include "faithd.h"
-#include "prefix.h"
-
-char *serverpath = NULL;
-char *serverarg[MAXARGV + 1];
-static char *faithdname = NULL;
-char logname[BUFSIZ];
-char procname[BUFSIZ];
-
-struct myaddrs {
- struct myaddrs *next;
- struct sockaddr *addr;
-};
-struct myaddrs *myaddrs = NULL;
-
-static const char *service;
-#ifdef USE_ROUTE
-static int sockfd = 0;
-#endif
-int dflag = 0;
-static int pflag = 0;
-static int inetd = 0;
-static char *configfile = NULL;
-
-int main(int, char **);
-#if 0
-static int inetd_main(int, char **);
-#endif
-static int daemon_main(int, char **);
-static void play_service(int);
-static void play_child(int, struct sockaddr *);
-static int faith_prefix(struct sockaddr *);
-static int map6to4(struct sockaddr_in6 *, struct sockaddr_in *);
-static void sig_child(int);
-static void sig_terminate(int);
-static void start_daemon(void);
-static void exit_stderr(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-static void grab_myaddrs(void);
-static void free_myaddrs(void);
-static void update_myaddrs(void);
-static void usage(void);
-
-int
-main(int argc, char **argv)
-{
-
- /*
- * Initializing stuff
- */
-
- faithdname = strrchr(argv[0], '/');
- if (faithdname)
- faithdname++;
- else
- faithdname = argv[0];
-
-#if 0
- if (strcmp(faithdname, "faithd") != 0) {
- inetd = 1;
- return inetd_main(argc, argv);
- } else
- return daemon_main(argc, argv);
-#else
- return daemon_main(argc, argv);
-#endif
-}
-
-#if 0
-static int
-inetd_main(int argc, char **argv)
-{
- char path[MAXPATHLEN];
- struct sockaddr_storage me;
- struct sockaddr_storage from;
- socklen_t melen, fromlen;
- int i;
- int error;
- const int on = 1;
- char sbuf[NI_MAXSERV], snum[NI_MAXSERV];
-
- if (config_load(configfile) < 0 && configfile) {
- exit_failure("could not load config file");
- /*NOTREACHED*/
- }
-
- if (strrchr(argv[0], '/') == NULL)
- snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]);
- else
- snprintf(path, sizeof(path), "%s", argv[0]);
-
-#ifdef USE_ROUTE
- grab_myaddrs();
-
- sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
- if (sockfd < 0) {
- exit_failure("socket(PF_ROUTE): %s", strerror(errno));
- /*NOTREACHED*/
- }
-#endif
-
- melen = sizeof(me);
- if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0) {
- exit_failure("getsockname: %s", strerror(errno));
- /*NOTREACHED*/
- }
- fromlen = sizeof(from);
- if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
- exit_failure("getpeername: %s", strerror(errno));
- /*NOTREACHED*/
- }
- if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
- sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0)
- service = sbuf;
- else
- service = DEFAULT_PORT_NAME;
- if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
- snum, sizeof(snum), NI_NUMERICHOST) != 0)
- snprintf(snum, sizeof(snum), "?");
-
- snprintf(logname, sizeof(logname), "faithd %s", snum);
- snprintf(procname, sizeof(procname), "accepting port %s", snum);
- openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
-
- if (argc >= MAXARGV) {
- exit_failure("too many arguments");
- /*NOTREACHED*/
- }
- serverarg[0] = serverpath = path;
- for (i = 1; i < argc; i++)
- serverarg[i] = argv[i];
- serverarg[i] = NULL;
-
- error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on,
- sizeof(on));
- if (error < 0) {
- exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- play_child(STDIN_FILENO, (struct sockaddr *)&from);
- exit_failure("should not reach here");
- return 0; /*dummy!*/
-}
-#endif
-
-static int
-daemon_main(int argc, char **argv)
-{
- struct addrinfo hints, *res;
- int s_wld, error, i, serverargc, on = 1;
- int family = AF_INET6;
- int c;
-
- while ((c = getopt(argc, argv, "df:p")) != -1) {
- switch (c) {
- case 'd':
- dflag++;
- break;
- case 'f':
- configfile = optarg;
- break;
- case 'p':
- pflag++;
- break;
- default:
- usage();
- /*NOTREACHED*/
- }
- }
- argc -= optind;
- argv += optind;
-
- if (config_load(configfile) < 0 && configfile) {
- exit_failure("could not load config file");
- /*NOTREACHED*/
- }
-
-
-#ifdef USE_ROUTE
- grab_myaddrs();
-#endif
-
- switch (argc) {
- case 0:
- usage();
- /*NOTREACHED*/
- default:
- serverargc = argc - NUMARG;
- if (serverargc >= MAXARGV)
- exit_stderr("too many arguments");
-
- serverpath = strdup(argv[NUMPRG]);
- if (!serverpath)
- exit_stderr("not enough core");
- for (i = 0; i < serverargc; i++) {
- serverarg[i] = strdup(argv[i + NUMARG]);
- if (!serverarg[i])
- exit_stderr("not enough core");
- }
- serverarg[i] = NULL;
- /* fall throuth */
- case 1: /* no local service */
- service = argv[NUMPRT];
- break;
- }
-
- start_daemon();
-
- /*
- * Opening wild card socket for this service.
- */
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- error = getaddrinfo(NULL, service, &hints, &res);
- if (error)
- exit_failure("getaddrinfo: %s", gai_strerror(error));
-
- s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s_wld == -1)
- exit_failure("socket: %s", strerror(errno));
-
-#ifdef IPV6_FAITH
- if (res->ai_family == AF_INET6) {
- error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on));
- if (error == -1)
- exit_failure("setsockopt(IPV6_FAITH): %s",
- strerror(errno));
- }
-#endif
-
- error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- if (error == -1)
- exit_failure("setsockopt(SO_REUSEADDR): %s", strerror(errno));
-
- error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
- if (error == -1)
- exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
-
-#ifdef IPV6_V6ONLY
- error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
- if (error == -1)
- exit_failure("setsockopt(IPV6_V6ONLY): %s", strerror(errno));
-#endif
-
- error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
- if (error == -1)
- exit_failure("bind: %s", strerror(errno));
-
- error = listen(s_wld, 5);
- if (error == -1)
- exit_failure("listen: %s", strerror(errno));
-
-#ifdef USE_ROUTE
- sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
- if (sockfd < 0) {
- exit_failure("socket(PF_ROUTE): %s", strerror(errno));
- /*NOTREACHED*/
- }
-#endif
-
- /*
- * Everything is OK.
- */
-
- snprintf(logname, sizeof(logname), "faithd %s", service);
- snprintf(procname, sizeof(procname), "accepting port %s", service);
- openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
- syslog(LOG_INFO, "Starting faith daemon for %s port", service);
-
- play_service(s_wld);
- /* NOTREACHED */
- exit(1); /*pacify gcc*/
-}
-
-static void
-play_service(int s_wld)
-{
- struct sockaddr_storage srcaddr;
- socklen_t len;
- int s_src;
- pid_t child_pid;
- struct pollfd pfd[2];
- int error;
- int maxfd;
-
- /*
- * Wait, accept, fork, faith....
- */
-again:
- setproctitle("%s", procname);
-
- pfd[0].fd = s_wld;
- pfd[0].events = POLLIN;
- pfd[1].revents = 0;
- maxfd = 1;
-#ifdef USE_ROUTE
- if (sockfd) {
- pfd[1].fd = sockfd;
- pfd[1].events = POLLIN;
- maxfd = 2;
- }
-#endif
-
- error = poll(pfd, maxfd, INFTIM);
- if (error < 0) {
- if (errno == EINTR)
- goto again;
- exit_failure("poll: %s", strerror(errno));
- /*NOTREACHED*/
- }
-
-#ifdef USE_ROUTE
- if (pfd[1].revents & POLLIN) {
- update_myaddrs();
- }
-#endif
- if (pfd[0].revents & POLLIN) {
- len = sizeof(srcaddr);
- s_src = accept(s_wld, (struct sockaddr *)&srcaddr, &len);
- if (s_src < 0) {
- if (errno == ECONNABORTED)
- goto again;
- exit_failure("socket: %s", strerror(errno));
- /*NOTREACHED*/
- }
- if (srcaddr.ss_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&srcaddr)->sin6_addr)) {
- close(s_src);
- syslog(LOG_ERR, "connection from IPv4 mapped address?");
- goto again;
- }
-
- child_pid = fork();
-
- if (child_pid == 0) {
- /* child process */
- close(s_wld);
- closelog();
- openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
- play_child(s_src, (struct sockaddr *)&srcaddr);
- exit_failure("should never reach here");
- /*NOTREACHED*/
- } else {
- /* parent process */
- close(s_src);
- if (child_pid == -1)
- syslog(LOG_ERR, "can't fork");
- }
- }
- goto again;
-}
-
-static void
-play_child(int s_src, struct sockaddr *srcaddr)
-{
- struct sockaddr_storage dstaddr6;
- struct sockaddr_storage dstaddr4;
- char src[NI_MAXHOST];
- char dst6[NI_MAXHOST];
- char dst4[NI_MAXHOST];
- socklen_t len = sizeof(dstaddr6);
- int s_dst, error, hport, nresvport, on = 1;
- struct timeval tv;
- struct sockaddr *sa4;
- const struct config *conf;
-
- tv.tv_sec = 1;
- tv.tv_usec = 0;
-
- getnameinfo(srcaddr, srcaddr->sa_len,
- src, sizeof(src), NULL, 0, NI_NUMERICHOST);
- syslog(LOG_INFO, "accepted a client from %s", src);
-
- error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len);
- if (error == -1) {
- exit_failure("getsockname: %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- getnameinfo((struct sockaddr *)&dstaddr6, len,
- dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST);
- syslog(LOG_INFO, "the client is connecting to %s", dst6);
-
- if (!faith_prefix((struct sockaddr *)&dstaddr6)) {
- if (serverpath) {
- /*
- * Local service
- */
- syslog(LOG_INFO, "executing local %s", serverpath);
- if (!inetd) {
- dup2(s_src, 0);
- close(s_src);
- dup2(0, 1);
- dup2(0, 2);
- }
- execv(serverpath, serverarg);
- syslog(LOG_ERR, "execv %s: %s", serverpath,
- strerror(errno));
- _exit(EXIT_FAILURE);
- } else {
- close(s_src);
- exit_success("no local service for %s", service);
- }
- }
-
- /*
- * Act as a translator
- */
-
- switch (((struct sockaddr *)&dstaddr6)->sa_family) {
- case AF_INET6:
- if (!map6to4((struct sockaddr_in6 *)&dstaddr6,
- (struct sockaddr_in *)&dstaddr4)) {
- close(s_src);
- exit_failure("map6to4 failed");
- /*NOTREACHED*/
- }
- syslog(LOG_INFO, "translating from v6 to v4");
- break;
- default:
- close(s_src);
- exit_failure("family not supported");
- /*NOTREACHED*/
- }
-
- sa4 = (struct sockaddr *)&dstaddr4;
- getnameinfo(sa4, sa4->sa_len,
- dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST);
-
- conf = config_match(srcaddr, sa4);
- if (!conf || !conf->permit) {
- close(s_src);
- if (conf) {
- exit_failure("translation to %s not permitted for %s",
- dst4, prefix_string(&conf->match));
- /*NOTREACHED*/
- } else {
- exit_failure("translation to %s not permitted", dst4);
- /*NOTREACHED*/
- }
- }
-
- syslog(LOG_INFO, "the translator is connecting to %s", dst4);
-
- setproctitle("port %s, %s -> %s", service, src, dst4);
-
- if (sa4->sa_family == AF_INET6)
- hport = ntohs(((struct sockaddr_in6 *)&dstaddr4)->sin6_port);
- else /* AF_INET */
- hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port);
-
- if (pflag)
- s_dst = rresvport_af(&nresvport, sa4->sa_family);
- else
- s_dst = socket(sa4->sa_family, SOCK_STREAM, 0);
- if (s_dst < 0) {
- exit_failure("socket: %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- if (conf->src.a.ss_family) {
- if (bind(s_dst, (const struct sockaddr *)&conf->src.a,
- conf->src.a.ss_len) < 0) {
- exit_failure("bind: %s", strerror(errno));
- /*NOTREACHED*/
- }
- }
-
- error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
- if (error < 0) {
- exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
- if (error < 0) {
- exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno));
- /*NOTREACHED*/
- }
- error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
- if (error < 0) {
- exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- error = connect(s_dst, sa4, sa4->sa_len);
- if (error < 0) {
- exit_failure("connect: %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- switch (hport) {
- case FTP_PORT:
- ftp_relay(s_src, s_dst);
- break;
- default:
- tcp_relay(s_src, s_dst, service);
- break;
- }
-
- /* NOTREACHED */
-}
-
-/* 0: non faith, 1: faith */
-static int
-faith_prefix(struct sockaddr *dst)
-{
-#ifndef USE_ROUTE
- int mib[4], size;
- struct in6_addr faith_prefix;
- struct sockaddr_in6 *dst6 = (struct sockaddr_in *)dst;
-
- if (dst->sa_family != AF_INET6)
- return 0;
-
- mib[0] = CTL_NET;
- mib[1] = PF_INET6;
- mib[2] = IPPROTO_IPV6;
- mib[3] = IPV6CTL_FAITH_PREFIX;
- size = sizeof(struct in6_addr);
- if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0) {
- exit_failure("sysctl: %s", strerror(errno));
- /*NOTREACHED*/
- }
-
- if (memcmp(dst, &faith_prefix,
- sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) {
- return 1;
- }
- return 0;
-#else
- struct myaddrs *p;
- struct sockaddr_in6 *sin6;
- struct sockaddr_in *sin4;
- struct sockaddr_in6 *dst6;
- struct sockaddr_in *dst4;
- struct sockaddr_in dstmap;
-
- dst6 = (struct sockaddr_in6 *)dst;
- if (dst->sa_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&dst6->sin6_addr)) {
- /* ugly... */
- memset(&dstmap, 0, sizeof(dstmap));
- dstmap.sin_family = AF_INET;
- dstmap.sin_len = sizeof(dstmap);
- memcpy(&dstmap.sin_addr, &dst6->sin6_addr.s6_addr[12],
- sizeof(dstmap.sin_addr));
- dst = (struct sockaddr *)&dstmap;
- }
-
- dst6 = (struct sockaddr_in6 *)dst;
- dst4 = (struct sockaddr_in *)dst;
-
- for (p = myaddrs; p; p = p->next) {
- sin6 = (struct sockaddr_in6 *)p->addr;
- sin4 = (struct sockaddr_in *)p->addr;
-
- if (p->addr->sa_len != dst->sa_len ||
- p->addr->sa_family != dst->sa_family)
- continue;
-
- switch (dst->sa_family) {
- case AF_INET6:
- if (sin6->sin6_scope_id == dst6->sin6_scope_id &&
- IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &dst6->sin6_addr))
- return 0;
- break;
- case AF_INET:
- if (sin4->sin_addr.s_addr == dst4->sin_addr.s_addr)
- return 0;
- break;
- }
- }
- return 1;
-#endif
-}
-
-/* 0: non faith, 1: faith */
-static int
-map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4)
-{
- memset(dst4, 0, sizeof(*dst4));
- dst4->sin_len = sizeof(*dst4);
- dst4->sin_family = AF_INET;
- dst4->sin_port = dst6->sin6_port;
- memcpy(&dst4->sin_addr, &dst6->sin6_addr.s6_addr[12],
- sizeof(dst4->sin_addr));
-
- if (dst4->sin_addr.s_addr == INADDR_ANY ||
- dst4->sin_addr.s_addr == INADDR_BROADCAST ||
- IN_MULTICAST(ntohl(dst4->sin_addr.s_addr)))
- return 0;
- return 1;
-}
-
-
-static void
-sig_child(int sig)
-{
- int save_errno = errno, status;
- struct syslog_data sdata = SYSLOG_DATA_INIT;
- pid_t pid;
-
- while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
- if (pid && WEXITSTATUS(status))
- syslog_r(LOG_WARNING, &sdata,
- "child %ld exit status 0x%x", (long)pid, status);
- }
-
- errno = save_errno;
-}
-
-void
-sig_terminate(int sig)
-{
- struct syslog_data sdata = SYSLOG_DATA_INIT;
-
- syslog_r(LOG_INFO, &sdata, "Terminating faith daemon");
- _exit(EXIT_SUCCESS);
-}
-
-static void
-start_daemon(void)
-{
-#ifdef SA_NOCLDWAIT
- struct sigaction sa;
-#endif
-
- if (daemon(0, 0) == -1)
- exit_stderr("daemon: %s", strerror(errno));
-
-#ifdef SA_NOCLDWAIT
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = sig_child;
- sa.sa_flags = SA_NOCLDWAIT;
- sigemptyset(&sa.sa_mask);
- sigaction(SIGCHLD, &sa, (struct sigaction *)0);
-#else
- if (signal(SIGCHLD, sig_child) == SIG_ERR) {
- exit_failure("signal CHLD: %s", strerror(errno));
- /*NOTREACHED*/
- }
-#endif
-
- if (signal(SIGTERM, sig_terminate) == SIG_ERR) {
- exit_failure("signal TERM: %s", strerror(errno));
- /*NOTREACHED*/
- }
-}
-
-static void
-exit_stderr(const char *fmt, ...)
-{
- va_list ap;
- char buf[BUFSIZ];
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- fprintf(stderr, "%s\n", buf);
- exit(EXIT_FAILURE);
-}
-
-void
-exit_failure(const char *fmt, ...)
-{
- va_list ap;
- char buf[BUFSIZ];
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- syslog(LOG_ERR, "%s", buf);
- exit(EXIT_FAILURE);
-}
-
-void
-exit_success(const char *fmt, ...)
-{
- struct syslog_data sdata = SYSLOG_DATA_INIT;
- va_list ap;
- char buf[BUFSIZ];
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- syslog_r(LOG_INFO, &sdata, "%s", buf);
- _exit(EXIT_SUCCESS);
-}
-
-#ifdef USE_ROUTE
-static void
-grab_myaddrs()
-{
- struct ifaddrs *ifap, *ifa;
- struct myaddrs *p;
- struct sockaddr_in6 *sin6;
-
- if (getifaddrs(&ifap) != 0) {
- exit_failure("getifaddrs");
- /*NOTREACHED*/
- }
-
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- switch (ifa->ifa_addr->sa_family) {
- case AF_INET:
- case AF_INET6:
- break;
- default:
- continue;
- }
-
- p = (struct myaddrs *)malloc(sizeof(struct myaddrs) +
- ifa->ifa_addr->sa_len);
- if (!p) {
- exit_failure("not enough core");
- /*NOTREACHED*/
- }
- memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len);
- p->next = myaddrs;
- p->addr = (struct sockaddr *)(p + 1);
-#ifdef __KAME__
- if (ifa->ifa_addr->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)p->addr;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
- IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = 0;
- sin6->sin6_addr.s6_addr[3] = 0;
- }
- }
-#endif
- myaddrs = p;
- if (dflag) {
- char hbuf[NI_MAXHOST];
-
- getnameinfo(p->addr, p->addr->sa_len,
- hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
- syslog(LOG_INFO, "my interface: %s %s", hbuf,
- ifa->ifa_name);
- }
- }
-
- freeifaddrs(ifap);
-}
-
-static void
-free_myaddrs()
-{
- struct myaddrs *p, *q;
-
- p = myaddrs;
- while (p) {
- q = p->next;
- free(p);
- p = q;
- }
- myaddrs = NULL;
-}
-
-static void
-update_myaddrs()
-{
- char msg[BUFSIZ];
- int len;
- struct rt_msghdr *rtm;
-
- len = read(sockfd, msg, sizeof(msg));
- if (len < 0) {
- syslog(LOG_ERR, "read(PF_ROUTE) failed");
- return;
- }
- rtm = (struct rt_msghdr *)msg;
- if (len < 4 || len < rtm->rtm_msglen) {
- syslog(LOG_ERR, "read(PF_ROUTE) short read");
- return;
- }
- if (rtm->rtm_version != RTM_VERSION)
- return;
- switch (rtm->rtm_type) {
- case RTM_NEWADDR:
- case RTM_DELADDR:
- case RTM_IFINFO:
- break;
- default:
- return;
- }
- /* XXX more filters here? */
-
- syslog(LOG_INFO, "update interface address list");
- free_myaddrs();
- grab_myaddrs();
-}
-#endif /*USE_ROUTE*/
-
-static void
-usage()
-{
- fprintf(stderr,
- "usage: %s [-dp] [-f configfile] service [serverpath [serverargs]]\n",
- faithdname);
- exit(0);
-}
diff --git a/usr.sbin/faithd/faithd.h b/usr.sbin/faithd/faithd.h
deleted file mode 100644
index 633bd97b108..00000000000
--- a/usr.sbin/faithd/faithd.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* $OpenBSD: faithd.h,v 1.9 2007/08/21 22:18:41 krw Exp $ */
-/* $KAME: faithd.h,v 1.9 2002/05/09 09:41:24 itojun Exp $ */
-
-/*
- * Copyright (C) 1997 and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-extern char logname[];
-extern int dflag;
-
-extern void tcp_relay(int, int, const char *);
-extern void ftp_relay(int, int);
-extern int ftp_active(int, int, int *, int *);
-extern int ftp_passive(int, int, int *, int *);
-extern void exit_success(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-extern void exit_failure(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-
-#define DEFAULT_PORT_NAME "telnet"
-#define DEFAULT_DIR "/usr/libexec"
-#define DEFAULT_NAME "telnetd"
-#define DEFAULT_PATH (DEFAULT_DIR "/" DEFAULT_NAME)
-
-#define FTP_PORT 21
-
-#define RETURN_SUCCESS 0
-#define RETURN_FAILURE 1
-
-#define YES 1
-#define NO 0
-
-#define MSS 2048
-#define MAXARGV 20
-
-#define NUMPRT 0
-#define NUMPRG 1
-#define NUMARG 2
-
-#define UC(b) (((int)b)&0xff)
-
-#define FAITH_TIMEOUT (30 * 60) /*second*/
diff --git a/usr.sbin/faithd/ftp.c b/usr.sbin/faithd/ftp.c
deleted file mode 100644
index 474521f0a33..00000000000
--- a/usr.sbin/faithd/ftp.c
+++ /dev/null
@@ -1,953 +0,0 @@
-/* $OpenBSD: ftp.c,v 1.15 2007/03/20 04:00:32 tedu Exp $ */
-/* $KAME: ftp.c,v 1.20 2002/09/08 01:12:30 itojun Exp $ */
-
-/*
- * Copyright (C) 1997 and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <poll.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include "faithd.h"
-
-static char rbuf[MSS];
-static char sbuf[MSS];
-static int passivemode = 0;
-static int wport4 = -1; /* listen() to active */
-static int wport6 = -1; /* listen() to passive */
-static int port4 = -1; /* active: inbound passive: outbound */
-static int port6 = -1; /* active: outbound passive: inbound */
-static struct sockaddr_storage data4; /* server data address */
-static struct sockaddr_storage data6; /* client data address */
-static int epsvall = 0;
-
-enum state { NONE, LPRT, EPRT, LPSV, EPSV };
-
-static int ftp_activeconn(void);
-static int ftp_passiveconn(void);
-static int ftp_copy(int, int);
-static int ftp_copyresult(int, int, enum state);
-static int ftp_copycommand(int, int, enum state *);
-
-void
-ftp_relay(int ctl6, int ctl4)
-{
- struct pollfd pfd[6];
- int error;
- enum state state = NONE;
- struct timeval tv;
-
- syslog(LOG_INFO, "starting ftp control connection");
-
- for (;;) {
- int maxfd = 0;
-
- pfd[0].fd = ctl4;
- pfd[0].events = POLLIN;
- pfd[1].fd = ctl6;
- pfd[1].events = POLLIN;
-
- maxfd = (ctl6 > maxfd) ? ctl6 : maxfd;
- if (0 <= port4) {
- pfd[2].fd = port4;
- pfd[2].events = POLLIN;
- } else
- pfd[2].fd = -1;
-
- if (0 <= port6) {
- pfd[3].fd = port6;
- pfd[3].events = POLLIN;
- } else
- pfd[3].fd = -1;
-#if 0
- if (0 <= wport4) {
- pfd[4].fd = wport4;
- pfd[4].events = POLLIN;
- } else
- pfd[4].fd = -1;
- if (0 <= wport6) {
- pfd[5].fd = wport6;
- pfd[5].events = POLLIN;
- } else
- pfd[5].fd = -1;
-#endif
- tv.tv_sec = FAITH_TIMEOUT;
- tv.tv_usec = 0;
-
- error = poll(pfd, 6, FAITH_TIMEOUT * 1000);
- if (error == -1)
- exit_failure("poll: %s", strerror(errno));
- else if (error == 0)
- exit_failure("connection timeout");
-
- /*
- * The order of the following checks does (slightly) matter.
- * It is important to visit all checks (do not use "continue"),
- * otherwise some of the pipe may become full and we cannot
- * relay correctly.
- */
- if (pfd[1].revents & POLLIN) {
- /*
- * copy control connection from the client.
- * command translation is necessary.
- */
- error = ftp_copycommand(ctl6, ctl4, &state);
-
- if (error < 0)
- goto bad;
- else if (error == 0) {
- close(ctl4);
- close(ctl6);
- exit_success("terminating ftp control connection");
- /*NOTREACHED*/
- }
- }
- if (pfd[1].revents & POLLIN) {
- /*
- * copy control connection from the server
- * translation of result code is necessary.
- */
- error = ftp_copyresult(ctl4, ctl6, state);
-
- if (error < 0)
- goto bad;
- else if (error == 0) {
- close(ctl4);
- close(ctl6);
- exit_success("terminating ftp control connection");
- /*NOTREACHED*/
- }
- }
- if (0 <= port4 && 0 <= port6 && (pfd[2].revents & POLLIN)) {
- /*
- * copy data connection.
- * no special treatment necessary.
- */
- if (pfd[2].revents & POLLIN)
- error = ftp_copy(port4, port6);
- switch (error) {
- case -1:
- goto bad;
- case 0:
- close(port4);
- close(port6);
- port4 = port6 = -1;
- syslog(LOG_INFO, "terminating data connection");
- break;
- default:
- break;
- }
- }
- if (0 <= port4 && 0 <= port6 && (pfd[3].revents & POLLIN)) {
- /*
- * copy data connection.
- * no special treatment necessary.
- */
- if (pfd[3].revents & POLLIN)
- error = ftp_copy(port6, port4);
- switch (error) {
- case -1:
- goto bad;
- case 0:
- close(port4);
- close(port6);
- port4 = port6 = -1;
- syslog(LOG_INFO, "terminating data connection");
- break;
- default:
- break;
- }
- }
-#if 0
- if (wport4 && (pfd[4].revents & POLLIN)) {
- /*
- * establish active data connection from the server.
- */
- ftp_activeconn();
- }
- if (wport6 && (pfd[5].revents & POLLIN)) {
- /*
- * establish passive data connection from the client.
- */
- ftp_passiveconn();
- }
-#endif
- }
-
- bad:
- exit_failure("%s", strerror(errno));
-}
-
-static int
-ftp_activeconn()
-{
- socklen_t n;
- int error;
- struct pollfd pfd[1];
- struct sockaddr *sa;
-
- /* get active connection from server */
- pfd[0].fd = wport4;
- pfd[0].events = POLLIN;
- n = sizeof(data4);
- if (poll(pfd, 1, 120 * 1000) == 0
- || (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) {
- close(wport4);
- wport4 = -1;
- syslog(LOG_INFO, "active mode data connection failed");
- return -1;
- }
-
- /* ask active connection to client */
- sa = (struct sockaddr *)&data6;
- port6 = socket(sa->sa_family, SOCK_STREAM, 0);
- if (port6 == -1) {
- close(port4);
- close(wport4);
- port4 = wport4 = -1;
- syslog(LOG_INFO, "active mode data connection failed");
- return -1;
- }
- error = connect(port6, sa, sa->sa_len);
- if (error < 0) {
- close(port6);
- close(port4);
- close(wport4);
- port6 = port4 = wport4 = -1;
- syslog(LOG_INFO, "active mode data connection failed");
- return -1;
- }
-
- syslog(LOG_INFO, "active mode data connection established");
- return 0;
-}
-
-static int
-ftp_passiveconn()
-{
- socklen_t len;
- int error;
- struct pollfd pfd[1];
- struct sockaddr *sa;
-
- /* get passive connection from client */
- pfd[0].fd = wport6;
- pfd[0].events = POLLIN;
- len = sizeof(data6);
- if (poll(pfd, 1, 120 * 1000) == 0
- || (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0) {
- close(wport6);
- wport6 = -1;
- syslog(LOG_INFO, "passive mode data connection failed");
- return -1;
- }
-
- /* ask passive connection to server */
- sa = (struct sockaddr *)&data4;
- port4 = socket(sa->sa_family, SOCK_STREAM, 0);
- if (port4 == -1) {
- close(wport6);
- close(port6);
- wport6 = port6 = -1;
- syslog(LOG_INFO, "passive mode data connection failed");
- return -1;
- }
- error = connect(port4, sa, sa->sa_len);
- if (error < 0) {
- close(wport6);
- close(port4);
- close(port6);
- wport6 = port4 = port6 = -1;
- syslog(LOG_INFO, "passive mode data connection failed");
- return -1;
- }
-
- syslog(LOG_INFO, "passive mode data connection established");
- return 0;
-}
-
-static int
-ftp_copy(int src, int dst)
-{
- int error, atmark, n;
-
- /* OOB data handling */
- error = ioctl(src, SIOCATMARK, &atmark);
- if (error != -1 && atmark == 1) {
- n = read(src, rbuf, 1);
- if (n == -1)
- goto bad;
- send(dst, rbuf, n, MSG_OOB);
-#if 0
- n = read(src, rbuf, sizeof(rbuf));
- if (n == -1)
- goto bad;
- write(dst, rbuf, n);
- return n;
-#endif
- }
-
- n = read(src, rbuf, sizeof(rbuf));
- switch (n) {
- case -1:
- case 0:
- return n;
- default:
- write(dst, rbuf, n);
- return n;
- }
-
- bad:
- exit_failure("%s", strerror(errno));
- /*NOTREACHED*/
- return 0; /* to make gcc happy */
-}
-
-static int
-ftp_copyresult(int src, int dst, enum state state)
-{
- int error, atmark, n;
- socklen_t len;
- char *param;
- int code;
- char *a, *p;
- int i;
-
- /* OOB data handling */
- error = ioctl(src, SIOCATMARK, &atmark);
- if (error != -1 && atmark == 1) {
- n = read(src, rbuf, 1);
- if (n == -1)
- goto bad;
- send(dst, rbuf, n, MSG_OOB);
-#if 0
- n = read(src, rbuf, sizeof(rbuf));
- if (n == -1)
- goto bad;
- write(dst, rbuf, n);
- return n;
-#endif
- }
-
- n = read(src, rbuf, sizeof(rbuf));
- if (n <= 0)
- return n;
- rbuf[n] = '\0';
-
- /*
- * parse argument
- */
- p = rbuf;
- for (i = 0; i < 3; i++) {
- if (!isdigit(*p)) {
- /* invalid reply */
- write(dst, rbuf, n);
- return n;
- }
- p++;
- }
- if (!isspace(*p)) {
- /* invalid reply */
- write(dst, rbuf, n);
- return n;
- }
- code = atoi(rbuf);
- param = p;
- /* param points to first non-command token, if any */
- while (isspace(*param))
- param++;
- if (!*param)
- param = NULL;
-
- switch (state) {
- case NONE:
- if (!passivemode && rbuf[0] == '1') {
- if (ftp_activeconn() < 0) {
- n = snprintf(rbuf, sizeof(rbuf),
- "425 Cannot open data connetion\r\n");
- if (n < 0 || n >= sizeof(rbuf))
- n = 0;
- }
- }
- if (n)
- write(dst, rbuf, n);
- return n;
- case LPRT:
- case EPRT:
- /* expecting "200 PORT command successful." */
- if (code == 200) {
- p = strstr(rbuf, "PORT");
- if (p) {
- p[0] = (state == LPRT) ? 'L' : 'E';
- p[1] = 'P';
- }
- } else {
- close(wport4);
- wport4 = -1;
- }
- write(dst, rbuf, n);
- return n;
- case LPSV:
- case EPSV:
- /*
- * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)"
- * (in some cases result comes without paren)
- */
- if (code != 227) {
-passivefail0:
- close(wport6);
- wport6 = -1;
- write(dst, rbuf, n);
- return n;
- }
-
- {
- unsigned int ho[4], po[2];
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
- u_short port;
-
- /*
- * PASV result -> LPSV/EPSV result
- */
- p = param;
- while (*p && *p != '(' && !isdigit(*p)) /*)*/
- p++;
- if (!*p)
- goto passivefail0; /*XXX*/
- if (*p == '(') /*)*/
- p++;
- n = sscanf(p, "%u,%u,%u,%u,%u,%u",
- &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]);
- if (n != 6)
- goto passivefail0; /*XXX*/
-
- /* keep PORT parameter */
- memset(&data4, 0, sizeof(data4));
- sin = (struct sockaddr_in *)&data4;
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = 0;
- for (n = 0; n < 4; n++) {
- sin->sin_addr.s_addr |=
- htonl((ho[n] & 0xff) << ((3 - n) * 8));
- }
- sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
-
- /* get ready for passive data connection */
- memset(&data6, 0, sizeof(data6));
- sin6 = (struct sockaddr_in6 *)&data6;
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- wport6 = socket(sin6->sin6_family, SOCK_STREAM, 0);
- if (wport6 == -1) {
-passivefail:
- n = snprintf(sbuf, sizeof(sbuf),
- "500 could not translate from PASV\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
-#ifdef IPV6_FAITH
- {
- int on = 1;
- error = setsockopt(wport6, IPPROTO_IPV6, IPV6_FAITH,
- &on, sizeof(on));
- if (error == -1)
- exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno));
- }
-#endif
- error = bind(wport6, (struct sockaddr *)sin6, sin6->sin6_len);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail;
- }
- error = listen(wport6, 1);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail;
- }
-
- /* transmit LPSV or EPSV */
- /*
- * addr from dst, port from wport6
- */
- len = sizeof(data6);
- error = getsockname(wport6, (struct sockaddr *)&data6, &len);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail;
- }
- sin6 = (struct sockaddr_in6 *)&data6;
- port = sin6->sin6_port;
-
- len = sizeof(data6);
- error = getsockname(dst, (struct sockaddr *)&data6, &len);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail;
- }
- sin6 = (struct sockaddr_in6 *)&data6;
- sin6->sin6_port = port;
-
- if (state == LPSV) {
- a = (char *)&sin6->sin6_addr;
- p = (char *)&sin6->sin6_port;
- n = snprintf(sbuf, sizeof(sbuf),
-"228 Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n",
- 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
- UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
- UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
- UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
- 2, UC(p[0]), UC(p[1]));
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(dst, sbuf, n);
- passivemode = 1;
- return n;
- } else {
- n = snprintf(sbuf, sizeof(sbuf),
-"229 Entering Extended Passive Mode (|||%d|)\r\n",
- ntohs(sin6->sin6_port));
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(dst, sbuf, n);
- passivemode = 1;
- return n;
- }
- }
- }
-
- bad:
- exit_failure("%s", strerror(errno));
- /*NOTREACHED*/
- return 0; /* to make gcc happy */
-}
-
-static int
-ftp_copycommand(int src, int dst, enum state *state)
-{
- int error, atmark, n;
- socklen_t len;
- unsigned int af, hal, ho[16], pal, po[2];
- char *a, *p, *q;
- char cmd[5], *param;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
- enum state nstate;
- char ch;
- int i;
-
- /* OOB data handling */
- error = ioctl(src, SIOCATMARK, &atmark);
- if (error != -1 && atmark == 1) {
- n = read(src, rbuf, 1);
- if (n == -1)
- goto bad;
- send(dst, rbuf, n, MSG_OOB);
-#if 0
- n = read(src, rbuf, sizeof(rbuf));
- if (n == -1)
- goto bad;
- write(dst, rbuf, n);
- return n;
-#endif
- }
-
- n = read(src, rbuf, sizeof(rbuf));
- if (n <= 0)
- return n;
- rbuf[n] = '\0';
-
- if (n < 4) {
- write(dst, rbuf, n);
- return n;
- }
-
- /*
- * parse argument
- */
- p = rbuf;
- q = cmd;
- for (i = 0; i < 4; i++) {
- if (!isalpha(*p)) {
- /* invalid command */
- write(dst, rbuf, n);
- return n;
- }
- *q++ = islower(*p) ? toupper(*p) : *p;
- p++;
- }
- if (!isspace(*p)) {
- /* invalid command */
- write(dst, rbuf, n);
- return n;
- }
- *q = '\0';
- param = p;
- /* param points to first non-command token, if any */
- while (isspace(*param))
- param++;
- if (!*param)
- param = NULL;
-
- *state = NONE;
-
- if (strcmp(cmd, "LPRT") == 0 && param) {
- /*
- * LPRT -> PORT
- */
- nstate = LPRT;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- if (epsvall) {
- n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
- cmd);
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
-
- n = sscanf(param,
-"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
- &af, &hal, &ho[0], &ho[1], &ho[2], &ho[3],
- &ho[4], &ho[5], &ho[6], &ho[7],
- &ho[8], &ho[9], &ho[10], &ho[11],
- &ho[12], &ho[13], &ho[14], &ho[15],
- &pal, &po[0], &po[1]);
- if (n != 21 || af != 6 || hal != 16|| pal != 2) {
- n = snprintf(sbuf, sizeof(sbuf),
- "501 illegal parameter to LPRT\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
-
- /* keep LPRT parameter */
- memset(&data6, 0, sizeof(data6));
- sin6 = (struct sockaddr_in6 *)&data6;
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- for (n = 0; n < 16; n++)
- sin6->sin6_addr.s6_addr[n] = ho[n];
- sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
-
-sendport:
- /* get ready for active data connection */
- len = sizeof(data4);
- error = getsockname(dst, (struct sockaddr *)&data4, &len);
- if (error == -1) {
-lprtfail:
- n = snprintf(sbuf, sizeof(sbuf),
- "500 could not translate to PORT\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
- if (((struct sockaddr *)&data4)->sa_family != AF_INET)
- goto lprtfail;
- sin = (struct sockaddr_in *)&data4;
- sin->sin_port = 0;
- wport4 = socket(sin->sin_family, SOCK_STREAM, 0);
- if (wport4 == -1)
- goto lprtfail;
- error = bind(wport4, (struct sockaddr *)sin, sin->sin_len);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto lprtfail;
- }
- error = listen(wport4, 1);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto lprtfail;
- }
-
- /* transmit PORT */
- len = sizeof(data4);
- error = getsockname(wport4, (struct sockaddr *)&data4, &len);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto lprtfail;
- }
- if (((struct sockaddr *)&data4)->sa_family != AF_INET) {
- close(wport4);
- wport4 = -1;
- goto lprtfail;
- }
- sin = (struct sockaddr_in *)&data4;
- a = (char *)&sin->sin_addr;
- p = (char *)&sin->sin_port;
- n = snprintf(sbuf, sizeof(sbuf), "PORT %d,%d,%d,%d,%d,%d\r\n",
- UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
- UC(p[0]), UC(p[1]));
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(dst, sbuf, n);
- *state = nstate;
- passivemode = 0;
- return n;
- } else if (strcmp(cmd, "EPRT") == 0 && param) {
- /*
- * EPRT -> PORT
- */
- char *afp, *hostp, *portp;
- struct addrinfo hints, *res;
-
- nstate = EPRT;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- if (epsvall) {
- n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
- cmd);
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
-
- p = param;
- ch = *p++; /* boundary character */
- afp = p;
- while (*p && *p != ch)
- p++;
- if (!*p) {
-eprtparamfail:
- n = snprintf(sbuf, sizeof(sbuf),
- "501 illegal parameter to EPRT\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
- *p++ = '\0';
- hostp = p;
- while (*p && *p != ch)
- p++;
- if (!*p)
- goto eprtparamfail;
- *p++ = '\0';
- portp = p;
- while (*p && *p != ch)
- p++;
- if (!*p)
- goto eprtparamfail;
- *p++ = '\0';
-
- n = sscanf(afp, "%d", &af);
- if (n != 1 || af != 2) {
- n = snprintf(sbuf, sizeof(sbuf),
- "501 unsupported address family to EPRT\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- error = getaddrinfo(hostp, portp, &hints, &res);
- if (error) {
- n = snprintf(sbuf, sizeof(sbuf),
- "501 EPRT: %s\r\n", gai_strerror(error));
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
- if (res->ai_next) {
- n = snprintf(sbuf, sizeof(sbuf),
- "501 EPRT: %s resolved to multiple addresses\r\n", hostp);
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- freeaddrinfo(res);
- return n;
- }
-
- memcpy(&data6, res->ai_addr, res->ai_addrlen);
-
- freeaddrinfo(res);
- goto sendport;
- } else if (strcmp(cmd, "LPSV") == 0 && !param) {
- /*
- * LPSV -> PASV
- */
- nstate = LPSV;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- if (epsvall) {
- n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
- cmd);
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- }
-
- /* transmit PASV */
- n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(dst, sbuf, n);
- *state = LPSV;
- passivemode = 0; /* to be set to 1 later */
- return n;
- } else if (strcmp(cmd, "EPSV") == 0 && !param) {
- /*
- * EPSV -> PASV
- */
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(dst, sbuf, n);
- *state = EPSV;
- passivemode = 0; /* to be set to 1 later */
- return n;
- } else if (strcmp(cmd, "EPSV") == 0 && param
- && strncasecmp(param, "ALL", 3) == 0 && isspace(param[3])) {
- /*
- * EPSV ALL
- */
- epsvall = 1;
- n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- } else if (strcmp(cmd, "PORT") == 0 || strcmp(cmd, "PASV") == 0) {
- /*
- * reject PORT/PASV
- */
- n = snprintf(sbuf, sizeof(sbuf), "502 %s not implemented.\r\n", cmd);
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- return n;
- } else if (passivemode
- && (strcmp(cmd, "STOR") == 0
- || strcmp(cmd, "STOU") == 0
- || strcmp(cmd, "RETR") == 0
- || strcmp(cmd, "LIST") == 0
- || strcmp(cmd, "NLST") == 0
- || strcmp(cmd, "APPE") == 0)) {
- /*
- * commands with data transfer. need to care about passive
- * mode data connection.
- */
-
- if (ftp_passiveconn() < 0) {
- n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n");
- if (n < 0 || n >= sizeof(sbuf))
- n = 0;
- if (n)
- write(src, sbuf, n);
- } else {
- /* simply relay the command */
- write(dst, rbuf, n);
- }
-
- *state = NONE;
- return n;
- } else {
- /* simply relay it */
- *state = NONE;
- write(dst, rbuf, n);
- return n;
- }
-
- bad:
- exit_failure("%s", strerror(errno));
- /*NOTREACHED*/
- return 0; /* to make gcc happy */
-}
diff --git a/usr.sbin/faithd/prefix.c b/usr.sbin/faithd/prefix.c
deleted file mode 100644
index 3ad8e58fa0a..00000000000
--- a/usr.sbin/faithd/prefix.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* $OpenBSD: prefix.c,v 1.7 2003/09/02 23:27:55 itojun Exp $ */
-/* $KAME: prefix.c,v 1.13 2003/09/02 22:50:17 itojun Exp $ */
-
-/*
- * Copyright (C) 2000 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#ifndef offsetof
-#define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member))
-#endif
-
-#include "faithd.h"
-#include "prefix.h"
-
-static int prefix_set(const char *, struct prefix *, int);
-static struct config *config_load1(const char *);
-#if 0
-static void config_show1(const struct config *);
-static void config_show(void);
-#endif
-
-struct config *config_list = NULL;
-const int niflags = NI_NUMERICHOST;
-
-static int
-prefix_set(const char *s, struct prefix *prefix, int slash)
-{
- char *p = NULL, *q, *r;
- struct addrinfo hints, *res = NULL;
- int max;
- char *a;
-
- p = strdup(s);
- if (!p)
- goto fail;
- q = strchr(p, '/');
- if (q) {
- if (!slash)
- goto fail;
- *q++ = '\0';
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(p, "0", &hints, &res))
- goto fail;
- if (res->ai_next || res->ai_addrlen > sizeof(prefix->a))
- goto fail;
- memcpy(&prefix->a, res->ai_addr, res->ai_addrlen);
-
- switch (prefix->a.ss_family) {
- case AF_INET:
- max = 32;
- a = (char *)&((struct sockaddr_in *)&prefix->a)->sin_addr;
- break;
- case AF_INET6:
- max = 128;
- a = (char *)&((struct sockaddr_in6 *)&prefix->a)->sin6_addr;
- break;
- default:
- a = NULL;
- max = -1;
- break;
- }
-
- if (q) {
- r = NULL;
- prefix->l = (int)strtoul(q, &r, 10);
- if (!*q || *r)
- goto fail;
- if (prefix->l < 0 || prefix->l > max)
- goto fail;
- } else
- prefix->l = max;
-
- if (p)
- free(p);
- if (res)
- freeaddrinfo(res);
- return 0;
-
-fail:
- if (p)
- free(p);
- if (res)
- freeaddrinfo(res);
- return -1;
-}
-
-const char *
-prefix_string(const struct prefix *prefix)
-{
- static char buf[NI_MAXHOST + 20];
- char hbuf[NI_MAXHOST];
-
- if (getnameinfo((const struct sockaddr *)&prefix->a, prefix->a.ss_len,
- hbuf, sizeof(hbuf), NULL, 0, niflags))
- return NULL;
- snprintf(buf, sizeof(buf), "%s/%d", hbuf, prefix->l);
- return buf;
-}
-
-int
-prefix_match(const struct prefix *prefix, const struct sockaddr *sa)
-{
- struct sockaddr_storage a, b;
- char *pa, *pb;
- int off, l;
-
- if (prefix->a.ss_family != sa->sa_family ||
- prefix->a.ss_len != sa->sa_len)
- return 0;
-
- if (prefix->a.ss_len > sizeof(a) || sa->sa_len > sizeof(b))
- return 0;
-
- switch (prefix->a.ss_family) {
- case AF_INET:
- off = offsetof(struct sockaddr_in, sin_addr);
- break;
- case AF_INET6:
- off = offsetof(struct sockaddr_in6, sin6_addr);
- break;
- default:
- if (memcmp(&prefix->a, sa, prefix->a.ss_len) != 0)
- return 0;
- else
- return 1;
- }
-
- memcpy(&a, &prefix->a, prefix->a.ss_len);
- memcpy(&b, sa, sa->sa_len);
- l = prefix->l / 8 + (prefix->l % 8 ? 1 : 0);
-
- /* overrun check */
- if (off + l > a.ss_len)
- return 0;
-
- pa = ((char *)&a) + off;
- pb = ((char *)&b) + off;
- if (prefix->l % 8) {
- pa[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
- pb[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
- }
- if (memcmp(pa, pb, l) != 0)
- return 0;
- else
- return 1;
-}
-
-/*
- * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr]
- * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
- */
-static struct config *
-config_load1(const char *line)
-{
- struct config *conf;
- char buf[BUFSIZ];
- char *p;
- char *token[4];
- int i;
-
- if (strlen(line) + 1 > sizeof(buf))
- return NULL;
- strlcpy(buf, line, sizeof(buf));
-
- p = strchr(buf, '\n');
- if (!p)
- return NULL;
- *p = '\0';
- p = strchr(buf, '#');
- if (p)
- *p = '\0';
- if (strlen(buf) == 0)
- return NULL;
-
- p = buf;
- memset(token, 0, sizeof(token));
- for (i = 0; i < sizeof(token) / sizeof(token[0]); i++) {
- token[i] = strtok(p, "\t ");
- p = NULL;
- if (token[i] == NULL)
- break;
- }
- /* extra tokens? */
- if (strtok(p, "\t ") != NULL)
- return NULL;
- /* insufficient tokens */
- switch (i) {
- case 3:
- case 4:
- break;
- default:
- return NULL;
- }
-
- conf = (struct config *)malloc(sizeof(*conf));
- if (conf == NULL)
- return NULL;
- memset(conf, 0, sizeof(*conf));
-
- if (strcasecmp(token[1], "permit") == 0)
- conf->permit = 1;
- else if (strcasecmp(token[1], "deny") == 0)
- conf->permit = 0;
- else {
- /* invalid keyword is considered as "deny" */
- conf->permit = 0;
- }
-
- if (prefix_set(token[0], &conf->match, 1) < 0)
- goto fail;
- if (prefix_set(token[2], &conf->dest, 1) < 0)
- goto fail;
- if (token[3]) {
- if (prefix_set(token[3], &conf->src, 0) < 0)
- goto fail;
- }
-
- return conf;
-
-fail:
- free(conf);
- return NULL;
-}
-
-int
-config_load(const char *configfile)
-{
- FILE *fp;
- char buf[BUFSIZ];
- struct config *conf, *p;
- struct config sentinel;
-
- config_list = NULL;
-
- if (!configfile)
- configfile = _PATH_PREFIX_CONF;
- fp = fopen(configfile, "r");
- if (fp == NULL)
- return -1;
-
- p = &sentinel;
- sentinel.next = NULL;
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- conf = config_load1(buf);
- if (conf) {
- p->next = conf;
- p = p->next;
- }
- }
- config_list = sentinel.next;
-
- fclose(fp);
- return 0;
-}
-
-#if 0
-static void
-config_show1(const struct config *conf)
-{
- const char *p;
-
- p = prefix_string(&conf->match);
- printf("%s", p ? p : "?");
-
- if (conf->permit)
- printf(" permit");
- else
- printf(" deny");
-
- p = prefix_string(&conf->dest);
- printf(" %s", p ? p : "?");
-
- printf("\n");
-}
-
-static void
-config_show()
-{
- struct config *conf;
-
- for (conf = config_list; conf; conf = conf->next)
- config_show1(conf);
-}
-#endif
-
-const struct config *
-config_match(struct sockaddr *sa1, struct sockaddr *sa2)
-{
- static struct config conf;
- const struct config *p;
-
- if (sa1->sa_len > sizeof(conf.match.a) ||
- sa2->sa_len > sizeof(conf.dest.a))
- return NULL;
-
- memset(&conf, 0, sizeof(conf));
- if (!config_list) {
- conf.permit = 1;
- memcpy(&conf.match.a, sa1, sa1->sa_len);
- memcpy(&conf.dest.a, sa2, sa2->sa_len);
- return &conf;
- }
-
- for (p = config_list; p; p = p->next)
- if (prefix_match(&p->match, sa1) && prefix_match(&p->dest, sa2))
- return p;
-
- return NULL;
-}
diff --git a/usr.sbin/faithd/prefix.h b/usr.sbin/faithd/prefix.h
deleted file mode 100644
index b8d930ea76c..00000000000
--- a/usr.sbin/faithd/prefix.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $OpenBSD: prefix.h,v 1.2 2002/02/16 21:28:02 millert Exp $ */
-/* $KAME: prefix.h,v 1.3 2000/11/19 11:45:38 itojun Exp $ */
-
-/*
- * Copyright (C) 2000 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-struct prefix {
- struct sockaddr_storage a;
- int l;
-};
-
-struct config {
- struct config *next;
-
- int permit;
- struct prefix match;
- struct prefix dest;
- struct prefix src; /* src to use for outgoing connection */
-};
-
-#define _PATH_PREFIX_CONF "/etc/faithd.conf"
-
-extern const char *prefix_string(const struct prefix *);
-extern int prefix_match(const struct prefix *, const struct sockaddr *);
-extern int config_load(const char *);
-extern const struct config *config_match(struct sockaddr *, struct sockaddr *);
diff --git a/usr.sbin/faithd/tcp.c b/usr.sbin/faithd/tcp.c
deleted file mode 100644
index 8982b63b474..00000000000
--- a/usr.sbin/faithd/tcp.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/* $OpenBSD: tcp.c,v 1.12 2002/09/08 01:20:15 itojun Exp $ */
-/* $KAME: tcp.c,v 1.10 2002/08/20 23:01:01 itojun Exp $ */
-
-/*
- * Copyright (C) 1997 and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include "faithd.h"
-
-static char tcpbuf[16*1024];
- /* bigger than MSS and may be lesser than window size */
-static int tblen, tboff, oob_exists;
-static fd_set readfds, writefds, exceptfds;
-static char atmark_buf[2];
-static pid_t cpid = (pid_t)0;
-static pid_t ppid = (pid_t)0;
-volatile time_t child_lastactive = (time_t)0;
-static time_t parent_lastactive = (time_t)0;
-
-static void sig_ctimeout(int);
-static void sig_child(int);
-static void notify_inactive(void);
-static void notify_active(void);
-static void send_data(int, int, const char *, int);
-static void relay(int, int, const char *, int);
-
-/*
- * Inactivity timer:
- * - child side (ppid != 0) will send SIGUSR1 to parent every (FAITH_TIMEOUT/4)
- * second if traffic is active. if traffic is inactive, don't send SIGUSR1.
- * - parent side (ppid == 0) will check the last SIGUSR1 it have seen.
- */
-static void
-sig_ctimeout(int sig)
-{
- int save_errno = errno;
- struct syslog_data sdata = SYSLOG_DATA_INIT;
-
- /* parent side: record notification from the child */
- if (dflag)
- syslog_r(LOG_DEBUG, &sdata, "activity timer from child");
- child_lastactive = time(NULL);
- errno = save_errno;
-}
-
-/* parent will terminate if child dies. */
-static void
-sig_child(int sig)
-{
- struct syslog_data sdata = SYSLOG_DATA_INIT;
- int status;
- pid_t pid;
-
- pid = wait3(&status, WNOHANG, (struct rusage *)0);
- if (pid > 0 && WEXITSTATUS(status))
- syslog_r(LOG_WARNING, &sdata,
- "child %ld exit status 0x%x", (long)pid, status);
- exit_success("terminate connection due to child termination");
-}
-
-static void
-notify_inactive()
-{
- time_t t;
-
- /* only on parent side... */
- if (ppid)
- return;
-
- /* parent side should check for timeout. */
- t = time(NULL);
- if (dflag) {
- syslog(LOG_DEBUG, "parent side %sactive, child side %sactive",
- (FAITH_TIMEOUT < t - parent_lastactive) ? "in" : "",
- (FAITH_TIMEOUT < t - child_lastactive) ? "in" : "");
- }
-
- if (FAITH_TIMEOUT < t - child_lastactive
- && FAITH_TIMEOUT < t - parent_lastactive) {
- /* both side timeouted */
- signal(SIGCHLD, SIG_DFL);
- kill(cpid, SIGTERM);
- wait(NULL);
- exit_failure("connection timeout");
- /* NOTREACHED */
- }
-}
-
-static void
-notify_active()
-{
- if (ppid) {
- /* child side: notify parent of active traffic */
- time_t t;
- t = time(NULL);
- if (FAITH_TIMEOUT / 4 < t - child_lastactive) {
- if (kill(ppid, SIGUSR1) < 0) {
- exit_failure("terminate connection due to parent termination");
- /* NOTREACHED */
- }
- child_lastactive = t;
- }
- } else {
- /* parent side */
- parent_lastactive = time(NULL);
- }
-}
-
-static void
-send_data(int s_rcv, int s_snd, const char *service, int direction)
-{
- int cc;
-
- if (oob_exists) {
- cc = send(s_snd, atmark_buf, 1, MSG_OOB);
- if (cc == -1)
- goto retry_or_err;
- oob_exists = 0;
- if (s_rcv >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_SET(s_rcv, &exceptfds);
- }
-
- for (; tboff < tblen; tboff += cc) {
- cc = write(s_snd, tcpbuf + tboff, tblen - tboff);
- if (cc < 0)
- goto retry_or_err;
- }
-#ifdef DEBUG
- if (tblen) {
- if (tblen >= sizeof(tcpbuf))
- tblen = sizeof(tcpbuf) - 1;
- tcpbuf[tblen] = '\0';
- syslog(LOG_DEBUG, "from %s (%dbytes): %s",
- direction == 1 ? "client" : "server", tblen, tcpbuf);
- }
-#endif /* DEBUG */
- tblen = 0; tboff = 0;
- if (s_snd >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_CLR(s_snd, &writefds);
- if (s_rcv >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_SET(s_rcv, &readfds);
- return;
- retry_or_err:
- if (errno != EAGAIN)
- exit_failure("writing relay data failed: %s", strerror(errno));
- if (s_snd >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_SET(s_snd, &writefds);
-}
-
-static void
-relay(int s_rcv, int s_snd, const char *service, int direction)
-{
- int atmark, error, maxfd;
- struct timeval tv;
- fd_set oreadfds, owritefds, oexceptfds;
-
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
- fcntl(s_snd, F_SETFD, O_NONBLOCK);
- oreadfds = readfds; owritefds = writefds; oexceptfds = exceptfds;
- if (s_rcv >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_SET(s_rcv, &readfds);
- FD_SET(s_rcv, &exceptfds);
- oob_exists = 0;
- maxfd = (s_rcv > s_snd) ? s_rcv : s_snd;
-
- for (;;) {
- tv.tv_sec = FAITH_TIMEOUT / 4;
- tv.tv_usec = 0;
- oreadfds = readfds;
- owritefds = writefds;
- oexceptfds = exceptfds;
- error = select(maxfd + 1, &readfds, &writefds, &exceptfds, &tv);
- if (error == -1) {
- if (errno == EINTR)
- continue;
- exit_failure("select: %s", strerror(errno));
- } else if (error == 0) {
- readfds = oreadfds;
- writefds = owritefds;
- exceptfds = oexceptfds;
- notify_inactive();
- continue;
- }
-
- /* activity notification */
- notify_active();
-
- if (FD_ISSET(s_rcv, &exceptfds)) {
- error = ioctl(s_rcv, SIOCATMARK, &atmark);
- if (error != -1 && atmark == 1) {
- int cc;
- oob_read_retry:
- cc = read(s_rcv, atmark_buf, 1);
- if (cc == 1) {
- if (s_rcv >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_CLR(s_rcv, &exceptfds);
- if (s_snd >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_SET(s_snd, &writefds);
- oob_exists = 1;
- } else if (cc == -1) {
- if (errno == EINTR)
- goto oob_read_retry;
- exit_failure("reading oob data failed"
- ": %s",
- strerror(errno));
- }
- }
- }
- if (FD_ISSET(s_rcv, &readfds)) {
- relaydata_read_retry:
- tblen = read(s_rcv, tcpbuf, sizeof(tcpbuf));
- tboff = 0;
-
- switch (tblen) {
- case -1:
- if (errno == EINTR)
- goto relaydata_read_retry;
- exit_failure("reading relay data failed: %s",
- strerror(errno));
- /* NOTREACHED */
- case 0:
- /* to close opposite-direction relay process */
- shutdown(s_snd, 0);
-
- close(s_rcv);
- close(s_snd);
- exit_success("terminating %s relay", service);
- /* NOTREACHED */
- default:
- if (s_rcv >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_CLR(s_rcv, &readfds);
- if (s_snd >= FD_SETSIZE)
- exit_failure("descriptor too big");
- FD_SET(s_snd, &writefds);
- break;
- }
- }
- if (FD_ISSET(s_snd, &writefds))
- send_data(s_rcv, s_snd, service, direction);
- }
-}
-
-void
-tcp_relay(int s_src, int s_dst, const char *service)
-{
- syslog(LOG_INFO, "starting %s relay", service);
-
- child_lastactive = parent_lastactive = time(NULL);
-
- cpid = fork();
- switch (cpid) {
- case -1:
- exit_failure("tcp_relay: can't fork grand child: %s",
- strerror(errno));
- /* NOTREACHED */
- case 0:
- /* child process: relay going traffic */
- ppid = getppid();
- /* this is child so reopen log */
- closelog();
- openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
- relay(s_src, s_dst, service, 1);
- /* NOTREACHED */
- default:
- /* parent process: relay coming traffic */
- ppid = (pid_t)0;
- signal(SIGUSR1, sig_ctimeout);
- signal(SIGCHLD, sig_child);
- relay(s_dst, s_src, service, 0);
- /* NOTREACHED */
- }
-}